{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gummy-field",
  "type": "registry:ui",
  "title": "Gummy Field",
  "description": "Accessible form composition that associates a Label, native or custom control, descriptions, and validation.",
  "registryDependencies": [
    "https://gummyui.dev/r/gummy-label.json",
    "https://gummyui.dev/r/gummy-form-styles.json"
  ],
  "files": [
    {
      "path": "components/ui/GummyField.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { GummyLabel } from \"./GummyLabel\";\n\ntype GummyFieldControlProps = {\n  id?: string;\n  className?: string;\n  required?: boolean;\n  disabled?: boolean;\n  readOnly?: boolean;\n  \"aria-describedby\"?: string;\n  \"aria-errormessage\"?: string;\n  \"aria-invalid\"?: React.AriaAttributes[\"aria-invalid\"];\n};\n\nexport type GummyFieldProps = Omit<\n  React.HTMLAttributes<HTMLDivElement>,\n  \"children\"\n> & {\n  /** One native or custom form control. Its accessibility props are composed. */\n  children: React.ReactElement<GummyFieldControlProps>;\n  /** Visible label associated to the child control. */\n  label: React.ReactNode;\n  description?: React.ReactNode;\n  errorMessage?: React.ReactNode;\n  successMessage?: React.ReactNode;\n  required?: boolean;\n  optional?: boolean;\n  disabled?: boolean;\n  readOnly?: boolean;\n  orientation?: \"vertical\" | \"horizontal\";\n  density?: \"default\" | \"compact\";\n  controlId?: 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\nexport const GummyField = React.forwardRef<HTMLDivElement, GummyFieldProps>(\n  function GummyField(\n    {\n      children,\n      label,\n      description,\n      errorMessage,\n      successMessage,\n      required = false,\n      optional = false,\n      disabled = false,\n      readOnly = false,\n      orientation = \"vertical\",\n      density = \"default\",\n      controlId: providedControlId,\n      className,\n      ...rootProps\n    },\n    ref,\n  ) {\n    const generatedId = React.useId().replace(/:/g, \"\");\n    const controlId =\n      providedControlId ?? children.props.id ?? `gummy-field-${generatedId}`;\n    const descriptionId = description ? `${controlId}-description` : undefined;\n    const errorId = errorMessage ? `${controlId}-error` : undefined;\n    const successId =\n      !errorMessage && successMessage ? `${controlId}-success` : undefined;\n    const status = errorMessage\n      ? \"error\"\n      : successMessage\n        ? \"success\"\n        : \"default\";\n    const control = React.cloneElement(children, {\n      id: controlId,\n      className: joinClassNames(\n        \"gummy-field__control\",\n        children.props.className,\n      ),\n      required: children.props.required ?? required,\n      disabled: children.props.disabled ?? disabled,\n      readOnly: children.props.readOnly ?? readOnly,\n      \"aria-describedby\": joinIds(\n        children.props[\"aria-describedby\"],\n        descriptionId,\n        errorId,\n        successId,\n      ),\n      \"aria-errormessage\":\n        children.props[\"aria-errormessage\"] ?? errorId,\n      \"aria-invalid\":\n        children.props[\"aria-invalid\"] ?? (errorMessage ? true : undefined),\n    });\n\n    return (\n      <div\n        {...rootProps}\n        ref={ref}\n        className={joinClassNames(\"gummy-field\", className)}\n        data-status={status}\n        data-disabled={disabled || undefined}\n        data-read-only={readOnly || undefined}\n        data-orientation={orientation}\n        data-density={density}\n      >\n        <GummyLabel\n          htmlFor={controlId}\n          required={required}\n          optional={optional}\n          disabled={disabled}\n          readOnly={readOnly}\n        >\n          {label}\n        </GummyLabel>\n        <div className=\"gummy-field__body\">\n          <div className=\"gummy-field__control-shell\">\n            <span className=\"gummy-field__pool\" aria-hidden=\"true\" />\n            {control}\n            {status !== \"default\" ? (\n              <span className=\"gummy-field__status\" aria-hidden=\"true\">\n                {status === \"error\" ? \"!\" : \"✓\"}\n              </span>\n            ) : null}\n          </div>\n          {description ? (\n            <p className=\"gummy-field__message\" id={descriptionId}>\n              {description}\n            </p>\n          ) : null}\n          {errorMessage ? (\n            <p\n              className=\"gummy-field__message gummy-field__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-field__message gummy-field__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      </div>\n    );\n  },\n);\n\nGummyField.displayName = \"GummyField\";\n"
    }
  ]
}
