{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "extends": "none",
  "name": "choice-box",
  "title": "choice-box",
  "description": "choice-box",
  "dependencies": [
    "react-aria-components",
    "cn",
    "tailwind-variants"
  ],
  "registryDependencies": [
    "https://intentui.com/r/primitive",
    "https://intentui.com/r/checkbox"
  ],
  "files": [
    {
      "path": "src/components/ui/choice-box.tsx",
      "content": "\"use client\"\n\nimport { createContext, use } from \"react\"\nimport type { GridListItemProps, GridListProps, TextProps } from \"react-aria-components\"\nimport { composeRenderProps, GridList, GridListItem, Text } from \"react-aria-components\"\nimport { cn } from \"cn\"\nimport type { VariantProps } from \"tailwind-variants\"\nimport { tv } from \"tailwind-variants\"\nimport { cx } from \"@/lib/primitive\"\nimport { Checkbox, CheckboxField } from \"./checkbox\"\n\nconst choiceBoxStyles = tv({\n  base: \"grid [--gutter:--spacing(4)]\",\n  variants: {\n    columns: {\n      1: \"col-span-full grid-cols-[auto_1fr]\",\n      2: \"sm:grid-cols-2\",\n      3: \"sm:grid-cols-3\",\n      4: \"sm:grid-cols-4\",\n      5: \"sm:grid-cols-5\",\n      6: \"sm:grid-cols-6\",\n    },\n    gap: {\n      0: \"gap-0\",\n      1: \"gap-1\",\n      2: \"gap-2\",\n      3: \"gap-3\",\n      4: \"gap-4\",\n      5: \"gap-5\",\n      6: \"gap-6\",\n      8: \"gap-8\",\n      10: \"gap-10\",\n      12: \"gap-12\",\n    },\n  },\n  defaultVariants: {\n    columns: 1,\n    gap: 0,\n  },\n  compoundVariants: [\n    {\n      gap: 0,\n      columns: 1,\n      className:\n        \"rounded-lg *:data-[slot=choice-box-item]:inset-ring *:data-[slot=choice-box-item]:-mt-px *:data-[slot=choice-box-item]:rounded-none *:data-[slot=choice-box-item]:last:rounded-b-[calc(var(--radius-lg)-1px)] *:data-[slot=choice-box-item]:first:rounded-t-[calc(var(--radius-lg)-1px)]\",\n    },\n  ],\n})\n\nconst ChoiceBoxContext = createContext<{ columns?: number; gap?: number; isReadOnly?: boolean }>({})\n\nconst useChoiceBoxContext = () => use(ChoiceBoxContext)\n\nexport interface ChoiceBoxProps<T extends object>\n  extends GridListProps<T>, VariantProps<typeof choiceBoxStyles> {\n  isReadOnly?: boolean\n}\n\nexport function ChoiceBox<T extends object>({\n  columns = 1,\n  gap = 0,\n  className,\n  selectionMode = \"single\",\n  isReadOnly,\n  ...props\n}: ChoiceBoxProps<T>) {\n  return (\n    <ChoiceBoxContext value={{ columns, gap, isReadOnly }}>\n      <GridList\n        data-slot=\"choice-box\"\n        layout={columns === 1 ? \"stack\" : \"grid\"}\n        selectionMode={selectionMode}\n        className={cx(\n          choiceBoxStyles({\n            columns,\n            gap,\n          }),\n          className\n        )}\n        {...props}\n      />\n    </ChoiceBoxContext>\n  )\n}\n\nconst choiceBoxItemStyles = tv({\n  base: [\n    \"group outline-hidden\",\n    \"[--choice-box-foreground:var(--color-primary-subtle-foreground)] [--choice-box:var(--color-primary-subtle)]\",\n    \"[--choice-box-selected-hovered:var(--color-primary-subtle)]/90\",\n    \"inset-ring inset-ring-border rounded-lg p-(--gutter) **:data-[slot=label]:font-medium\",\n    \"**:data-[slot=avatar]:row-span-2 **:data-[slot=avatar]:mt-0.5 **:data-[slot=avatar]:shrink-0\",\n    \"**:[svg]:row-span-2 **:[svg]:h-[1.1lh] **:[svg]:w-5 **:[svg]:shrink-0\",\n    \"has-[svg:not([data-slot=check-indicator])]:grid-cols-[auto_1fr_auto] has-data-[slot=avatar]:grid-cols-[auto_1fr_auto]\",\n    \"grid grid-cols-[1fr_auto] content-start items-start gap-x-[calc(var(--gutter)-(--spacing(1)))] gap-y-1\",\n    \"[--choice-box-active-ring:var(--color-ring)]/70 [--choice-box-ring:var(--color-ring)]/20\",\n    \"has-[[slot=description]]:**:data-[slot=label]:font-medium\",\n  ],\n  variants: {\n    isLink: {\n      true: \"cursor-pointer\",\n      false: \"cursor-default\",\n    },\n    isHovered: {\n      true: \"not-data-readonly:not-data-focus-visible:not-selected:inset-ring-muted-foreground/30\",\n    },\n    isFocused: {\n      true: \"inset-ring-(--choice-box-active-ring) ring-(--choice-box-ring) ring-3 invalid:ring-danger-subtle-foreground/20\",\n    },\n    isInvalid: { true: \"ring-3 ring-danger-subtle-foreground/20\" },\n    isOneColumn: {\n      true: \"col-span-full\",\n    },\n    isActive: {\n      true: [\n        \"bg-(--choice-box) text-(--choice-box-foreground)\",\n        \"inset-ring-(--choice-box-active-ring) z-20 hover:bg-(--choice-box-selected-hovered)\",\n        \"**:data-[slot=label]:text-(--choice-box-foreground)\",\n        \"**:[[slot=description]]:text-(--choice-box-foreground)\",\n      ],\n    },\n    isDisabled: {\n      true: \"z-10 opacity-50 **:data-[slot=label]:text-muted-foreground forced-colors:text-[GrayText] **:[[slot=description]]:text-muted-foreground/70\",\n    },\n  },\n})\n\nexport interface ChoiceBoxItemProps\n  extends GridListItemProps, VariantProps<typeof choiceBoxItemStyles> {\n  label?: string\n  description?: string\n}\n\nexport function ChoiceBoxItem({\n  className,\n  label,\n  description,\n  children,\n  ...props\n}: ChoiceBoxItemProps) {\n  const textValue = typeof children === \"string\" ? children : undefined\n  const { columns, isReadOnly } = useChoiceBoxContext()\n  return (\n    <GridListItem\n      textValue={textValue}\n      data-readonly={isReadOnly}\n      data-slot=\"choice-box-item\"\n      {...props}\n      className={composeRenderProps(\n        className,\n        (className, { isFocusVisible, isSelected, ...renderProps }) =>\n          choiceBoxItemStyles({\n            ...renderProps,\n            isOneColumn: columns === 1,\n            isLink: \"href\" in props,\n            isFocused: !isReadOnly && renderProps.isFocused,\n            isActive: (!isReadOnly && isSelected) || isFocusVisible,\n            className,\n          })\n      )}\n    >\n      {composeRenderProps(children, (children, { selectionMode }) => {\n        const isStringChild = typeof children === \"string\"\n        const hasCustomChildren = typeof children !== \"undefined\"\n\n        const content = hasCustomChildren ? (\n          isStringChild ? (\n            <ChoiceBoxLabel>{children}</ChoiceBoxLabel>\n          ) : (\n            children\n          )\n        ) : (\n          <>\n            {label && <ChoiceBoxLabel>{label}</ChoiceBoxLabel>}\n            {description && <ChoiceBoxDescription>{description}</ChoiceBoxDescription>}\n          </>\n        )\n        return (\n          <>\n            {content}\n            {selectionMode === \"multiple\" && (\n              <CheckboxField\n                slot=\"selection\"\n                className=\"gap-x-0 col-start-2 self-start group-has-[svg:not([data-slot=check-indicator])]:col-start-3 group-has-data-[slot=avatar]:col-start-3\"\n              >\n                <Checkbox className=\"col-span-1\" />\n              </CheckboxField>\n            )}\n          </>\n        )\n      })}\n    </GridListItem>\n  )\n}\n\nexport interface ChoiceBoxLabelProps extends TextProps {\n  ref?: React.Ref<HTMLDivElement>\n}\n\nexport function ChoiceBoxLabel({ className, ref, ...props }: ChoiceBoxLabelProps) {\n  return (\n    <Text\n      data-slot=\"label\"\n      ref={ref}\n      className={cn(\n        \"select-none text-base/6 text-foreground group-disabled:opacity-50 sm:text-sm/6\",\n        \"col-start-1 row-start-1\",\n        \"group-has-[svg:not([data-slot=check-indicator])]:col-start-2\",\n        \"group-has-data-[slot=avatar]:col-start-2\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport type ChoiceBoxDescriptionProps = ChoiceBoxLabelProps\n\nexport function ChoiceBoxDescription({ className, ref, ...props }: ChoiceBoxDescriptionProps) {\n  return (\n    <Text\n      slot=\"description\"\n      ref={ref}\n      className={cn(\n        \"col-start-1 row-start-2\",\n        \"group-has-[svg:not([data-slot=check-indicator])]:col-start-2\",\n        \"group-has-data-[slot=avatar]:col-start-2\",\n        \"text-base/6 text-muted-foreground sm:text-sm/6\",\n        \"group-disabled:opacity-50\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "cssVars": {
    "theme": {
      "color-primary-subtle": "var(--primary-subtle)",
      "color-primary-subtle-foreground": "var(--primary-subtle-foreground)",
      "color-danger-subtle-foreground": "var(--danger-subtle-foreground)"
    },
    "light": {
      "primary-subtle": "oklch(0.623 0.214 259.815 / 0.15)",
      "primary-subtle-foreground": "oklch(0.488 0.243 264.376)",
      "danger-subtle-foreground": "oklch(0.505 0.213 27.518)"
    },
    "dark": {
      "primary-subtle": "oklch(0.623 0.214 259.815 / 0.1)",
      "primary-subtle-foreground": "oklch(0.707 0.165 254.624)",
      "danger-subtle-foreground": "oklch(0.704 0.191 22.216)"
    }
  },
  "type": "registry:ui"
}