{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gummy-native-select",
  "type": "registry:ui",
  "title": "Gummy Native Select",
  "description": "Platform-native single Select with an attached chevron reservoir, validation, and focusable read-only behavior.",
  "registryDependencies": [
    "https://gummyui.dev/r/gummy-label.json",
    "https://gummyui.dev/r/gummy-form-styles.json"
  ],
  "files": [
    {
      "path": "components/ui/GummyNativeSelect.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { GummyLabel } from \"./GummyLabel\";\n\nexport type GummyNativeSelectProps = Omit<\n  React.SelectHTMLAttributes<HTMLSelectElement>,\n  \"children\" | \"multiple\" | \"size\"\n> & {\n  children: React.ReactNode;\n  label: React.ReactNode;\n  description?: React.ReactNode;\n  errorMessage?: React.ReactNode;\n  successMessage?: React.ReactNode;\n  optional?: boolean;\n  readOnly?: boolean;\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 GummyNativeSelect = React.forwardRef<\n  HTMLSelectElement,\n  GummyNativeSelectProps\n>(function GummyNativeSelect(\n  {\n    children,\n    label,\n    description,\n    errorMessage,\n    successMessage,\n    optional = false,\n    readOnly = false,\n    wrapperClassName,\n    className,\n    id: providedId,\n    required,\n    disabled,\n    value,\n    defaultValue,\n    onChange,\n    onKeyDown,\n    onPointerDown,\n    \"aria-describedby\": ariaDescribedBy,\n    \"aria-errormessage\": ariaErrorMessage,\n    \"aria-invalid\": ariaInvalid,\n    ...selectProps\n  },\n  forwardedRef,\n) {\n  const generatedId = React.useId().replace(/:/g, \"\");\n  const id = providedId ?? `gummy-native-select-${generatedId}`;\n  const descriptionId = description ? `${id}-description` : undefined;\n  const errorId = errorMessage ? `${id}-error` : undefined;\n  const successId =\n    !errorMessage && successMessage ? `${id}-success` : undefined;\n  const status = errorMessage\n    ? \"error\"\n    : successMessage\n      ? \"success\"\n      : \"default\";\n  const selectRef = React.useRef<HTMLSelectElement | null>(null);\n  const lastAcceptedValue = React.useRef<string>(\n    value === undefined\n      ? defaultValue === undefined\n        ? \"\"\n        : String(defaultValue)\n      : String(value),\n  );\n\n  React.useEffect(() => {\n    if (value !== undefined) lastAcceptedValue.current = String(value);\n  }, [value]);\n\n  return (\n    <div\n      className={joinClassNames(\"gummy-native-select\", wrapperClassName)}\n      data-status={status}\n      data-disabled={disabled || undefined}\n      data-read-only={readOnly || undefined}\n    >\n      <GummyLabel\n        htmlFor={id}\n        required={required}\n        optional={optional}\n        disabled={disabled}\n        readOnly={readOnly}\n      >\n        {label}\n      </GummyLabel>\n      <div className=\"gummy-native-select__shell\">\n        <span className=\"gummy-native-select__pool\" aria-hidden=\"true\" />\n        <select\n          {...selectProps}\n          ref={(node) => {\n            selectRef.current = node;\n            assignRef(forwardedRef, node);\n          }}\n          id={id}\n          className={joinClassNames(\"gummy-native-select__control\", className)}\n          required={required}\n          disabled={disabled}\n          value={value}\n          defaultValue={value === undefined ? defaultValue : undefined}\n          aria-readonly={readOnly || undefined}\n          aria-describedby={joinIds(\n            ariaDescribedBy,\n            descriptionId,\n            errorId,\n            successId,\n          )}\n          aria-errormessage={ariaErrorMessage ?? errorId}\n          aria-invalid={ariaInvalid ?? (errorMessage ? true : undefined)}\n          onPointerDown={(event) => {\n            if (readOnly) {\n              event.preventDefault();\n              event.currentTarget.focus();\n            }\n            onPointerDown?.(event);\n          }}\n          onKeyDown={(event) => {\n            if (\n              readOnly &&\n              [\n                \" \",\n                \"Enter\",\n                \"ArrowUp\",\n                \"ArrowDown\",\n                \"Home\",\n                \"End\",\n                \"PageUp\",\n                \"PageDown\",\n              ].includes(event.key)\n            ) {\n              event.preventDefault();\n            }\n            onKeyDown?.(event);\n          }}\n          onChange={(event) => {\n            if (readOnly) {\n              event.currentTarget.value = lastAcceptedValue.current;\n              return;\n            }\n            lastAcceptedValue.current = event.currentTarget.value;\n            onChange?.(event);\n          }}\n        >\n          {children}\n        </select>\n        <span className=\"gummy-native-select__chevron\" aria-hidden=\"true\">\n          <svg viewBox=\"0 0 16 10\" focusable=\"false\">\n            <path d=\"m2 2 6 6 6-6\" />\n          </svg>\n        </span>\n        {status !== \"default\" ? (\n          <span className=\"gummy-native-select__status\" aria-hidden=\"true\">\n            {status === \"error\" ? \"!\" : \"✓\"}\n          </span>\n        ) : null}\n      </div>\n      {description ? (\n        <p className=\"gummy-native-select__message\" id={descriptionId}>\n          {description}\n        </p>\n      ) : null}\n      {errorMessage ? (\n        <p\n          className=\"gummy-native-select__message gummy-native-select__message--error\"\n          id={errorId}\n          role=\"alert\"\n        >\n          <span className=\"gummy-form-message-mark\" aria-hidden=\"true\" />\n          <span>{errorMessage}</span>\n        </p>\n      ) : successId ? (\n        <p\n          className=\"gummy-native-select__message gummy-native-select__message--success\"\n          id={successId}\n        >\n          <span className=\"gummy-form-message-mark\" aria-hidden=\"true\" />\n          <span>{successMessage}</span>\n        </p>\n      ) : null}\n    </div>\n  );\n});\n\nGummyNativeSelect.displayName = \"GummyNativeSelect\";\n"
    }
  ]
}
