@gerege-systems/ui 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +234 -0
  3. package/dist-lib/__tests__/helpers/color.d.ts +9 -0
  4. package/dist-lib/__tests__/helpers/theme.d.ts +18 -0
  5. package/dist-lib/components/ui/Accordion.d.ts +21 -0
  6. package/dist-lib/components/ui/Accordion.js +71 -0
  7. package/dist-lib/components/ui/Accordion.js.map +1 -0
  8. package/dist-lib/components/ui/Alert.d.ts +51 -0
  9. package/dist-lib/components/ui/Alert.js +79 -0
  10. package/dist-lib/components/ui/Alert.js.map +1 -0
  11. package/dist-lib/components/ui/Avatar.d.ts +52 -0
  12. package/dist-lib/components/ui/Avatar.js +94 -0
  13. package/dist-lib/components/ui/Avatar.js.map +1 -0
  14. package/dist-lib/components/ui/Badge.d.ts +26 -0
  15. package/dist-lib/components/ui/Badge.js +76 -0
  16. package/dist-lib/components/ui/Badge.js.map +1 -0
  17. package/dist-lib/components/ui/Breadcrumbs.d.ts +33 -0
  18. package/dist-lib/components/ui/Breadcrumbs.js +52 -0
  19. package/dist-lib/components/ui/Breadcrumbs.js.map +1 -0
  20. package/dist-lib/components/ui/Button.d.ts +52 -0
  21. package/dist-lib/components/ui/Button.js +131 -0
  22. package/dist-lib/components/ui/Button.js.map +1 -0
  23. package/dist-lib/components/ui/Calendar.d.ts +15 -0
  24. package/dist-lib/components/ui/Calendar.js +139 -0
  25. package/dist-lib/components/ui/Calendar.js.map +1 -0
  26. package/dist-lib/components/ui/Card.d.ts +39 -0
  27. package/dist-lib/components/ui/Card.js +97 -0
  28. package/dist-lib/components/ui/Card.js.map +1 -0
  29. package/dist-lib/components/ui/Carousel.d.ts +27 -0
  30. package/dist-lib/components/ui/Carousel.js +174 -0
  31. package/dist-lib/components/ui/Carousel.js.map +1 -0
  32. package/dist-lib/components/ui/Chart.d.ts +87 -0
  33. package/dist-lib/components/ui/Chart.js +487 -0
  34. package/dist-lib/components/ui/Chart.js.map +1 -0
  35. package/dist-lib/components/ui/Checkbox.d.ts +28 -0
  36. package/dist-lib/components/ui/Checkbox.js +70 -0
  37. package/dist-lib/components/ui/Checkbox.js.map +1 -0
  38. package/dist-lib/components/ui/Combobox.d.ts +67 -0
  39. package/dist-lib/components/ui/Combobox.js +195 -0
  40. package/dist-lib/components/ui/Combobox.js.map +1 -0
  41. package/dist-lib/components/ui/CommandPalette.d.ts +112 -0
  42. package/dist-lib/components/ui/CommandPalette.js +179 -0
  43. package/dist-lib/components/ui/CommandPalette.js.map +1 -0
  44. package/dist-lib/components/ui/ContextMenu.d.ts +50 -0
  45. package/dist-lib/components/ui/ContextMenu.js +165 -0
  46. package/dist-lib/components/ui/ContextMenu.js.map +1 -0
  47. package/dist-lib/components/ui/DataGrid.d.ts +79 -0
  48. package/dist-lib/components/ui/DataGrid.js +99 -0
  49. package/dist-lib/components/ui/DataGrid.js.map +1 -0
  50. package/dist-lib/components/ui/DatePicker.d.ts +45 -0
  51. package/dist-lib/components/ui/DatePicker.js +193 -0
  52. package/dist-lib/components/ui/DatePicker.js.map +1 -0
  53. package/dist-lib/components/ui/DesignSystemProvider.d.ts +147 -0
  54. package/dist-lib/components/ui/DesignSystemProvider.js +135 -0
  55. package/dist-lib/components/ui/DesignSystemProvider.js.map +1 -0
  56. package/dist-lib/components/ui/Dialog.d.ts +77 -0
  57. package/dist-lib/components/ui/Dialog.js +165 -0
  58. package/dist-lib/components/ui/Dialog.js.map +1 -0
  59. package/dist-lib/components/ui/Drawer.d.ts +44 -0
  60. package/dist-lib/components/ui/Drawer.js +132 -0
  61. package/dist-lib/components/ui/Drawer.js.map +1 -0
  62. package/dist-lib/components/ui/DropdownMenu.d.ts +47 -0
  63. package/dist-lib/components/ui/DropdownMenu.js +169 -0
  64. package/dist-lib/components/ui/DropdownMenu.js.map +1 -0
  65. package/dist-lib/components/ui/EmptyState.d.ts +48 -0
  66. package/dist-lib/components/ui/EmptyState.js +46 -0
  67. package/dist-lib/components/ui/EmptyState.js.map +1 -0
  68. package/dist-lib/components/ui/ErrorState.d.ts +51 -0
  69. package/dist-lib/components/ui/ErrorState.js +69 -0
  70. package/dist-lib/components/ui/ErrorState.js.map +1 -0
  71. package/dist-lib/components/ui/FileUpload.d.ts +26 -0
  72. package/dist-lib/components/ui/FileUpload.js +111 -0
  73. package/dist-lib/components/ui/FileUpload.js.map +1 -0
  74. package/dist-lib/components/ui/Form.d.ts +36 -0
  75. package/dist-lib/components/ui/Form.js +131 -0
  76. package/dist-lib/components/ui/Form.js.map +1 -0
  77. package/dist-lib/components/ui/Icon.d.ts +34 -0
  78. package/dist-lib/components/ui/Icon.js +32 -0
  79. package/dist-lib/components/ui/Icon.js.map +1 -0
  80. package/dist-lib/components/ui/IconButton.d.ts +34 -0
  81. package/dist-lib/components/ui/IconButton.js +64 -0
  82. package/dist-lib/components/ui/IconButton.js.map +1 -0
  83. package/dist-lib/components/ui/Input.d.ts +54 -0
  84. package/dist-lib/components/ui/Input.js +158 -0
  85. package/dist-lib/components/ui/Input.js.map +1 -0
  86. package/dist-lib/components/ui/Kbd.d.ts +16 -0
  87. package/dist-lib/components/ui/Kbd.js +24 -0
  88. package/dist-lib/components/ui/Kbd.js.map +1 -0
  89. package/dist-lib/components/ui/MultiSelect.d.ts +64 -0
  90. package/dist-lib/components/ui/MultiSelect.js +210 -0
  91. package/dist-lib/components/ui/MultiSelect.js.map +1 -0
  92. package/dist-lib/components/ui/Pagination.d.ts +55 -0
  93. package/dist-lib/components/ui/Pagination.js +153 -0
  94. package/dist-lib/components/ui/Pagination.js.map +1 -0
  95. package/dist-lib/components/ui/Popover.d.ts +16 -0
  96. package/dist-lib/components/ui/Popover.js +35 -0
  97. package/dist-lib/components/ui/Popover.js.map +1 -0
  98. package/dist-lib/components/ui/Progress.d.ts +40 -0
  99. package/dist-lib/components/ui/Progress.js +100 -0
  100. package/dist-lib/components/ui/Progress.js.map +1 -0
  101. package/dist-lib/components/ui/RadioGroup.d.ts +27 -0
  102. package/dist-lib/components/ui/RadioGroup.js +81 -0
  103. package/dist-lib/components/ui/RadioGroup.js.map +1 -0
  104. package/dist-lib/components/ui/RelativeTime.d.ts +19 -0
  105. package/dist-lib/components/ui/RelativeTime.js +31 -0
  106. package/dist-lib/components/ui/RelativeTime.js.map +1 -0
  107. package/dist-lib/components/ui/ScrollArea.d.ts +21 -0
  108. package/dist-lib/components/ui/ScrollArea.js +60 -0
  109. package/dist-lib/components/ui/ScrollArea.js.map +1 -0
  110. package/dist-lib/components/ui/Select.d.ts +61 -0
  111. package/dist-lib/components/ui/Select.js +139 -0
  112. package/dist-lib/components/ui/Select.js.map +1 -0
  113. package/dist-lib/components/ui/Separator.d.ts +13 -0
  114. package/dist-lib/components/ui/Separator.js +26 -0
  115. package/dist-lib/components/ui/Separator.js.map +1 -0
  116. package/dist-lib/components/ui/Sheet.d.ts +55 -0
  117. package/dist-lib/components/ui/Sheet.js +136 -0
  118. package/dist-lib/components/ui/Sheet.js.map +1 -0
  119. package/dist-lib/components/ui/Sidebar.d.ts +91 -0
  120. package/dist-lib/components/ui/Sidebar.js +212 -0
  121. package/dist-lib/components/ui/Sidebar.js.map +1 -0
  122. package/dist-lib/components/ui/Skeleton.d.ts +37 -0
  123. package/dist-lib/components/ui/Skeleton.js +29 -0
  124. package/dist-lib/components/ui/Skeleton.js.map +1 -0
  125. package/dist-lib/components/ui/Slider.d.ts +33 -0
  126. package/dist-lib/components/ui/Slider.js +64 -0
  127. package/dist-lib/components/ui/Slider.js.map +1 -0
  128. package/dist-lib/components/ui/Snackbar.d.ts +21 -0
  129. package/dist-lib/components/ui/Snackbar.js +57 -0
  130. package/dist-lib/components/ui/Snackbar.js.map +1 -0
  131. package/dist-lib/components/ui/Spinner.d.ts +23 -0
  132. package/dist-lib/components/ui/Spinner.js +54 -0
  133. package/dist-lib/components/ui/Spinner.js.map +1 -0
  134. package/dist-lib/components/ui/Stepper.d.ts +40 -0
  135. package/dist-lib/components/ui/Stepper.js +111 -0
  136. package/dist-lib/components/ui/Stepper.js.map +1 -0
  137. package/dist-lib/components/ui/Switch.d.ts +33 -0
  138. package/dist-lib/components/ui/Switch.js +80 -0
  139. package/dist-lib/components/ui/Switch.js.map +1 -0
  140. package/dist-lib/components/ui/Table.d.ts +71 -0
  141. package/dist-lib/components/ui/Table.js +179 -0
  142. package/dist-lib/components/ui/Table.js.map +1 -0
  143. package/dist-lib/components/ui/Tabs.d.ts +32 -0
  144. package/dist-lib/components/ui/Tabs.js +91 -0
  145. package/dist-lib/components/ui/Tabs.js.map +1 -0
  146. package/dist-lib/components/ui/TagInput.d.ts +39 -0
  147. package/dist-lib/components/ui/TagInput.js +111 -0
  148. package/dist-lib/components/ui/TagInput.js.map +1 -0
  149. package/dist-lib/components/ui/Textarea.d.ts +34 -0
  150. package/dist-lib/components/ui/Textarea.js +88 -0
  151. package/dist-lib/components/ui/Textarea.js.map +1 -0
  152. package/dist-lib/components/ui/Timeline.d.ts +33 -0
  153. package/dist-lib/components/ui/Timeline.js +56 -0
  154. package/dist-lib/components/ui/Timeline.js.map +1 -0
  155. package/dist-lib/components/ui/Toast.d.ts +53 -0
  156. package/dist-lib/components/ui/Toast.js +158 -0
  157. package/dist-lib/components/ui/Toast.js.map +1 -0
  158. package/dist-lib/components/ui/Tooltip.d.ts +38 -0
  159. package/dist-lib/components/ui/Tooltip.js +60 -0
  160. package/dist-lib/components/ui/Tooltip.js.map +1 -0
  161. package/dist-lib/components/ui/TopNav.d.ts +37 -0
  162. package/dist-lib/components/ui/TopNav.js +69 -0
  163. package/dist-lib/components/ui/TopNav.js.map +1 -0
  164. package/dist-lib/components/ui/Tree.d.ts +51 -0
  165. package/dist-lib/components/ui/Tree.js +170 -0
  166. package/dist-lib/components/ui/Tree.js.map +1 -0
  167. package/dist-lib/hooks/use-debounce.d.ts +19 -0
  168. package/dist-lib/hooks/use-debounce.js +36 -0
  169. package/dist-lib/hooks/use-debounce.js.map +1 -0
  170. package/dist-lib/hooks/use-delayed-loading.d.ts +21 -0
  171. package/dist-lib/hooks/use-delayed-loading.js +20 -0
  172. package/dist-lib/hooks/use-delayed-loading.js.map +1 -0
  173. package/dist-lib/hooks/use-field-ids.d.ts +30 -0
  174. package/dist-lib/hooks/use-field-ids.js +18 -0
  175. package/dist-lib/hooks/use-field-ids.js.map +1 -0
  176. package/dist-lib/hooks/use-media-query.d.ts +11 -0
  177. package/dist-lib/hooks/use-media-query.js +22 -0
  178. package/dist-lib/hooks/use-media-query.js.map +1 -0
  179. package/dist-lib/hooks/use-modifier-key.d.ts +13 -0
  180. package/dist-lib/hooks/use-modifier-key.js +19 -0
  181. package/dist-lib/hooks/use-modifier-key.js.map +1 -0
  182. package/dist-lib/hooks/use-strings.d.ts +5 -0
  183. package/dist-lib/hooks/use-strings.js +12 -0
  184. package/dist-lib/hooks/use-strings.js.map +1 -0
  185. package/dist-lib/hooks/use-toast.d.ts +48 -0
  186. package/dist-lib/hooks/use-toast.js +67 -0
  187. package/dist-lib/hooks/use-toast.js.map +1 -0
  188. package/dist-lib/icon.d.ts +8 -0
  189. package/dist-lib/icon.js +7 -0
  190. package/dist-lib/icon.js.map +1 -0
  191. package/dist-lib/icons/index.d.ts +80 -0
  192. package/dist-lib/icons/index.js +163 -0
  193. package/dist-lib/icons/index.js.map +1 -0
  194. package/dist-lib/illustrations/index.d.ts +10 -0
  195. package/dist-lib/illustrations/index.js +114 -0
  196. package/dist-lib/illustrations/index.js.map +1 -0
  197. package/dist-lib/index.d.ts +68 -0
  198. package/dist-lib/index.js +291 -0
  199. package/dist-lib/index.js.map +1 -0
  200. package/dist-lib/lib/cva.d.ts +6 -0
  201. package/dist-lib/lib/format.d.ts +65 -0
  202. package/dist-lib/lib/format.js +95 -0
  203. package/dist-lib/lib/format.js.map +1 -0
  204. package/dist-lib/lib/return-focus.d.ts +11 -0
  205. package/dist-lib/lib/return-focus.js +12 -0
  206. package/dist-lib/lib/return-focus.js.map +1 -0
  207. package/dist-lib/lib/strings.d.ts +190 -0
  208. package/dist-lib/lib/strings.js +141 -0
  209. package/dist-lib/lib/strings.js.map +1 -0
  210. package/dist-lib/lib/strings.mn.d.ts +3 -0
  211. package/dist-lib/lib/strings.mn.js +115 -0
  212. package/dist-lib/lib/strings.mn.js.map +1 -0
  213. package/dist-lib/lib/utils.d.ts +11 -0
  214. package/dist-lib/lib/utils.js +10 -0
  215. package/dist-lib/lib/utils.js.map +1 -0
  216. package/dist-lib/styles.css +1 -0
  217. package/dist-lib/theme.css +840 -0
  218. package/package.json +158 -0
@@ -0,0 +1,70 @@
1
+ "use client";
2
+ import { jsxs as s, jsx as e } from "react/jsx-runtime";
3
+ import { forwardRef as N, useId as y } from "react";
4
+ import * as m from "@radix-ui/react-checkbox";
5
+ import { Minus as j, Check as C } from "../../icons/index.js";
6
+ import { cn as o } from "../../lib/utils.js";
7
+ const I = N(
8
+ function({
9
+ className: u,
10
+ label: c,
11
+ description: a,
12
+ error: t,
13
+ hideLabel: b,
14
+ id: x,
15
+ disabled: n,
16
+ "aria-describedby": h,
17
+ "aria-invalid": i,
18
+ ...d
19
+ }, g) {
20
+ const v = y(), r = x ?? v, l = a ? `${r}-desc` : void 0, f = t ? `${r}-error` : void 0, k = [f, l, h].filter(Boolean).join(" ") || void 0, p = !!t || i === !0 || i === "true";
21
+ return /* @__PURE__ */ s("div", { className: o("flex flex-col gap-1", u), children: [
22
+ /* @__PURE__ */ s("div", { className: "flex items-start gap-2.5", children: [
23
+ /* @__PURE__ */ e(
24
+ m.Root,
25
+ {
26
+ ref: g,
27
+ id: r,
28
+ disabled: n,
29
+ "aria-describedby": k,
30
+ "aria-invalid": p ? !0 : i,
31
+ className: o(
32
+ "peer relative mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-sm border",
33
+ // WCAG 2.5.8: 16px visual box, ≥24px hit area via an invisible inset halo.
34
+ 'before:absolute before:-inset-1.5 before:content-[""]',
35
+ "transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out)]",
36
+ "focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
37
+ "data-[state=checked]:bg-accent data-[state=checked]:border-accent data-[state=checked]:text-on-accent",
38
+ "data-[state=indeterminate]:bg-accent data-[state=indeterminate]:border-accent data-[state=indeterminate]:text-on-accent",
39
+ "disabled:cursor-not-allowed disabled:opacity-50",
40
+ "border-border-input aria-invalid:border-danger"
41
+ ),
42
+ ...d,
43
+ children: /* @__PURE__ */ e(m.Indicator, { className: "flex items-center justify-center", children: d.checked === "indeterminate" ? /* @__PURE__ */ e(j, { className: "size-3", "aria-hidden": !0, strokeWidth: 3 }) : /* @__PURE__ */ e(C, { className: "size-3", "aria-hidden": !0, strokeWidth: 3 }) })
44
+ }
45
+ ),
46
+ c && /* @__PURE__ */ s("div", { className: "flex flex-col gap-0.5", children: [
47
+ /* @__PURE__ */ e(
48
+ "label",
49
+ {
50
+ htmlFor: r,
51
+ className: o(
52
+ "text-foreground text-sm select-none",
53
+ n && "cursor-not-allowed opacity-50",
54
+ b && "sr-only"
55
+ ),
56
+ children: c
57
+ }
58
+ ),
59
+ a && /* @__PURE__ */ e("p", { id: l, className: "text-foreground-subtle text-xs", children: a })
60
+ ] })
61
+ ] }),
62
+ t && /* @__PURE__ */ e("p", { id: f, className: "text-danger-text text-xs", children: t })
63
+ ] });
64
+ }
65
+ );
66
+ I.displayName = "Checkbox";
67
+ export {
68
+ I as Checkbox
69
+ };
70
+ //# sourceMappingURL=Checkbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Checkbox.js","sources":["../../../src/components/ui/Checkbox.tsx"],"sourcesContent":["'use client';\n\nimport {\n forwardRef,\n useId,\n type ComponentPropsWithoutRef,\n type ElementRef,\n type ReactNode,\n} from 'react';\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox';\nimport { Check, Minus } from '@/icons';\nimport { cn } from '@/lib/utils';\n\nexport interface CheckboxProps extends Omit<\n ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>,\n 'asChild'\n> {\n /** Visible label rendered to the right of the box. */\n label?: ReactNode;\n /** Secondary description rendered below the label. */\n description?: ReactNode;\n /** Validation error message. */\n error?: ReactNode;\n /** Hide the label visually while keeping it in the a11y tree. */\n hideLabel?: boolean;\n}\n\n/**\n * Checkbox with optional inline label + description. Pass `checked=\"indeterminate\"`\n * for the indeterminate state — Radix renders a `Minus` icon automatically.\n *\n * @example Single\n * <Checkbox label=\"I agree to the terms\" checked={ok} onCheckedChange={setOk} />\n *\n * @example Tri-state header\n * <Checkbox aria-label=\"Select all\"\n * checked={allSelected ? true : someSelected ? 'indeterminate' : false}\n * onCheckedChange={toggleAll} />\n *\n * @do Use indeterminate to summarise child rows in a table header.\n * @dont Use a Checkbox for mutually exclusive choices — use RadioGroup.\n */\nexport const Checkbox = forwardRef<ElementRef<typeof CheckboxPrimitive.Root>, CheckboxProps>(\n function Checkbox(\n {\n className,\n label,\n description,\n error,\n hideLabel,\n id,\n disabled,\n 'aria-describedby': ariaDescribedby,\n 'aria-invalid': ariaInvalid,\n ...props\n },\n ref,\n ) {\n const autoId = useId();\n const fieldId = id ?? autoId;\n const descId = description ? `${fieldId}-desc` : undefined;\n const errorId = error ? `${fieldId}-error` : undefined;\n const describedBy = [errorId, descId, ariaDescribedby].filter(Boolean).join(' ') || undefined;\n const isError = Boolean(error) || ariaInvalid === true || ariaInvalid === 'true';\n\n return (\n <div className={cn('flex flex-col gap-1', className)}>\n <div className=\"flex items-start gap-2.5\">\n <CheckboxPrimitive.Root\n ref={ref}\n id={fieldId}\n disabled={disabled}\n aria-describedby={describedBy}\n aria-invalid={isError ? true : ariaInvalid}\n className={cn(\n 'peer relative mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-sm border',\n // WCAG 2.5.8: 16px visual box, ≥24px hit area via an invisible inset halo.\n 'before:absolute before:-inset-1.5 before:content-[\"\"]',\n 'transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out)]',\n 'focus-visible:ring-ring focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n 'data-[state=checked]:bg-accent data-[state=checked]:border-accent data-[state=checked]:text-on-accent',\n 'data-[state=indeterminate]:bg-accent data-[state=indeterminate]:border-accent data-[state=indeterminate]:text-on-accent',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'border-border-input aria-invalid:border-danger',\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className=\"flex items-center justify-center\">\n {props.checked === 'indeterminate' ? (\n <Minus className=\"size-3\" aria-hidden strokeWidth={3} />\n ) : (\n <Check className=\"size-3\" aria-hidden strokeWidth={3} />\n )}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n\n {label && (\n <div className=\"flex flex-col gap-0.5\">\n <label\n htmlFor={fieldId}\n className={cn(\n 'text-foreground text-sm select-none',\n disabled && 'cursor-not-allowed opacity-50',\n hideLabel && 'sr-only',\n )}\n >\n {label}\n </label>\n {description && (\n <p id={descId} className=\"text-foreground-subtle text-xs\">\n {description}\n </p>\n )}\n </div>\n )}\n </div>\n {error && (\n <p id={errorId} className=\"text-danger-text text-xs\">\n {error}\n </p>\n )}\n </div>\n );\n },\n);\n\nCheckbox.displayName = 'Checkbox';\n"],"names":["Checkbox","forwardRef","className","label","description","error","hideLabel","id","disabled","ariaDescribedby","ariaInvalid","props","ref","autoId","useId","fieldId","descId","errorId","describedBy","isError","cn","jsxs","jsx","CheckboxPrimitive","Minus","Check"],"mappings":";;;;;;AA0CO,MAAMA,IAAWC;AAAA,EACtB,SACE;AAAA,IACE,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,aAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,IAAAC;AAAA,IACA,UAAAC;AAAA,IACA,oBAAoBC;AAAA,IACpB,gBAAgBC;AAAA,IAChB,GAAGC;AAAA,EAAA,GAELC,GACA;AACA,UAAMC,IAASC,EAAA,GACTC,IAAUR,KAAMM,GAChBG,IAASZ,IAAc,GAAGW,CAAO,UAAU,QAC3CE,IAAUZ,IAAQ,GAAGU,CAAO,WAAW,QACvCG,IAAc,CAACD,GAASD,GAAQP,CAAe,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KAAK,QAC9EU,IAAU,EAAQd,KAAUK,MAAgB,MAAQA,MAAgB;AAE1E,6BACG,OAAA,EAAI,WAAWU,EAAG,uBAAuBlB,CAAS,GACjD,UAAA;AAAA,MAAA,gBAAAmB,EAAC,OAAA,EAAI,WAAU,4BACb,UAAA;AAAA,QAAA,gBAAAC;AAAA,UAACC,EAAkB;AAAA,UAAlB;AAAA,YACC,KAAAX;AAAA,YACA,IAAIG;AAAA,YACJ,UAAAP;AAAA,YACA,oBAAkBU;AAAA,YAClB,gBAAcC,IAAU,KAAOT;AAAA,YAC/B,WAAWU;AAAA,cACT;AAAA;AAAA,cAEA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,YAED,GAAGT;AAAA,YAEJ,UAAA,gBAAAW,EAACC,EAAkB,WAAlB,EAA4B,WAAU,oCACpC,UAAAZ,EAAM,YAAY,kBACjB,gBAAAW,EAACE,GAAA,EAAM,WAAU,UAAS,eAAW,IAAC,aAAa,EAAA,CAAG,IAEtD,gBAAAF,EAACG,GAAA,EAAM,WAAU,UAAS,eAAW,IAAC,aAAa,EAAA,CAAG,EAAA,CAE1D;AAAA,UAAA;AAAA,QAAA;AAAA,QAGDtB,KACC,gBAAAkB,EAAC,OAAA,EAAI,WAAU,yBACb,UAAA;AAAA,UAAA,gBAAAC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAASP;AAAA,cACT,WAAWK;AAAA,gBACT;AAAA,gBACAZ,KAAY;AAAA,gBACZF,KAAa;AAAA,cAAA;AAAA,cAGd,UAAAH;AAAA,YAAA;AAAA,UAAA;AAAA,UAEFC,KACC,gBAAAkB,EAAC,KAAA,EAAE,IAAIN,GAAQ,WAAU,kCACtB,UAAAZ,EAAA,CACH;AAAA,QAAA,EAAA,CAEJ;AAAA,MAAA,GAEJ;AAAA,MACCC,KACC,gBAAAiB,EAAC,KAAA,EAAE,IAAIL,GAAS,WAAU,4BACvB,UAAAZ,EAAA,CACH;AAAA,IAAA,GAEJ;AAAA,EAEJ;AACF;AAEAL,EAAS,cAAc;"}
@@ -0,0 +1,67 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ComboboxOption {
3
+ value: string;
4
+ label: string;
5
+ description?: string;
6
+ disabled?: boolean;
7
+ }
8
+ export interface ComboboxProps {
9
+ /** Currently selected value (controlled). */
10
+ value: string | null;
11
+ /** Called when a value is picked or cleared. */
12
+ onChange: (value: string | null) => void;
13
+ /** Static options. Ignored if `loadOptions` is provided. */
14
+ options?: ComboboxOption[];
15
+ /**
16
+ * Async loader called with the current query each time it changes.
17
+ * Use for server-side search.
18
+ */
19
+ loadOptions?: (query: string) => Promise<ComboboxOption[]>;
20
+ /**
21
+ * Label to show for a preset `value` in `loadOptions` mode before the
22
+ * first search has resolved (the component has no option list yet).
23
+ */
24
+ selectedLabel?: string;
25
+ /** Visible label above the field. */
26
+ label?: ReactNode;
27
+ /** Hint below the field. Hidden when `error` is set. */
28
+ helperText?: ReactNode;
29
+ /** Validation error. */
30
+ error?: ReactNode;
31
+ /** Placeholder shown when no value is selected. */
32
+ placeholder?: string;
33
+ /** Search placeholder inside the popover. */
34
+ searchPlaceholder?: string;
35
+ /** Empty state copy when nothing matches. */
36
+ emptyText?: string;
37
+ /** Message shown when `loadOptions` rejects. */
38
+ loadErrorText?: string;
39
+ /** Allow clearing the selection with an inline ×. */
40
+ clearable?: boolean;
41
+ /** Disable the entire field. */
42
+ disabled?: boolean;
43
+ /** Field size, matches Input. */
44
+ size?: 'sm' | 'md' | 'lg';
45
+ /** Consumer-supplied id for the trigger (label association). */
46
+ id?: string;
47
+ className?: string;
48
+ }
49
+ /**
50
+ * Single-select with typeahead. Use `options` for client-side filtering or
51
+ * `loadOptions` for server-side search.
52
+ *
53
+ * @example Client-side
54
+ * <Combobox label="Country" options={countries} value={c} onChange={setC} />
55
+ *
56
+ * @example Server-side
57
+ * <Combobox label="Assignee"
58
+ * value={user}
59
+ * onChange={setUser}
60
+ * loadOptions={async (q) => api.searchUsers(q)} />
61
+ *
62
+ * @do Use Combobox over Select for >12 options or when the user is expected
63
+ * to know what they want.
64
+ * @dont Re-query on every keystroke without debouncing — pass a debounced
65
+ * `loadOptions` to avoid hammering the server.
66
+ */
67
+ export declare const Combobox: import('react').ForwardRefExoticComponent<ComboboxProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,195 @@
1
+ "use client";
2
+ import { jsxs as o, jsx as r } from "react/jsx-runtime";
3
+ import { forwardRef as de, useState as s, useCallback as D, useMemo as M, useRef as ie, useEffect as Q } from "react";
4
+ import * as p from "@radix-ui/react-popover";
5
+ import { Command as f } from "cmdk";
6
+ import { X as ce, ChevronsUpDown as ue, Loader2 as me, Check as fe } from "../../icons/index.js";
7
+ import { cn as b } from "../../lib/utils.js";
8
+ import { useStrings as be } from "../../hooks/use-strings.js";
9
+ import { useFieldIds as xe } from "../../hooks/use-field-ids.js";
10
+ import { IconButton as pe } from "./IconButton.js";
11
+ const ge = de(function({
12
+ value: a,
13
+ onChange: g,
14
+ options: k,
15
+ loadOptions: l,
16
+ selectedLabel: h,
17
+ label: n,
18
+ helperText: v,
19
+ error: y,
20
+ placeholder: U,
21
+ searchPlaceholder: V,
22
+ emptyText: X,
23
+ loadErrorText: A,
24
+ clearable: z = !0,
25
+ disabled: L,
26
+ size: x = "md",
27
+ id: R,
28
+ className: G
29
+ }, J) {
30
+ const d = be(), N = U ?? d.combobox.placeholder, K = V ?? d.combobox.searchPlaceholder, W = X ?? d.combobox.empty, Y = A ?? d.combobox.loadError, w = !!y, { fieldId: c, helperId: Z, errorId: _, describedBy: O } = xe(R, {
31
+ hasHelper: !!v,
32
+ hasError: w
33
+ }), [ee, re] = s(void 0), te = D((e) => re(e == null ? void 0 : e.id), []), [u, B] = s(!1), [C, oe] = s(""), [S, j] = s([]), [I, F] = s(!1), [T, $] = s(!1), [m, H] = s(null), E = M(
34
+ () => l ? S : k ?? [],
35
+ [l, S, k]
36
+ ), q = ie(l);
37
+ Q(() => {
38
+ q.current = l;
39
+ }), Q(() => {
40
+ const e = q.current;
41
+ if (!e || !u) return;
42
+ let t = !1;
43
+ return F(!0), $(!1), e(C).then((P) => {
44
+ t || j(P);
45
+ }).catch(() => {
46
+ t || (j([]), $(!0));
47
+ }).finally(() => {
48
+ t || F(!1);
49
+ }), () => {
50
+ t = !0;
51
+ };
52
+ }, [C, u, !!l]);
53
+ const i = M(() => {
54
+ if (a == null) return null;
55
+ const e = E.find((t) => t.value === a);
56
+ return e || ((m == null ? void 0 : m.value) === a ? m : h !== void 0 ? { value: a, label: h } : null);
57
+ }, [E, a, m, h]), ae = x === "sm" ? "h-8" : x === "lg" ? "h-10" : "h-9", se = x === "sm" ? "px-2.5" : x === "lg" ? "px-3.5" : "px-3", le = z ? "pr-14" : "pr-9", ne = D(() => {
58
+ H(null), g(null);
59
+ }, [g]);
60
+ return /* @__PURE__ */ o("div", { ref: J, className: b("flex flex-col gap-1.5", G), children: [
61
+ n && /* @__PURE__ */ r(
62
+ "label",
63
+ {
64
+ id: `${c}-label`,
65
+ htmlFor: c,
66
+ className: "text-foreground text-sm font-medium",
67
+ children: n
68
+ }
69
+ ),
70
+ /* @__PURE__ */ o(p.Root, { open: u, onOpenChange: B, children: [
71
+ /* @__PURE__ */ o("div", { className: "relative w-full", children: [
72
+ /* @__PURE__ */ r(p.Trigger, { asChild: !0, children: /* @__PURE__ */ r(
73
+ "button",
74
+ {
75
+ id: c,
76
+ type: "button",
77
+ role: "combobox",
78
+ "aria-expanded": u,
79
+ "aria-haspopup": "listbox",
80
+ "aria-controls": u ? ee : void 0,
81
+ "aria-labelledby": n ? `${c}-label` : void 0,
82
+ "aria-label": n || R ? void 0 : N,
83
+ "aria-invalid": w || void 0,
84
+ "aria-describedby": O,
85
+ disabled: L,
86
+ className: b(
87
+ "bg-card text-foreground inline-flex w-full items-center justify-between gap-2 rounded-md border text-sm",
88
+ "transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out)]",
89
+ "focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
90
+ "disabled:cursor-not-allowed disabled:opacity-50",
91
+ ae,
92
+ se,
93
+ le,
94
+ w ? "border-danger focus-visible:border-danger focus-visible:ring-danger" : "border-border-input focus-visible:border-accent focus-visible:ring-ring"
95
+ ),
96
+ children: /* @__PURE__ */ r(
97
+ "span",
98
+ {
99
+ className: b("truncate", !i && "text-foreground-subtle"),
100
+ title: i ? i.label : void 0,
101
+ children: i ? i.label : N
102
+ }
103
+ )
104
+ }
105
+ ) }),
106
+ /* @__PURE__ */ o("span", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center gap-0.5 pr-2", children: [
107
+ z && i && !L && /* @__PURE__ */ r(
108
+ pe,
109
+ {
110
+ size: "sm",
111
+ variant: "ghost",
112
+ "aria-label": d.combobox.clear,
113
+ icon: /* @__PURE__ */ r(ce, {}),
114
+ onClick: ne,
115
+ className: "text-foreground-subtle hover:text-foreground pointer-events-auto size-6"
116
+ }
117
+ ),
118
+ /* @__PURE__ */ r(ue, { className: "text-foreground-subtle size-4", "aria-hidden": !0 })
119
+ ] })
120
+ ] }),
121
+ /* @__PURE__ */ r(p.Portal, { children: /* @__PURE__ */ r(
122
+ p.Content,
123
+ {
124
+ "aria-labelledby": n ? `${c}-label` : void 0,
125
+ "aria-label": n ? void 0 : N,
126
+ align: "start",
127
+ sideOffset: 4,
128
+ className: b(
129
+ "border-border bg-popover text-popover-foreground z-[var(--z-popover)] w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-lg border shadow-md",
130
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
131
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
132
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
133
+ ),
134
+ children: /* @__PURE__ */ o(f, { shouldFilter: !l, className: "flex h-full w-full flex-col", children: [
135
+ /* @__PURE__ */ o("div", { className: "border-border flex items-center border-b px-3", children: [
136
+ /* @__PURE__ */ r(
137
+ f.Input,
138
+ {
139
+ value: C,
140
+ onValueChange: oe,
141
+ placeholder: K,
142
+ className: "placeholder:text-foreground-subtle flex h-9 w-full bg-transparent py-2 text-lg outline-none md:text-sm"
143
+ }
144
+ ),
145
+ I && /* @__PURE__ */ r(me, { className: "text-foreground-subtle size-4 animate-spin", "aria-hidden": !0 })
146
+ ] }),
147
+ /* @__PURE__ */ o(
148
+ f.List,
149
+ {
150
+ ref: te,
151
+ label: d.command.suggestions,
152
+ className: "max-h-64 overflow-y-auto p-1",
153
+ children: [
154
+ E.map((e) => {
155
+ const t = e.value === a;
156
+ return /* @__PURE__ */ o(
157
+ f.Item,
158
+ {
159
+ value: e.value,
160
+ keywords: e.description ? [e.label, e.description] : [e.label],
161
+ disabled: e.disabled,
162
+ onSelect: (P) => {
163
+ H(e), g(P), B(!1);
164
+ },
165
+ className: b(
166
+ "text-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm",
167
+ "data-[selected=true]:bg-background-muted",
168
+ "data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50"
169
+ ),
170
+ children: [
171
+ /* @__PURE__ */ r("span", { className: "flex-1", children: e.label }),
172
+ e.description && /* @__PURE__ */ r("span", { className: "text-foreground-subtle text-xs", children: e.description }),
173
+ t && /* @__PURE__ */ r(fe, { className: "text-accent size-4", "aria-hidden": !0 })
174
+ ]
175
+ },
176
+ e.value
177
+ );
178
+ }),
179
+ T && !I && /* @__PURE__ */ r("div", { className: "text-danger-text px-2 py-6 text-center text-sm", children: Y }),
180
+ !I && !T && /* @__PURE__ */ r(f.Empty, { className: "text-foreground-subtle px-2 py-6 text-center text-sm", children: W })
181
+ ]
182
+ }
183
+ )
184
+ ] })
185
+ }
186
+ ) })
187
+ ] }),
188
+ y ? /* @__PURE__ */ r("p", { id: _, className: "text-danger-text text-xs", children: y }) : v ? /* @__PURE__ */ r("p", { id: Z, className: "text-foreground-subtle text-xs", children: v }) : null
189
+ ] });
190
+ });
191
+ ge.displayName = "Combobox";
192
+ export {
193
+ ge as Combobox
194
+ };
195
+ //# sourceMappingURL=Combobox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Combobox.js","sources":["../../../src/components/ui/Combobox.tsx"],"sourcesContent":["'use client';\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { Command as CommandPrimitive } from 'cmdk';\nimport { Check, ChevronsUpDown, Loader2, X } from '@/icons';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\nimport { useFieldIds } from '@/hooks/use-field-ids';\nimport { IconButton } from './IconButton';\n\nexport interface ComboboxOption {\n value: string;\n label: string;\n description?: string;\n disabled?: boolean;\n}\n\nexport interface ComboboxProps {\n /** Currently selected value (controlled). */\n value: string | null;\n /** Called when a value is picked or cleared. */\n onChange: (value: string | null) => void;\n /** Static options. Ignored if `loadOptions` is provided. */\n options?: ComboboxOption[];\n /**\n * Async loader called with the current query each time it changes.\n * Use for server-side search.\n */\n loadOptions?: (query: string) => Promise<ComboboxOption[]>;\n /**\n * Label to show for a preset `value` in `loadOptions` mode before the\n * first search has resolved (the component has no option list yet).\n */\n selectedLabel?: string;\n /** Visible label above the field. */\n label?: ReactNode;\n /** Hint below the field. Hidden when `error` is set. */\n helperText?: ReactNode;\n /** Validation error. */\n error?: ReactNode;\n /** Placeholder shown when no value is selected. */\n placeholder?: string;\n /** Search placeholder inside the popover. */\n searchPlaceholder?: string;\n /** Empty state copy when nothing matches. */\n emptyText?: string;\n /** Message shown when `loadOptions` rejects. */\n loadErrorText?: string;\n /** Allow clearing the selection with an inline ×. */\n clearable?: boolean;\n /** Disable the entire field. */\n disabled?: boolean;\n /** Field size, matches Input. */\n size?: 'sm' | 'md' | 'lg';\n /** Consumer-supplied id for the trigger (label association). */\n id?: string;\n className?: string;\n}\n\n/**\n * Single-select with typeahead. Use `options` for client-side filtering or\n * `loadOptions` for server-side search.\n *\n * @example Client-side\n * <Combobox label=\"Country\" options={countries} value={c} onChange={setC} />\n *\n * @example Server-side\n * <Combobox label=\"Assignee\"\n * value={user}\n * onChange={setUser}\n * loadOptions={async (q) => api.searchUsers(q)} />\n *\n * @do Use Combobox over Select for >12 options or when the user is expected\n * to know what they want.\n * @dont Re-query on every keystroke without debouncing — pass a debounced\n * `loadOptions` to avoid hammering the server.\n */\nexport const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(function Combobox(\n {\n value,\n onChange,\n options,\n loadOptions,\n selectedLabel,\n label,\n helperText,\n error,\n placeholder: placeholderProp,\n searchPlaceholder: searchPlaceholderProp,\n emptyText: emptyTextProp,\n loadErrorText: loadErrorTextProp,\n clearable = true,\n disabled,\n size = 'md',\n id,\n className,\n },\n ref,\n) {\n const strings = useStrings();\n const placeholder = placeholderProp ?? strings.combobox.placeholder;\n const searchPlaceholder = searchPlaceholderProp ?? strings.combobox.searchPlaceholder;\n const emptyText = emptyTextProp ?? strings.combobox.empty;\n const loadErrorText = loadErrorTextProp ?? strings.combobox.loadError;\n const isError = Boolean(error);\n const { fieldId, helperId, errorId, describedBy } = useFieldIds(id, {\n hasHelper: Boolean(helperText),\n hasError: isError,\n });\n // cmdk assigns its own id to the list, so read it back from the node once\n // the portal mounts; aria-controls is only set while the listbox exists.\n const [listId, setListId] = useState<string | undefined>(undefined);\n const listRef = useCallback((el: HTMLDivElement | null) => setListId(el?.id), []);\n\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [loaded, setLoaded] = useState<ComboboxOption[]>([]);\n const [loading, setLoading] = useState(false);\n const [loadError, setLoadError] = useState(false);\n // In async mode the option list only exists after the first search, so the\n // chosen option is remembered here to keep its label on the trigger.\n const [selectedOption, setSelectedOption] = useState<ComboboxOption | null>(null);\n\n // Resolve options: static or async-loaded.\n const items = useMemo(\n () => (loadOptions ? loaded : (options ?? [])),\n [loadOptions, loaded, options],\n );\n\n // Latest loader in a ref so an inline `loadOptions={async q => …}` does not\n // retrigger the fetch on every parent render — only query / open do.\n const loadRef = useRef(loadOptions);\n useEffect(() => {\n loadRef.current = loadOptions;\n });\n const hasLoader = Boolean(loadOptions);\n useEffect(() => {\n const load = loadRef.current;\n if (!load || !open) return;\n let cancelled = false;\n setLoading(true);\n setLoadError(false);\n load(query)\n .then((res) => {\n if (!cancelled) setLoaded(res);\n })\n .catch(() => {\n if (!cancelled) {\n setLoaded([]);\n setLoadError(true);\n }\n })\n .finally(() => {\n if (!cancelled) setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [query, open, hasLoader]);\n\n const selected = useMemo<ComboboxOption | null>(() => {\n if (value === null || value === undefined) return null;\n const fromItems = items.find((o) => o.value === value);\n if (fromItems) return fromItems;\n if (selectedOption?.value === value) return selectedOption;\n if (selectedLabel !== undefined) return { value, label: selectedLabel };\n return null;\n }, [items, value, selectedOption, selectedLabel]);\n\n const triggerHeight = size === 'sm' ? 'h-8' : size === 'lg' ? 'h-10' : 'h-9';\n const triggerPadding = size === 'sm' ? 'px-2.5' : size === 'lg' ? 'px-3.5' : 'px-3';\n // Leave room on the right for the clear button + chevron.\n const triggerPaddingRight = clearable ? 'pr-14' : 'pr-9';\n\n const handleClear = useCallback(() => {\n setSelectedOption(null);\n onChange(null);\n }, [onChange]);\n\n return (\n <div ref={ref} className={cn('flex flex-col gap-1.5', className)}>\n {label && (\n <label\n id={`${fieldId}-label`}\n htmlFor={fieldId}\n className=\"text-foreground text-sm font-medium\"\n >\n {label}\n </label>\n )}\n\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n <div className=\"relative w-full\">\n <PopoverPrimitive.Trigger asChild>\n <button\n id={fieldId}\n type=\"button\"\n role=\"combobox\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-controls={open ? listId : undefined}\n // role=combobox takes no name from content, so the placeholder\n // must be exposed explicitly. A consumer `id` implies an external\n // <label htmlFor>, which aria-label would override.\n aria-labelledby={label ? `${fieldId}-label` : undefined}\n aria-label={label || id ? undefined : placeholder}\n aria-invalid={isError || undefined}\n aria-describedby={describedBy}\n disabled={disabled}\n className={cn(\n 'bg-card text-foreground inline-flex w-full items-center justify-between gap-2 rounded-md border text-sm',\n 'transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out)]',\n 'focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n triggerHeight,\n triggerPadding,\n triggerPaddingRight,\n isError\n ? 'border-danger focus-visible:border-danger focus-visible:ring-danger'\n : 'border-border-input focus-visible:border-accent focus-visible:ring-ring',\n )}\n >\n <span\n className={cn('truncate', !selected && 'text-foreground-subtle')}\n title={selected ? selected.label : undefined}\n >\n {selected ? selected.label : placeholder}\n </span>\n </button>\n </PopoverPrimitive.Trigger>\n\n {/* Controls sit outside the trigger: a button inside a button is invalid HTML. */}\n <span className=\"pointer-events-none absolute inset-y-0 right-0 flex items-center gap-0.5 pr-2\">\n {clearable && selected && !disabled && (\n <IconButton\n size=\"sm\"\n variant=\"ghost\"\n aria-label={strings.combobox.clear}\n icon={<X />}\n onClick={handleClear}\n className=\"text-foreground-subtle hover:text-foreground pointer-events-auto size-6\"\n />\n )}\n <ChevronsUpDown className=\"text-foreground-subtle size-4\" aria-hidden />\n </span>\n </div>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n // Radix gives the popover role=\"dialog\"; name it after the field.\n aria-labelledby={label ? `${fieldId}-label` : undefined}\n aria-label={label ? undefined : placeholder}\n align=\"start\"\n sideOffset={4}\n className={cn(\n 'border-border bg-popover text-popover-foreground z-[var(--z-popover)] w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-lg border shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n )}\n >\n <CommandPrimitive shouldFilter={!loadOptions} className=\"flex h-full w-full flex-col\">\n <div className=\"border-border flex items-center border-b px-3\">\n <CommandPrimitive.Input\n value={query}\n onValueChange={setQuery}\n placeholder={searchPlaceholder}\n className=\"placeholder:text-foreground-subtle flex h-9 w-full bg-transparent py-2 text-lg outline-none md:text-sm\"\n />\n {loading && (\n <Loader2 className=\"text-foreground-subtle size-4 animate-spin\" aria-hidden />\n )}\n </div>\n <CommandPrimitive.List\n ref={listRef}\n label={strings.command.suggestions}\n className=\"max-h-64 overflow-y-auto p-1\"\n >\n {items.map((opt) => {\n const isSelected = opt.value === value;\n return (\n <CommandPrimitive.Item\n key={opt.value}\n value={opt.value}\n // cmdk matches on value + keywords; users type the label, not the id.\n keywords={opt.description ? [opt.label, opt.description] : [opt.label]}\n disabled={opt.disabled}\n onSelect={(v) => {\n setSelectedOption(opt);\n onChange(v);\n setOpen(false);\n }}\n className={cn(\n 'text-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm',\n 'data-[selected=true]:bg-background-muted',\n 'data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50',\n )}\n >\n <span className=\"flex-1\">{opt.label}</span>\n {opt.description && (\n <span className=\"text-foreground-subtle text-xs\">{opt.description}</span>\n )}\n {isSelected && <Check className=\"text-accent size-4\" aria-hidden />}\n </CommandPrimitive.Item>\n );\n })}\n {loadError && !loading && (\n <div className=\"text-danger-text px-2 py-6 text-center text-sm\">\n {loadErrorText}\n </div>\n )}\n {/* cmdk only shows Empty when no item matches the query, so it can always be mounted. */}\n {!loading && !loadError && (\n <CommandPrimitive.Empty className=\"text-foreground-subtle px-2 py-6 text-center text-sm\">\n {emptyText}\n </CommandPrimitive.Empty>\n )}\n </CommandPrimitive.List>\n </CommandPrimitive>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n\n {error ? (\n <p id={errorId} className=\"text-danger-text text-xs\">\n {error}\n </p>\n ) : helperText ? (\n <p id={helperId} className=\"text-foreground-subtle text-xs\">\n {helperText}\n </p>\n ) : null}\n </div>\n );\n});\n\nCombobox.displayName = 'Combobox';\n"],"names":["Combobox","forwardRef","value","onChange","options","loadOptions","selectedLabel","label","helperText","error","placeholderProp","searchPlaceholderProp","emptyTextProp","loadErrorTextProp","clearable","disabled","size","id","className","ref","strings","useStrings","placeholder","searchPlaceholder","emptyText","loadErrorText","isError","fieldId","helperId","errorId","describedBy","useFieldIds","listId","setListId","useState","listRef","useCallback","el","open","setOpen","query","setQuery","loaded","setLoaded","loading","setLoading","loadError","setLoadError","selectedOption","setSelectedOption","items","useMemo","loadRef","useRef","useEffect","load","cancelled","res","selected","fromItems","o","triggerHeight","triggerPadding","triggerPaddingRight","handleClear","cn","jsx","PopoverPrimitive","jsxs","IconButton","X","ChevronsUpDown","CommandPrimitive","Loader2","opt","isSelected","v","Check"],"mappings":"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"}
@@ -0,0 +1,112 @@
1
+ import { Dispatch, ReactNode, SetStateAction } from 'react';
2
+ export declare const Command: import('react').ForwardRefExoticComponent<Omit<{
3
+ children?: React.ReactNode;
4
+ } & Pick<Pick<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import('react').HTMLAttributes<HTMLDivElement>> & {
5
+ ref?: React.Ref<HTMLDivElement>;
6
+ } & {
7
+ asChild?: boolean;
8
+ }, "key" | keyof import('react').HTMLAttributes<HTMLDivElement> | "asChild"> & {
9
+ label?: string;
10
+ shouldFilter?: boolean;
11
+ filter?: (value: string, search: string, keywords?: string[]) => number;
12
+ defaultValue?: string;
13
+ value?: string;
14
+ onValueChange?: (value: string) => void;
15
+ loop?: boolean;
16
+ disablePointerSelection?: boolean;
17
+ vimBindings?: boolean;
18
+ } & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
19
+ export declare const CommandInput: import('react').ForwardRefExoticComponent<Omit<Omit<Pick<Pick<import('react').DetailedHTMLProps<import('react').InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "key" | keyof import('react').InputHTMLAttributes<HTMLInputElement>> & {
20
+ ref?: React.Ref<HTMLInputElement>;
21
+ } & {
22
+ asChild?: boolean;
23
+ }, "key" | "asChild" | keyof import('react').InputHTMLAttributes<HTMLInputElement>>, "value" | "type" | "onChange"> & {
24
+ value?: string;
25
+ onValueChange?: (search: string) => void;
26
+ } & import('react').RefAttributes<HTMLInputElement>, "ref"> & import('react').RefAttributes<HTMLInputElement>>;
27
+ export declare const CommandList: import('react').ForwardRefExoticComponent<Omit<{
28
+ children?: React.ReactNode;
29
+ } & Pick<Pick<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import('react').HTMLAttributes<HTMLDivElement>> & {
30
+ ref?: React.Ref<HTMLDivElement>;
31
+ } & {
32
+ asChild?: boolean;
33
+ }, "key" | keyof import('react').HTMLAttributes<HTMLDivElement> | "asChild"> & {
34
+ label?: string;
35
+ } & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
36
+ export declare const CommandEmpty: import('react').ForwardRefExoticComponent<Omit<{
37
+ children?: React.ReactNode;
38
+ } & Pick<Pick<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import('react').HTMLAttributes<HTMLDivElement>> & {
39
+ ref?: React.Ref<HTMLDivElement>;
40
+ } & {
41
+ asChild?: boolean;
42
+ }, "key" | keyof import('react').HTMLAttributes<HTMLDivElement> | "asChild"> & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
43
+ export declare const CommandGroup: import('react').ForwardRefExoticComponent<Omit<{
44
+ children?: React.ReactNode;
45
+ } & Omit<Pick<Pick<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import('react').HTMLAttributes<HTMLDivElement>> & {
46
+ ref?: React.Ref<HTMLDivElement>;
47
+ } & {
48
+ asChild?: boolean;
49
+ }, "key" | keyof import('react').HTMLAttributes<HTMLDivElement> | "asChild">, "value" | "heading"> & {
50
+ heading?: React.ReactNode;
51
+ value?: string;
52
+ forceMount?: boolean;
53
+ } & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
54
+ export declare const CommandSeparator: import('react').ForwardRefExoticComponent<Omit<Pick<Pick<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import('react').HTMLAttributes<HTMLDivElement>> & {
55
+ ref?: React.Ref<HTMLDivElement>;
56
+ } & {
57
+ asChild?: boolean;
58
+ }, "key" | keyof import('react').HTMLAttributes<HTMLDivElement> | "asChild"> & {
59
+ alwaysRender?: boolean;
60
+ } & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
61
+ export declare const CommandItem: import('react').ForwardRefExoticComponent<Omit<{
62
+ children?: React.ReactNode;
63
+ } & Omit<Pick<Pick<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof import('react').HTMLAttributes<HTMLDivElement>> & {
64
+ ref?: React.Ref<HTMLDivElement>;
65
+ } & {
66
+ asChild?: boolean;
67
+ }, "key" | keyof import('react').HTMLAttributes<HTMLDivElement> | "asChild">, "value" | "onSelect" | "disabled"> & {
68
+ disabled?: boolean;
69
+ onSelect?: (value: string) => void;
70
+ value?: string;
71
+ keywords?: string[];
72
+ forceMount?: boolean;
73
+ } & import('react').RefAttributes<HTMLDivElement>, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
74
+ export declare function CommandShortcut({ children, className, }: {
75
+ children: ReactNode;
76
+ className?: string;
77
+ }): import("react/jsx-runtime").JSX.Element;
78
+ export declare namespace CommandShortcut {
79
+ var displayName: string;
80
+ }
81
+ export interface CommandDialogProps {
82
+ open: boolean;
83
+ onOpenChange: (open: boolean) => void;
84
+ children: ReactNode;
85
+ /** Visible label for screen readers. */
86
+ title?: string;
87
+ }
88
+ export declare function CommandDialog({ open, onOpenChange, children, title }: CommandDialogProps): import("react/jsx-runtime").JSX.Element;
89
+ /**
90
+ * Hook that wires ⌘K / Ctrl+K to a setter — the canonical way to mount the
91
+ * palette in an app shell.
92
+ *
93
+ * @example
94
+ * const [open, setOpen] = useState(false);
95
+ * useCommandPaletteShortcut(setOpen);
96
+ * …
97
+ * <CommandDialog open={open} onOpenChange={setOpen}>
98
+ * <CommandInput placeholder="Type a command…" />
99
+ * <CommandList>
100
+ * <CommandEmpty>No results.</CommandEmpty>
101
+ * <CommandGroup heading="Suggestions">
102
+ * <CommandItem>Create project</CommandItem>
103
+ * <CommandItem>Invite teammate</CommandItem>
104
+ * </CommandGroup>
105
+ * </CommandList>
106
+ * </CommandDialog>
107
+ *
108
+ * @do Group items by category. Show "Recent" first when the query is empty.
109
+ * @dont Hide essential actions behind the palette only — keep at least one
110
+ * button entry in the UI.
111
+ */
112
+ export declare function useCommandPaletteShortcut(setOpen: Dispatch<SetStateAction<boolean>>): void;