{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gummy-checkbox",
  "type": "registry:ui",
  "title": "Gummy Checkbox",
  "description": "Native Checkbox with a 44px target, mixed state, validation, and focusable read-only behavior.",
  "registryDependencies": [
    "https://gummyui.dev/r/gummy-form-styles.json"
  ],
  "files": [
    {
      "path": "components/ui/GummyCheckbox.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nexport type GummyCheckboxProps = Omit<\n  React.InputHTMLAttributes<HTMLInputElement>,\n  \"children\" | \"size\" | \"type\"\n> & {\n  label: React.ReactNode;\n  description?: React.ReactNode;\n  errorMessage?: React.ReactNode;\n  indeterminate?: boolean;\n  readOnly?: boolean;\n  onCheckedChange?: (checked: boolean | \"indeterminate\") => void;\n  wrapperClassName?: string;\n};\n\nfunction joinClassNames(...values: Array<string | false | null | undefined>) {\n  return values.filter(Boolean).join(\" \");\n}\n\nfunction joinIds(...values: Array<string | undefined>) {\n  return values.filter(Boolean).join(\" \") || undefined;\n}\n\nfunction assignRef<T>(ref: React.ForwardedRef<T>, value: T | null) {\n  if (typeof ref === \"function\") ref(value);\n  else if (ref) ref.current = value;\n}\n\nexport const GummyCheckbox = React.forwardRef<\n  HTMLInputElement,\n  GummyCheckboxProps\n>(function GummyCheckbox(\n  {\n    label,\n    description,\n    errorMessage,\n    indeterminate = false,\n    readOnly = false,\n    onCheckedChange,\n    wrapperClassName,\n    className,\n    id: providedId,\n    disabled,\n    required,\n    checked,\n    defaultChecked,\n    onChange,\n    onClick,\n    onKeyDown,\n    \"aria-describedby\": ariaDescribedBy,\n    \"aria-invalid\": ariaInvalid,\n    ...inputProps\n  },\n  forwardedRef,\n) {\n  const generatedId = React.useId().replace(/:/g, \"\");\n  const id = providedId ?? `gummy-checkbox-${generatedId}`;\n  const titleId = `${id}-label`;\n  const descriptionId = description ? `${id}-description` : undefined;\n  const errorId = errorMessage ? `${id}-error` : undefined;\n  const inputRef = React.useRef<HTMLInputElement | null>(null);\n  const [uncontrolledChecked, setUncontrolledChecked] = React.useState(\n    Boolean(defaultChecked),\n  );\n  const renderedChecked =\n    checked === undefined ? uncontrolledChecked : Boolean(checked);\n\n  React.useEffect(() => {\n    if (inputRef.current) inputRef.current.indeterminate = indeterminate;\n  }, [indeterminate]);\n\n  return (\n    <div\n      className={joinClassNames(\"gummy-checkbox\", wrapperClassName)}\n      data-disabled={disabled || undefined}\n      data-read-only={readOnly || undefined}\n      data-invalid={Boolean(errorMessage) || undefined}\n      data-indeterminate={indeterminate || undefined}\n    >\n      <label className=\"gummy-checkbox__label\" htmlFor={id}>\n        <span className=\"gummy-checkbox__target\">\n          <input\n            {...inputProps}\n            ref={(node) => {\n              inputRef.current = node;\n              assignRef(forwardedRef, node);\n            }}\n            id={id}\n            type=\"checkbox\"\n            className={joinClassNames(\"gummy-checkbox__input\", className)}\n            checked={renderedChecked}\n            disabled={disabled}\n            required={required}\n            aria-readonly={readOnly || undefined}\n            aria-checked={indeterminate ? \"mixed\" : undefined}\n            aria-labelledby={titleId}\n            aria-describedby={joinIds(ariaDescribedBy, descriptionId, errorId)}\n            aria-invalid={ariaInvalid ?? (errorMessage ? true : undefined)}\n            onClick={(event) => {\n              if (readOnly) {\n                event.preventDefault();\n                event.currentTarget.checked = renderedChecked;\n                queueMicrotask(() => {\n                  if (inputRef.current) {\n                    inputRef.current.checked = renderedChecked;\n                  }\n                });\n              }\n              onClick?.(event);\n            }}\n            onKeyDown={(event) => {\n              if (readOnly && (event.key === \" \" || event.key === \"Enter\")) {\n                event.preventDefault();\n              }\n              onKeyDown?.(event);\n            }}\n            onChange={(event) => {\n              if (!readOnly) {\n                if (checked === undefined) {\n                  setUncontrolledChecked(event.currentTarget.checked);\n                }\n                onCheckedChange?.(event.currentTarget.checked);\n                onChange?.(event);\n              } else {\n                event.currentTarget.checked = renderedChecked;\n                queueMicrotask(() => {\n                  if (inputRef.current) {\n                    inputRef.current.checked = renderedChecked;\n                  }\n                });\n              }\n            }}\n          />\n          <span className=\"gummy-checkbox__indicator\" aria-hidden=\"true\">\n            <span className=\"gummy-checkbox__pool\" />\n            <svg viewBox=\"0 0 18 14\" focusable=\"false\">\n              <path d=\"M2 7.4 6.7 12 16 2\" />\n            </svg>\n            <span className=\"gummy-checkbox__mixed\" />\n          </span>\n        </span>\n        <span className=\"gummy-checkbox__copy\">\n          <span className=\"gummy-checkbox__title\" id={titleId}>\n            {label}\n            {required ? (\n              <span className=\"gummy-checkbox__required\" aria-hidden=\"true\">\n                Required\n              </span>\n            ) : null}\n            {readOnly ? (\n              <span className=\"gummy-checkbox__read-only\" aria-hidden=\"true\">\n                Read only\n              </span>\n            ) : null}\n          </span>\n          {description ? (\n            <span className=\"gummy-checkbox__description\" id={descriptionId}>\n              {description}\n            </span>\n          ) : null}\n          {errorMessage ? (\n            <span\n              className=\"gummy-checkbox__error\"\n              id={errorId}\n              role=\"alert\"\n            >\n              <span className=\"gummy-form-message-mark\" aria-hidden=\"true\" />\n              <span>{errorMessage}</span>\n            </span>\n          ) : null}\n        </span>\n      </label>\n    </div>\n  );\n});\n\nGummyCheckbox.displayName = \"GummyCheckbox\";\n"
    }
  ]
}
