{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "grid",
  "type": "registry:ui",
  "title": "Grid",
  "description": "Two-dimensional layout primitive with GridItem spans, token-backed gaps, fixed and auto-fit columns, alignment, and asChild composition.",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://components.dethink.co.uk/r/dethink-base.json"
  ],
  "files": [
    {
      "path": "packages/components/src/components/grid/grid.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/components/grid/grid.tsx",
      "content": "import {\n  Children,\n  cloneElement,\n  createElement,\n  forwardRef,\n  isValidElement,\n  version as reactVersion,\n  type FieldsetHTMLAttributes,\n  type FormHTMLAttributes,\n  type ForwardedRef,\n  type HTMLAttributes,\n  type ReactElement,\n  type ReactNode,\n  type Ref,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type GridElement =\n  | \"div\"\n  | \"section\"\n  | \"article\"\n  | \"main\"\n  | \"aside\"\n  | \"nav\"\n  | \"header\"\n  | \"footer\"\n  | \"ul\"\n  | \"ol\"\n  | \"li\"\n  | \"form\"\n  | \"fieldset\";\n\nexport type GridColumns =\n  | \"1\"\n  | \"2\"\n  | \"3\"\n  | \"4\"\n  | \"5\"\n  | \"6\"\n  | \"12\"\n  | \"auto-fit-xs\"\n  | \"auto-fit-sm\"\n  | \"auto-fit-md\"\n  | \"auto-fit-lg\";\n\nexport type GridRows = \"none\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\nexport type GridGap =\n  \"none\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"8\" | \"10\" | \"12\";\nexport type GridAlign = \"stretch\" | \"start\" | \"center\" | \"end\";\nexport type GridJustify = \"stretch\" | \"start\" | \"center\" | \"end\";\nexport type GridContent =\n  \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\" | \"stretch\";\n\nexport type GridItemElement =\n  \"div\" | \"span\" | \"li\" | \"section\" | \"article\" | \"aside\";\nexport type GridItemSpan = \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"full\";\nexport type GridItemAlign = \"auto\" | \"stretch\" | \"start\" | \"center\" | \"end\";\nexport type GridItemJustify = \"auto\" | \"stretch\" | \"start\" | \"center\" | \"end\";\nexport type GridItemMinInlineSize = \"auto\" | \"0\";\n\ntype GridBaseProps = {\n  align?: GridAlign;\n  alignContent?: GridContent;\n  as?: GridElement;\n  asChild?: boolean;\n  columnGap?: GridGap;\n  columns?: GridColumns;\n  gap?: GridGap;\n  justify?: GridJustify;\n  justifyContent?: GridContent;\n  rowGap?: GridGap;\n  rows?: GridRows;\n};\n\ntype GridItemBaseProps = {\n  align?: GridItemAlign;\n  as?: GridItemElement;\n  asChild?: boolean;\n  colSpan?: GridItemSpan;\n  justify?: GridItemJustify;\n  minInlineSize?: GridItemMinInlineSize;\n  rowSpan?: GridItemSpan;\n};\n\ntype GridFormAttributes = Pick<\n  FormHTMLAttributes<HTMLFormElement>,\n  | \"acceptCharset\"\n  | \"action\"\n  | \"autoComplete\"\n  | \"encType\"\n  | \"method\"\n  | \"name\"\n  | \"noValidate\"\n  | \"target\"\n>;\n\ntype GridFieldsetAttributes = Pick<\n  FieldsetHTMLAttributes<HTMLFieldSetElement>,\n  \"disabled\" | \"form\" | \"name\"\n>;\n\ntype NativeGridProps = HTMLAttributes<HTMLElement> &\n  GridFormAttributes &\n  GridFieldsetAttributes &\n  GridBaseProps & {\n    asChild?: false;\n    children?: ReactNode;\n  };\n\ntype ChildGridProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> &\n  GridBaseProps & {\n    asChild: true;\n    children: ReactElement<GridSlotProps>;\n  };\n\nexport type GridProps = NativeGridProps | ChildGridProps;\n\ntype NativeGridItemProps = HTMLAttributes<HTMLElement> &\n  GridItemBaseProps & {\n    asChild?: false;\n    children?: ReactNode;\n  };\n\ntype ChildGridItemProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> &\n  GridItemBaseProps & {\n    asChild: true;\n    children: ReactElement<GridSlotProps>;\n  };\n\nexport type GridItemProps = NativeGridItemProps | ChildGridItemProps;\n\ntype GridSlotProps = Record<string, unknown> & {\n  children?: ReactNode;\n  className?: string;\n  ref?: Ref<HTMLElement>;\n};\n\ntype GridElementWithRef = ReactElement<GridSlotProps> & {\n  ref?: Ref<HTMLElement>;\n};\n\ntype EventHandler = (...args: unknown[]) => void;\n\nconst gridBaseClasses = \"box-border grid min-w-0\";\nconst gridItemBaseClasses = \"box-border\";\n\nconst gridColumnClasses: Record<GridColumns, string> = {\n  1: \"grid-cols-1\",\n  2: \"grid-cols-2\",\n  3: \"grid-cols-3\",\n  4: \"grid-cols-4\",\n  5: \"grid-cols-5\",\n  6: \"grid-cols-6\",\n  12: \"grid-cols-12\",\n  \"auto-fit-xs\": \"grid-cols-[repeat(auto-fit,minmax(min(12rem,100%),1fr))]\",\n  \"auto-fit-sm\": \"grid-cols-[repeat(auto-fit,minmax(min(16rem,100%),1fr))]\",\n  \"auto-fit-md\": \"grid-cols-[repeat(auto-fit,minmax(min(20rem,100%),1fr))]\",\n  \"auto-fit-lg\": \"grid-cols-[repeat(auto-fit,minmax(min(24rem,100%),1fr))]\",\n};\n\nconst gridRowClasses: Record<GridRows, string | undefined> = {\n  none: undefined,\n  1: \"grid-rows-1\",\n  2: \"grid-rows-2\",\n  3: \"grid-rows-3\",\n  4: \"grid-rows-4\",\n  5: \"grid-rows-5\",\n  6: \"grid-rows-6\",\n};\n\nconst gridGapClasses: Record<GridGap, string> = {\n  none: \"gap-[var(--dt-space-0)]\",\n  1: \"gap-[var(--dt-space-1)]\",\n  2: \"gap-[var(--dt-space-2)]\",\n  3: \"gap-[var(--dt-space-3)]\",\n  4: \"gap-[var(--dt-space-4)]\",\n  5: \"gap-[var(--dt-space-5)]\",\n  6: \"gap-[var(--dt-space-6)]\",\n  8: \"gap-[var(--dt-space-8)]\",\n  10: \"gap-[var(--dt-space-10)]\",\n  12: \"gap-[var(--dt-space-12)]\",\n};\n\nconst gridRowGapClasses: Record<GridGap, string> = {\n  none: \"gap-y-[var(--dt-space-0)]\",\n  1: \"gap-y-[var(--dt-space-1)]\",\n  2: \"gap-y-[var(--dt-space-2)]\",\n  3: \"gap-y-[var(--dt-space-3)]\",\n  4: \"gap-y-[var(--dt-space-4)]\",\n  5: \"gap-y-[var(--dt-space-5)]\",\n  6: \"gap-y-[var(--dt-space-6)]\",\n  8: \"gap-y-[var(--dt-space-8)]\",\n  10: \"gap-y-[var(--dt-space-10)]\",\n  12: \"gap-y-[var(--dt-space-12)]\",\n};\n\nconst gridColumnGapClasses: Record<GridGap, string> = {\n  none: \"gap-x-[var(--dt-space-0)]\",\n  1: \"gap-x-[var(--dt-space-1)]\",\n  2: \"gap-x-[var(--dt-space-2)]\",\n  3: \"gap-x-[var(--dt-space-3)]\",\n  4: \"gap-x-[var(--dt-space-4)]\",\n  5: \"gap-x-[var(--dt-space-5)]\",\n  6: \"gap-x-[var(--dt-space-6)]\",\n  8: \"gap-x-[var(--dt-space-8)]\",\n  10: \"gap-x-[var(--dt-space-10)]\",\n  12: \"gap-x-[var(--dt-space-12)]\",\n};\n\nconst gridAlignClasses: Record<GridAlign, string> = {\n  stretch: \"items-stretch\",\n  start: \"items-start\",\n  center: \"items-center\",\n  end: \"items-end\",\n};\n\nconst gridJustifyClasses: Record<GridJustify, string> = {\n  stretch: \"justify-items-stretch\",\n  start: \"justify-items-start\",\n  center: \"justify-items-center\",\n  end: \"justify-items-end\",\n};\n\nconst gridAlignContentClasses: Record<GridContent, string> = {\n  start: \"content-start\",\n  center: \"content-center\",\n  end: \"content-end\",\n  between: \"content-between\",\n  around: \"content-around\",\n  evenly: \"content-evenly\",\n  stretch: \"content-stretch\",\n};\n\nconst gridJustifyContentClasses: Record<GridContent, string> = {\n  start: \"justify-start\",\n  center: \"justify-center\",\n  end: \"justify-end\",\n  between: \"justify-between\",\n  around: \"justify-around\",\n  evenly: \"justify-evenly\",\n  stretch: \"justify-stretch\",\n};\n\nconst gridItemColSpanClasses: Record<GridItemSpan, string> = {\n  1: \"col-span-1\",\n  2: \"col-span-2\",\n  3: \"col-span-3\",\n  4: \"col-span-4\",\n  5: \"col-span-5\",\n  6: \"col-span-6\",\n  full: \"col-span-full\",\n};\n\nconst gridItemRowSpanClasses: Record<GridItemSpan, string> = {\n  1: \"row-span-1\",\n  2: \"row-span-2\",\n  3: \"row-span-3\",\n  4: \"row-span-4\",\n  5: \"row-span-5\",\n  6: \"row-span-6\",\n  full: \"row-span-full\",\n};\n\nconst gridItemAlignClasses: Record<GridItemAlign, string> = {\n  auto: \"self-auto\",\n  stretch: \"self-stretch\",\n  start: \"self-start\",\n  center: \"self-center\",\n  end: \"self-end\",\n};\n\nconst gridItemJustifyClasses: Record<GridItemJustify, string> = {\n  auto: \"justify-self-auto\",\n  stretch: \"justify-self-stretch\",\n  start: \"justify-self-start\",\n  center: \"justify-self-center\",\n  end: \"justify-self-end\",\n};\n\nconst gridItemMinInlineSizeClasses: Record<\n  GridItemMinInlineSize,\n  string | undefined\n> = {\n  auto: undefined,\n  0: \"min-w-0\",\n};\n\nexport function gridClassNames({\n  align = \"stretch\",\n  alignContent = \"start\",\n  className,\n  columnGap,\n  columns = \"1\",\n  gap = \"none\",\n  justify = \"stretch\",\n  justifyContent = \"start\",\n  rowGap,\n  rows = \"none\",\n}: Pick<\n  GridProps,\n  | \"align\"\n  | \"alignContent\"\n  | \"className\"\n  | \"columnGap\"\n  | \"columns\"\n  | \"gap\"\n  | \"justify\"\n  | \"justifyContent\"\n  | \"rowGap\"\n  | \"rows\"\n> = {}) {\n  return cn(\n    gridBaseClasses,\n    gridColumnClasses[columns],\n    gridRowClasses[rows],\n    gridGapClasses[gap],\n    rowGap ? gridRowGapClasses[rowGap] : undefined,\n    columnGap ? gridColumnGapClasses[columnGap] : undefined,\n    gridAlignClasses[align],\n    gridJustifyClasses[justify],\n    gridAlignContentClasses[alignContent],\n    gridJustifyContentClasses[justifyContent],\n    className,\n  );\n}\n\nexport function gridItemClassNames({\n  align = \"auto\",\n  className,\n  colSpan = \"1\",\n  justify = \"auto\",\n  minInlineSize = \"auto\",\n  rowSpan = \"1\",\n}: Pick<\n  GridItemProps,\n  \"align\" | \"className\" | \"colSpan\" | \"justify\" | \"minInlineSize\" | \"rowSpan\"\n> = {}) {\n  return cn(\n    gridItemBaseClasses,\n    gridItemColSpanClasses[colSpan],\n    gridItemRowSpanClasses[rowSpan],\n    gridItemAlignClasses[align],\n    gridItemJustifyClasses[justify],\n    gridItemMinInlineSizeClasses[minInlineSize],\n    className,\n  );\n}\n\nfunction setRef<T>(ref: Ref<T> | undefined, node: T | null) {\n  if (typeof ref === \"function\") {\n    ref(node);\n    return;\n  }\n\n  if (ref) {\n    ref.current = node;\n  }\n}\n\nfunction composeRefs<T>(...refs: Array<Ref<T> | undefined>) {\n  return (node: T | null) => {\n    for (const ref of refs) {\n      setRef(ref, node);\n    }\n  };\n}\n\nfunction getChildRef(child: ReactElement<GridSlotProps>) {\n  if (\"ref\" in child.props) {\n    return child.props.ref;\n  }\n\n  return reactVersion.startsWith(\"18.\")\n    ? (child as GridElementWithRef).ref\n    : undefined;\n}\n\nfunction isEventHandler(key: string, value: unknown): value is EventHandler {\n  return /^on[A-Z]/.test(key) && typeof value === \"function\";\n}\n\nfunction isDefaultPreventedEvent(\n  event: unknown,\n): event is { defaultPrevented: boolean } {\n  return (\n    typeof event === \"object\" &&\n    event !== null &&\n    \"defaultPrevented\" in event &&\n    event.defaultPrevented === true\n  );\n}\n\nfunction composeEventHandlers(\n  componentHandler: EventHandler,\n  childHandler: EventHandler,\n): EventHandler {\n  return (...args) => {\n    componentHandler(...args);\n\n    if (!isDefaultPreventedEvent(args[0])) {\n      childHandler(...args);\n    }\n  };\n}\n\nfunction composeSlotProps(\n  componentProps: Record<string, unknown>,\n  childProps: GridSlotProps,\n) {\n  const composedProps: GridSlotProps = {\n    ...componentProps,\n    ...childProps,\n  };\n\n  for (const [key, componentValue] of Object.entries(componentProps)) {\n    const childValue = childProps[key];\n\n    if (\n      isEventHandler(key, componentValue) &&\n      isEventHandler(key, childValue)\n    ) {\n      composedProps[key] = composeEventHandlers(componentValue, childValue);\n    }\n  }\n\n  return composedProps;\n}\n\nfunction getGridDataAttributes({\n  align,\n  alignContent,\n  as,\n  asChild,\n  columnGap,\n  columns,\n  gap,\n  justify,\n  justifyContent,\n  rowGap,\n  rows,\n}: Pick<\n  GridProps,\n  | \"align\"\n  | \"alignContent\"\n  | \"as\"\n  | \"asChild\"\n  | \"columnGap\"\n  | \"columns\"\n  | \"gap\"\n  | \"justify\"\n  | \"justifyContent\"\n  | \"rowGap\"\n  | \"rows\"\n>) {\n  return {\n    \"data-slot\": \"grid\",\n    \"data-as-child\": asChild ? \"true\" : undefined,\n    \"data-element\": asChild ? undefined : as,\n    \"data-columns\": columns,\n    \"data-rows\": rows,\n    \"data-gap\": gap,\n    \"data-row-gap\": rowGap,\n    \"data-column-gap\": columnGap,\n    \"data-align\": align,\n    \"data-justify\": justify,\n    \"data-align-content\": alignContent,\n    \"data-justify-content\": justifyContent,\n  };\n}\n\nfunction getGridItemDataAttributes({\n  align,\n  as,\n  asChild,\n  colSpan,\n  justify,\n  minInlineSize,\n  rowSpan,\n}: Pick<\n  GridItemProps,\n  | \"align\"\n  | \"as\"\n  | \"asChild\"\n  | \"colSpan\"\n  | \"justify\"\n  | \"minInlineSize\"\n  | \"rowSpan\"\n>) {\n  return {\n    \"data-slot\": \"grid-item\",\n    \"data-as-child\": asChild ? \"true\" : undefined,\n    \"data-element\": asChild ? undefined : as,\n    \"data-col-span\": colSpan,\n    \"data-row-span\": rowSpan,\n    \"data-align\": align,\n    \"data-justify\": justify,\n    \"data-min-inline-size\": minInlineSize,\n  };\n}\n\nexport const Grid = forwardRef<HTMLElement, GridProps>(\n  (\n    {\n      align = \"stretch\",\n      alignContent = \"start\",\n      as = \"div\",\n      asChild = false,\n      children,\n      className,\n      columnGap,\n      columns = \"1\",\n      gap = \"none\",\n      justify = \"stretch\",\n      justifyContent = \"start\",\n      rowGap,\n      rows = \"none\",\n      ...props\n    },\n    ref,\n  ) => {\n    const classes = gridClassNames({\n      align,\n      alignContent,\n      className,\n      columnGap,\n      columns,\n      gap,\n      justify,\n      justifyContent,\n      rowGap,\n      rows,\n    });\n    const dataAttributes = getGridDataAttributes({\n      align,\n      alignContent,\n      as,\n      asChild,\n      columnGap,\n      columns,\n      gap,\n      justify,\n      justifyContent,\n      rowGap,\n      rows,\n    });\n\n    if (asChild) {\n      const child = Children.only(children);\n\n      if (!isValidElement<GridSlotProps>(child)) {\n        throw new Error(\n          \"Grid with asChild expects a single React element child.\",\n        );\n      }\n\n      const childRef = getChildRef(child);\n      const composedProps = composeSlotProps(props, child.props);\n\n      return cloneElement(child, {\n        ...composedProps,\n        ...dataAttributes,\n        ref: composeRefs(ref as Ref<HTMLElement>, childRef),\n        className: cn(classes, child.props.className),\n      });\n    }\n\n    return createElement(\n      as,\n      {\n        ...props,\n        ...dataAttributes,\n        ref: ref as ForwardedRef<HTMLElement>,\n        className: classes,\n      },\n      children,\n    );\n  },\n);\n\nGrid.displayName = \"Grid\";\n\nexport const GridItem = forwardRef<HTMLElement, GridItemProps>(\n  (\n    {\n      align = \"auto\",\n      as = \"div\",\n      asChild = false,\n      children,\n      className,\n      colSpan = \"1\",\n      justify = \"auto\",\n      minInlineSize = \"auto\",\n      rowSpan = \"1\",\n      ...props\n    },\n    ref,\n  ) => {\n    const classes = gridItemClassNames({\n      align,\n      className,\n      colSpan,\n      justify,\n      minInlineSize,\n      rowSpan,\n    });\n    const dataAttributes = getGridItemDataAttributes({\n      align,\n      as,\n      asChild,\n      colSpan,\n      justify,\n      minInlineSize,\n      rowSpan,\n    });\n\n    if (asChild) {\n      const child = Children.only(children);\n\n      if (!isValidElement<GridSlotProps>(child)) {\n        throw new Error(\n          \"GridItem with asChild expects a single React element child.\",\n        );\n      }\n\n      const childRef = getChildRef(child);\n      const composedProps = composeSlotProps(props, child.props);\n\n      return cloneElement(child, {\n        ...composedProps,\n        ...dataAttributes,\n        ref: composeRefs(ref as Ref<HTMLElement>, childRef),\n        className: cn(classes, child.props.className),\n      });\n    }\n\n    return createElement(\n      as,\n      {\n        ...props,\n        ...dataAttributes,\n        ref: ref as ForwardedRef<HTMLElement>,\n        className: classes,\n      },\n      children,\n    );\n  },\n);\n\nGridItem.displayName = \"GridItem\";\n"
    },
    {
      "path": "packages/components/src/components/grid/index.ts",
      "type": "registry:file",
      "target": "~/components/dethink/components/grid/index.ts",
      "content": "export {\n  Grid,\n  GridItem,\n  gridClassNames,\n  gridItemClassNames,\n  type GridAlign,\n  type GridColumns,\n  type GridContent,\n  type GridElement,\n  type GridGap,\n  type GridItemAlign,\n  type GridItemElement,\n  type GridItemJustify,\n  type GridItemMinInlineSize,\n  type GridItemProps,\n  type GridItemSpan,\n  type GridJustify,\n  type GridProps,\n  type GridRows,\n} from \"./grid\";\n"
    },
    {
      "path": "packages/components/src/utils/cn.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/cn.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"
    }
  ]
}
