{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "flex",
  "type": "registry:ui",
  "title": "Flex",
  "description": "Lower-level flexbox layout primitive with FlexItem sizing controls, token-backed gaps, wrapping, alignment, and asChild composition.",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://components.dethink.co.uk/r/dethink-base.json"
  ],
  "files": [
    {
      "path": "packages/components/src/components/flex/flex.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/components/flex/flex.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 FlexElement =\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  | \"span\";\n\nexport type FlexDisplay = \"flex\" | \"inline-flex\";\nexport type FlexDirection = \"row\" | \"column\";\nexport type FlexWrap = \"nowrap\" | \"wrap\";\nexport type FlexGap =\n  \"none\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"8\" | \"10\" | \"12\";\nexport type FlexAlign = \"stretch\" | \"start\" | \"center\" | \"end\" | \"baseline\";\nexport type FlexJustify =\n  \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\";\nexport type FlexContent =\n  \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\" | \"stretch\";\n\nexport type FlexItemElement =\n  \"div\" | \"span\" | \"li\" | \"section\" | \"article\" | \"aside\";\nexport type FlexItemGrow = \"0\" | \"1\";\nexport type FlexItemShrink = \"0\" | \"1\";\nexport type FlexItemBasis = \"auto\" | \"0\" | \"full\" | \"xs\" | \"sm\" | \"md\" | \"lg\";\nexport type FlexItemAlign =\n  \"auto\" | \"stretch\" | \"start\" | \"center\" | \"end\" | \"baseline\";\nexport type FlexItemMinInlineSize = \"auto\" | \"0\";\n\ntype FlexBaseProps = {\n  align?: FlexAlign;\n  as?: FlexElement;\n  asChild?: boolean;\n  columnGap?: FlexGap;\n  content?: FlexContent;\n  direction?: FlexDirection;\n  display?: FlexDisplay;\n  gap?: FlexGap;\n  justify?: FlexJustify;\n  rowGap?: FlexGap;\n  wrap?: FlexWrap;\n};\n\ntype FlexItemBaseProps = {\n  align?: FlexItemAlign;\n  as?: FlexItemElement;\n  asChild?: boolean;\n  basis?: FlexItemBasis;\n  grow?: FlexItemGrow;\n  minInlineSize?: FlexItemMinInlineSize;\n  shrink?: FlexItemShrink;\n};\n\ntype FlexFormAttributes = Pick<\n  FormHTMLAttributes<HTMLFormElement>,\n  | \"acceptCharset\"\n  | \"action\"\n  | \"autoComplete\"\n  | \"encType\"\n  | \"method\"\n  | \"name\"\n  | \"noValidate\"\n  | \"target\"\n>;\n\ntype FlexFieldsetAttributes = Pick<\n  FieldsetHTMLAttributes<HTMLFieldSetElement>,\n  \"disabled\" | \"form\" | \"name\"\n>;\n\ntype NativeFlexProps = HTMLAttributes<HTMLElement> &\n  FlexFormAttributes &\n  FlexFieldsetAttributes &\n  FlexBaseProps & {\n    asChild?: false;\n    children?: ReactNode;\n  };\n\ntype ChildFlexProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> &\n  FlexBaseProps & {\n    asChild: true;\n    children: ReactElement<FlexSlotProps>;\n  };\n\nexport type FlexProps = NativeFlexProps | ChildFlexProps;\n\ntype NativeFlexItemProps = HTMLAttributes<HTMLElement> &\n  FlexItemBaseProps & {\n    asChild?: false;\n    children?: ReactNode;\n  };\n\ntype ChildFlexItemProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> &\n  FlexItemBaseProps & {\n    asChild: true;\n    children: ReactElement<FlexSlotProps>;\n  };\n\nexport type FlexItemProps = NativeFlexItemProps | ChildFlexItemProps;\n\ntype FlexSlotProps = Record<string, unknown> & {\n  children?: ReactNode;\n  className?: string;\n  ref?: Ref<HTMLElement>;\n};\n\ntype FlexElementWithRef = ReactElement<FlexSlotProps> & {\n  ref?: Ref<HTMLElement>;\n};\n\ntype EventHandler = (...args: unknown[]) => void;\n\nconst flexBaseClasses = \"box-border min-w-0\";\nconst flexItemBaseClasses = \"box-border\";\n\nconst flexDisplayClasses: Record<FlexDisplay, string> = {\n  flex: \"flex\",\n  \"inline-flex\": \"inline-flex\",\n};\n\nconst flexDirectionClasses: Record<FlexDirection, string> = {\n  row: \"flex-row\",\n  column: \"flex-col\",\n};\n\nconst flexWrapClasses: Record<FlexWrap, string> = {\n  nowrap: \"flex-nowrap\",\n  wrap: \"flex-wrap\",\n};\n\nconst flexGapClasses: Record<FlexGap, 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 flexRowGapClasses: Record<FlexGap, 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 flexColumnGapClasses: Record<FlexGap, 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 flexAlignClasses: Record<FlexAlign, string> = {\n  stretch: \"items-stretch\",\n  start: \"items-start\",\n  center: \"items-center\",\n  end: \"items-end\",\n  baseline: \"items-baseline\",\n};\n\nconst flexJustifyClasses: Record<FlexJustify, 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};\n\nconst flexContentClasses: Record<FlexContent, 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 flexItemGrowClasses: Record<FlexItemGrow, string> = {\n  0: \"grow-0\",\n  1: \"grow\",\n};\n\nconst flexItemShrinkClasses: Record<FlexItemShrink, string> = {\n  0: \"shrink-0\",\n  1: \"shrink\",\n};\n\nconst flexItemBasisClasses: Record<FlexItemBasis, string> = {\n  auto: \"basis-auto\",\n  0: \"basis-0\",\n  full: \"basis-full\",\n  xs: \"basis-32\",\n  sm: \"basis-48\",\n  md: \"basis-64\",\n  lg: \"basis-80\",\n};\n\nconst flexItemAlignClasses: Record<FlexItemAlign, string> = {\n  auto: \"self-auto\",\n  stretch: \"self-stretch\",\n  start: \"self-start\",\n  center: \"self-center\",\n  end: \"self-end\",\n  baseline: \"self-baseline\",\n};\n\nconst flexItemMinInlineSizeClasses: Record<\n  FlexItemMinInlineSize,\n  string | undefined\n> = {\n  auto: undefined,\n  0: \"min-w-0\",\n};\n\nexport function flexClassNames({\n  align = \"stretch\",\n  className,\n  columnGap,\n  content = \"stretch\",\n  direction = \"row\",\n  display = \"flex\",\n  gap = \"none\",\n  justify = \"start\",\n  rowGap,\n  wrap = \"nowrap\",\n}: Pick<\n  FlexProps,\n  | \"align\"\n  | \"className\"\n  | \"columnGap\"\n  | \"content\"\n  | \"direction\"\n  | \"display\"\n  | \"gap\"\n  | \"justify\"\n  | \"rowGap\"\n  | \"wrap\"\n> = {}) {\n  return cn(\n    flexBaseClasses,\n    flexDisplayClasses[display],\n    flexDirectionClasses[direction],\n    flexWrapClasses[wrap],\n    flexGapClasses[gap],\n    rowGap ? flexRowGapClasses[rowGap] : undefined,\n    columnGap ? flexColumnGapClasses[columnGap] : undefined,\n    flexAlignClasses[align],\n    flexJustifyClasses[justify],\n    flexContentClasses[content],\n    className,\n  );\n}\n\nexport function flexItemClassNames({\n  align = \"auto\",\n  basis = \"auto\",\n  className,\n  grow,\n  minInlineSize = \"auto\",\n  shrink,\n}: Pick<\n  FlexItemProps,\n  \"align\" | \"basis\" | \"className\" | \"grow\" | \"minInlineSize\" | \"shrink\"\n> = {}) {\n  return cn(\n    flexItemBaseClasses,\n    grow ? flexItemGrowClasses[grow] : undefined,\n    shrink ? flexItemShrinkClasses[shrink] : undefined,\n    flexItemBasisClasses[basis],\n    flexItemAlignClasses[align],\n    flexItemMinInlineSizeClasses[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<FlexSlotProps>) {\n  if (\"ref\" in child.props) {\n    return child.props.ref;\n  }\n\n  return reactVersion.startsWith(\"18.\")\n    ? (child as FlexElementWithRef).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: FlexSlotProps,\n) {\n  const composedProps: FlexSlotProps = {\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 getFlexDataAttributes({\n  align,\n  as,\n  asChild,\n  columnGap,\n  content,\n  direction,\n  display,\n  gap,\n  justify,\n  rowGap,\n  wrap,\n}: Pick<\n  FlexProps,\n  | \"align\"\n  | \"as\"\n  | \"asChild\"\n  | \"columnGap\"\n  | \"content\"\n  | \"direction\"\n  | \"display\"\n  | \"gap\"\n  | \"justify\"\n  | \"rowGap\"\n  | \"wrap\"\n>) {\n  return {\n    \"data-slot\": \"flex\",\n    \"data-as-child\": asChild ? \"true\" : undefined,\n    \"data-element\": asChild ? undefined : as,\n    \"data-display\": display,\n    \"data-direction\": direction,\n    \"data-wrap\": wrap,\n    \"data-gap\": gap,\n    \"data-row-gap\": rowGap,\n    \"data-column-gap\": columnGap,\n    \"data-align\": align,\n    \"data-justify\": justify,\n    \"data-content\": content,\n  };\n}\n\nfunction getFlexItemDataAttributes({\n  align,\n  as,\n  asChild,\n  basis,\n  grow,\n  minInlineSize,\n  shrink,\n}: Pick<\n  FlexItemProps,\n  \"align\" | \"as\" | \"asChild\" | \"basis\" | \"grow\" | \"minInlineSize\" | \"shrink\"\n>) {\n  return {\n    \"data-slot\": \"flex-item\",\n    \"data-as-child\": asChild ? \"true\" : undefined,\n    \"data-element\": asChild ? undefined : as,\n    \"data-grow\": grow,\n    \"data-shrink\": shrink,\n    \"data-basis\": basis,\n    \"data-align\": align,\n    \"data-min-inline-size\": minInlineSize,\n  };\n}\n\nexport const Flex = forwardRef<HTMLElement, FlexProps>(\n  (\n    {\n      align = \"stretch\",\n      as = \"div\",\n      asChild = false,\n      children,\n      className,\n      columnGap,\n      content = \"stretch\",\n      direction = \"row\",\n      display = \"flex\",\n      gap = \"none\",\n      justify = \"start\",\n      rowGap,\n      wrap = \"nowrap\",\n      ...props\n    },\n    ref,\n  ) => {\n    const classes = flexClassNames({\n      align,\n      className,\n      columnGap,\n      content,\n      direction,\n      display,\n      gap,\n      justify,\n      rowGap,\n      wrap,\n    });\n    const dataAttributes = getFlexDataAttributes({\n      align,\n      as,\n      asChild,\n      columnGap,\n      content,\n      direction,\n      display,\n      gap,\n      justify,\n      rowGap,\n      wrap,\n    });\n\n    if (asChild) {\n      const child = Children.only(children);\n\n      if (!isValidElement<FlexSlotProps>(child)) {\n        throw new Error(\n          \"Flex 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\nFlex.displayName = \"Flex\";\n\nexport const FlexItem = forwardRef<HTMLElement, FlexItemProps>(\n  (\n    {\n      align = \"auto\",\n      as = \"div\",\n      asChild = false,\n      basis = \"auto\",\n      children,\n      className,\n      grow,\n      minInlineSize = \"auto\",\n      shrink,\n      ...props\n    },\n    ref,\n  ) => {\n    const classes = flexItemClassNames({\n      align,\n      basis,\n      className,\n      grow,\n      minInlineSize,\n      shrink,\n    });\n    const dataAttributes = getFlexItemDataAttributes({\n      align,\n      as,\n      asChild,\n      basis,\n      grow,\n      minInlineSize,\n      shrink,\n    });\n\n    if (asChild) {\n      const child = Children.only(children);\n\n      if (!isValidElement<FlexSlotProps>(child)) {\n        throw new Error(\n          \"FlexItem 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\nFlexItem.displayName = \"FlexItem\";\n"
    },
    {
      "path": "packages/components/src/components/flex/index.ts",
      "type": "registry:file",
      "target": "~/components/dethink/components/flex/index.ts",
      "content": "export {\n  Flex,\n  FlexItem,\n  flexClassNames,\n  flexItemClassNames,\n  type FlexAlign,\n  type FlexContent,\n  type FlexDirection,\n  type FlexDisplay,\n  type FlexElement,\n  type FlexGap,\n  type FlexItemAlign,\n  type FlexItemBasis,\n  type FlexItemElement,\n  type FlexItemGrow,\n  type FlexItemMinInlineSize,\n  type FlexItemProps,\n  type FlexItemShrink,\n  type FlexJustify,\n  type FlexProps,\n  type FlexWrap,\n} from \"./flex\";\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"
    }
  ]
}
