{
  "name": "checkbox",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "checkbox.tsx",
      "content": "\"use client\";\r\n\r\nimport { css, themeVars as theme } from \"@yugnex/core\";\r\nimport { useControllableState } from \"@yugnex/core/client\";\r\nimport { forwardRef, useEffect, useRef, type InputHTMLAttributes } from \"react\";\r\n\r\ntype CheckedState = boolean | \"indeterminate\";\r\n\r\nconst boxClass = css({\r\n  position: \"relative\",\r\n  display: \"inline-flex\",\r\n  alignItems: \"center\",\r\n  justifyContent: \"center\",\r\n  width: \"1.125rem\",\r\n  height: \"1.125rem\",\r\n  borderRadius: theme.radius.sm,\r\n  border: `1px solid ${theme.color.input}`,\r\n  backgroundColor: theme.color.background,\r\n  cursor: \"pointer\",\r\n  flexShrink: 0,\r\n  transitionProperty: \"background-color, border-color\",\r\n  transitionDuration: theme.duration.fast,\r\n  transitionTimingFunction: theme.easing.standard,\r\n  '&[data-state=\"checked\"], &[data-state=\"indeterminate\"]': {\r\n    backgroundColor: theme.color.primary,\r\n    borderColor: theme.color.primary,\r\n  },\r\n  \"&:has(:focus-visible)\": {\r\n    outline: `2px solid ${theme.color.ring}`,\r\n    outlineOffset: \"2px\",\r\n  },\r\n  '&[data-disabled=\"true\"]': {\r\n    opacity: 0.5,\r\n    cursor: \"not-allowed\",\r\n  },\r\n});\r\n\r\nconst inputClass = css({\r\n  position: \"absolute\",\r\n  inset: 0,\r\n  width: \"100%\",\r\n  height: \"100%\",\r\n  margin: 0,\r\n  opacity: 0,\r\n});\r\n\r\nconst iconClass = css({\r\n  color: \"#ffffff\",\r\n  width: \"0.75rem\",\r\n  height: \"0.75rem\",\r\n});\r\n\r\nexport interface CheckboxProps\r\n  extends Omit<InputHTMLAttributes<HTMLInputElement>, \"checked\" | \"defaultChecked\" | \"onChange\" | \"type\"> {\r\n  checked?: CheckedState;\r\n  defaultChecked?: CheckedState;\r\n  onCheckedChange?: (checked: CheckedState) => void;\r\n}\r\n\r\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\r\n  { checked, defaultChecked = false, onCheckedChange, className, disabled, id, ...props },\r\n  ref,\r\n) {\r\n  const [state, setState] = useControllableState<CheckedState>({\r\n    value: checked,\r\n    defaultValue: defaultChecked,\r\n    onChange: onCheckedChange,\r\n  });\r\n\r\n  const inputRef = useRef<HTMLInputElement | null>(null);\r\n\r\n  useEffect(() => {\r\n    if (inputRef.current) inputRef.current.indeterminate = state === \"indeterminate\";\r\n  }, [state]);\r\n\r\n  const dataState = state === \"indeterminate\" ? \"indeterminate\" : state ? \"checked\" : \"unchecked\";\r\n\r\n  return (\r\n    <span\r\n      className={className ? `${boxClass} ${className}` : boxClass}\r\n      data-state={dataState}\r\n      data-disabled={disabled ? \"true\" : undefined}\r\n    >\r\n      <input\r\n        ref={(node) => {\r\n          inputRef.current = node;\r\n          if (typeof ref === \"function\") ref(node);\r\n          else if (ref) ref.current = node;\r\n        }}\r\n        id={id}\r\n        type=\"checkbox\"\r\n        className={inputClass}\r\n        checked={state === true}\r\n        disabled={disabled}\r\n        onChange={(event) => setState(event.target.checked)}\r\n        {...props}\r\n      />\r\n      {state === \"indeterminate\" ? (\r\n        <svg viewBox=\"0 0 12 12\" className={iconClass} fill=\"none\" aria-hidden=\"true\">\r\n          <path d=\"M2.5 6H9.5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\r\n        </svg>\r\n      ) : state ? (\r\n        <svg viewBox=\"0 0 12 12\" className={iconClass} fill=\"none\" aria-hidden=\"true\">\r\n          <path\r\n            d=\"M2.5 6.5L4.75 8.75L9.5 3.5\"\r\n            stroke=\"currentColor\"\r\n            strokeWidth=\"2\"\r\n            strokeLinecap=\"round\"\r\n            strokeLinejoin=\"round\"\r\n          />\r\n        </svg>\r\n      ) : null}\r\n    </span>\r\n  );\r\n});\r\n",
      "type": "registry:component"
    }
  ]
}