@hoardodile/ui 0.1.7 → 0.1.9

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 (260) hide show
  1. package/dist/chunk-2BVZEYNW.js +97 -0
  2. package/dist/chunk-2BVZEYNW.js.map +1 -0
  3. package/dist/chunk-2DTR6CD5.js +47 -0
  4. package/dist/chunk-2DTR6CD5.js.map +1 -0
  5. package/dist/chunk-2HWSCY4T.js +20 -0
  6. package/dist/chunk-2HWSCY4T.js.map +1 -0
  7. package/dist/chunk-363CCKQ7.js +75 -0
  8. package/dist/chunk-363CCKQ7.js.map +1 -0
  9. package/dist/chunk-3ZQJWBVB.js +30 -0
  10. package/dist/chunk-3ZQJWBVB.js.map +1 -0
  11. package/dist/chunk-4D36OO5W.js +277 -0
  12. package/dist/chunk-4D36OO5W.js.map +1 -0
  13. package/dist/chunk-4UITFLIN.js +31 -0
  14. package/dist/chunk-4UITFLIN.js.map +1 -0
  15. package/dist/chunk-6HAIUXNZ.js +11 -0
  16. package/dist/chunk-6HAIUXNZ.js.map +1 -0
  17. package/dist/chunk-7JMMFY67.js +62 -0
  18. package/dist/chunk-7JMMFY67.js.map +1 -0
  19. package/dist/chunk-7MWWHI6T.js +1149 -0
  20. package/dist/chunk-7MWWHI6T.js.map +1 -0
  21. package/dist/chunk-AEHTAUAQ.js +65 -0
  22. package/dist/chunk-AEHTAUAQ.js.map +1 -0
  23. package/dist/chunk-ASRGQ5BD.js +130 -0
  24. package/dist/chunk-ASRGQ5BD.js.map +1 -0
  25. package/dist/chunk-BFGOE5AI.js +187 -0
  26. package/dist/chunk-BFGOE5AI.js.map +1 -0
  27. package/dist/chunk-BRT25IDQ.js +46 -0
  28. package/dist/chunk-BRT25IDQ.js.map +1 -0
  29. package/dist/chunk-BU5DQOPM.js +29 -0
  30. package/dist/chunk-BU5DQOPM.js.map +1 -0
  31. package/dist/chunk-BWASOT5X.js +266 -0
  32. package/dist/chunk-BWASOT5X.js.map +1 -0
  33. package/dist/chunk-F32V4Z7Q.js +26 -0
  34. package/dist/chunk-F32V4Z7Q.js.map +1 -0
  35. package/dist/chunk-F7RHDRRJ.js +24 -0
  36. package/dist/chunk-F7RHDRRJ.js.map +1 -0
  37. package/dist/chunk-FH5RNCFR.js +21 -0
  38. package/dist/chunk-FH5RNCFR.js.map +1 -0
  39. package/dist/chunk-GKSX5ULZ.js +513 -0
  40. package/dist/chunk-GKSX5ULZ.js.map +1 -0
  41. package/dist/chunk-JPFDNRCA.js +26 -0
  42. package/dist/chunk-JPFDNRCA.js.map +1 -0
  43. package/dist/chunk-KNPRUZ4H.js +13 -0
  44. package/dist/chunk-KNPRUZ4H.js.map +1 -0
  45. package/dist/chunk-KOFWEPPB.js +254 -0
  46. package/dist/chunk-KOFWEPPB.js.map +1 -0
  47. package/dist/chunk-M5OJN54O.js +10 -0
  48. package/dist/chunk-M5OJN54O.js.map +1 -0
  49. package/dist/chunk-OEVALKQ5.js +51 -0
  50. package/dist/chunk-OEVALKQ5.js.map +1 -0
  51. package/dist/chunk-OW5FWLPH.js +33 -0
  52. package/dist/chunk-OW5FWLPH.js.map +1 -0
  53. package/dist/chunk-POX7TXBH.js +41 -0
  54. package/dist/chunk-POX7TXBH.js.map +1 -0
  55. package/dist/chunk-PWJBHUM2.js +58 -0
  56. package/dist/chunk-PWJBHUM2.js.map +1 -0
  57. package/dist/chunk-QGMDWGJT.js +23 -0
  58. package/dist/chunk-QGMDWGJT.js.map +1 -0
  59. package/dist/chunk-QGTQQNUL.js +36 -0
  60. package/dist/chunk-QGTQQNUL.js.map +1 -0
  61. package/dist/chunk-SAY52ZKI.js +152 -0
  62. package/dist/chunk-SAY52ZKI.js.map +1 -0
  63. package/dist/chunk-SKDPGSRL.js +166 -0
  64. package/dist/chunk-SKDPGSRL.js.map +1 -0
  65. package/dist/chunk-T56ARCUK.js +38 -0
  66. package/dist/chunk-T56ARCUK.js.map +1 -0
  67. package/dist/chunk-TDDHQZ62.js +227 -0
  68. package/dist/chunk-TDDHQZ62.js.map +1 -0
  69. package/dist/chunk-TMQ5OMBK.js +29 -0
  70. package/dist/chunk-TMQ5OMBK.js.map +1 -0
  71. package/dist/chunk-UEVND7AS.js +23 -0
  72. package/dist/chunk-UEVND7AS.js.map +1 -0
  73. package/dist/chunk-UPWHCG4S.js +40 -0
  74. package/dist/chunk-UPWHCG4S.js.map +1 -0
  75. package/dist/chunk-VWUNF7VX.js +3 -0
  76. package/dist/chunk-VWUNF7VX.js.map +1 -0
  77. package/dist/chunk-WI6O7GZK.js +45 -0
  78. package/dist/chunk-WI6O7GZK.js.map +1 -0
  79. package/dist/chunk-WVEK3WCX.js +21 -0
  80. package/dist/chunk-WVEK3WCX.js.map +1 -0
  81. package/dist/chunk-XBPQEZES.js +48 -0
  82. package/dist/chunk-XBPQEZES.js.map +1 -0
  83. package/dist/chunk-ZYAGKKR7.js +142 -0
  84. package/dist/chunk-ZYAGKKR7.js.map +1 -0
  85. package/dist/components/alert.js +2 -21
  86. package/dist/components/alert.js.map +1 -1
  87. package/dist/components/app-dialog.js +10 -654
  88. package/dist/components/app-dialog.js.map +1 -1
  89. package/dist/components/badge.js +2 -23
  90. package/dist/components/badge.js.map +1 -1
  91. package/dist/components/breadcrumb.js +5 -504
  92. package/dist/components/breadcrumb.js.map +1 -1
  93. package/dist/components/button.js +3 -76
  94. package/dist/components/button.js.map +1 -1
  95. package/dist/components/caption-bar.js +7 -521
  96. package/dist/components/caption-bar.js.map +1 -1
  97. package/dist/components/checkbox.js +4 -74
  98. package/dist/components/checkbox.js.map +1 -1
  99. package/dist/components/chip-button.js +4 -85
  100. package/dist/components/chip-button.js.map +1 -1
  101. package/dist/components/close-confirm-dialog.js +12 -662
  102. package/dist/components/close-confirm-dialog.js.map +1 -1
  103. package/dist/components/color-picker.js +7 -533
  104. package/dist/components/color-picker.js.map +1 -1
  105. package/dist/components/combobox.js +15 -937
  106. package/dist/components/combobox.js.map +1 -1
  107. package/dist/components/confirm-by-typing-dialog.js +12 -669
  108. package/dist/components/confirm-by-typing-dialog.js.map +1 -1
  109. package/dist/components/confirm-dialog.js +11 -637
  110. package/dist/components/confirm-dialog.js.map +1 -1
  111. package/dist/components/count-badge.js +2 -21
  112. package/dist/components/count-badge.js.map +1 -1
  113. package/dist/components/dialog.js +8 -569
  114. package/dist/components/dialog.js.map +1 -1
  115. package/dist/components/dropdown-menu.js +9 -1007
  116. package/dist/components/dropdown-menu.js.map +1 -1
  117. package/dist/components/dropdown-select.js +9 -883
  118. package/dist/components/dropdown-select.js.map +1 -1
  119. package/dist/components/empty.js +2 -21
  120. package/dist/components/empty.js.map +1 -1
  121. package/dist/components/filter-rail.js +7 -145
  122. package/dist/components/filter-rail.js.map +1 -1
  123. package/dist/components/fixed-action-bar.js +2 -21
  124. package/dist/components/fixed-action-bar.js.map +1 -1
  125. package/dist/components/font-picker.js +11 -589
  126. package/dist/components/font-picker.js.map +1 -1
  127. package/dist/components/form.js +9 -66
  128. package/dist/components/form.js.map +1 -1
  129. package/dist/components/icon-tile.js +3 -43
  130. package/dist/components/icon-tile.js.map +1 -1
  131. package/dist/components/icon-toggle.js +3 -43
  132. package/dist/components/icon-toggle.js.map +1 -1
  133. package/dist/components/icon.js +3 -47
  134. package/dist/components/icon.js.map +1 -1
  135. package/dist/components/image-crop-panel.js +19 -775
  136. package/dist/components/image-crop-panel.js.map +1 -1
  137. package/dist/components/image-cropper.js +1 -164
  138. package/dist/components/image-cropper.js.map +1 -1
  139. package/dist/components/input-group.js +6 -268
  140. package/dist/components/input-group.js.map +1 -1
  141. package/dist/components/input.js +3 -58
  142. package/dist/components/input.js.map +1 -1
  143. package/dist/components/label.js +3 -38
  144. package/dist/components/label.js.map +1 -1
  145. package/dist/components/list-empty-row.js +2 -21
  146. package/dist/components/list-empty-row.js.map +1 -1
  147. package/dist/components/management-empty.js +2 -21
  148. package/dist/components/management-empty.js.map +1 -1
  149. package/dist/components/management-skeleton.js +4 -59
  150. package/dist/components/management-skeleton.js.map +1 -1
  151. package/dist/components/meta-chip.js +2 -21
  152. package/dist/components/meta-chip.js.map +1 -1
  153. package/dist/components/mobile-drawer.js +7 -268
  154. package/dist/components/mobile-drawer.js.map +1 -1
  155. package/dist/components/page-header.js +3 -42
  156. package/dist/components/page-header.js.map +1 -1
  157. package/dist/components/page-scaffold.js +5 -76
  158. package/dist/components/page-scaffold.js.map +1 -1
  159. package/dist/components/pagination-bar.js +13 -617
  160. package/dist/components/pagination-bar.js.map +1 -1
  161. package/dist/components/pagination.js +6 -684
  162. package/dist/components/pagination.js.map +1 -1
  163. package/dist/components/panel-toolbar.js +11 -716
  164. package/dist/components/panel-toolbar.js.map +1 -1
  165. package/dist/components/pill-tabs.js +2 -21
  166. package/dist/components/pill-tabs.js.map +1 -1
  167. package/dist/components/plugin-download-consent.js +13 -663
  168. package/dist/components/plugin-download-consent.js.map +1 -1
  169. package/dist/components/popover.js +5 -242
  170. package/dist/components/popover.js.map +1 -1
  171. package/dist/components/preview-card.js +2 -21
  172. package/dist/components/preview-card.js.map +1 -1
  173. package/dist/components/progress.js +2 -20
  174. package/dist/components/progress.js.map +1 -1
  175. package/dist/components/radio-group.js +2 -21
  176. package/dist/components/radio-group.js.map +1 -1
  177. package/dist/components/scroll-area.js +2 -21
  178. package/dist/components/scroll-area.js.map +1 -1
  179. package/dist/components/search-field.js +6 -590
  180. package/dist/components/search-field.js.map +1 -1
  181. package/dist/components/secondary-stat.js +3 -40
  182. package/dist/components/secondary-stat.js.map +1 -1
  183. package/dist/components/section-header.js +3 -43
  184. package/dist/components/section-header.js.map +1 -1
  185. package/dist/components/section-label.js +3 -44
  186. package/dist/components/section-label.js.map +1 -1
  187. package/dist/components/section-tabs.js +2 -21
  188. package/dist/components/section-tabs.js.map +1 -1
  189. package/dist/components/separator.js +3 -47
  190. package/dist/components/separator.js.map +1 -1
  191. package/dist/components/sheet.js +8 -467
  192. package/dist/components/sheet.js.map +1 -1
  193. package/dist/components/sidebar.js +24 -1047
  194. package/dist/components/sidebar.js.map +1 -1
  195. package/dist/components/skeleton.js +3 -39
  196. package/dist/components/skeleton.js.map +1 -1
  197. package/dist/components/slider.js +2 -21
  198. package/dist/components/slider.js.map +1 -1
  199. package/dist/components/sortable-chip-list.js +2 -21
  200. package/dist/components/sortable-chip-list.js.map +1 -1
  201. package/dist/components/special-tag-surface.js +3 -531
  202. package/dist/components/special-tag-surface.js.map +1 -1
  203. package/dist/components/spinner.js +3 -63
  204. package/dist/components/spinner.js.map +1 -1
  205. package/dist/components/surface.js +3 -49
  206. package/dist/components/surface.js.map +1 -1
  207. package/dist/components/switch.js +3 -51
  208. package/dist/components/switch.js.map +1 -1
  209. package/dist/components/table.js +2 -20
  210. package/dist/components/table.js.map +1 -1
  211. package/dist/components/tag-chip.js +6 -617
  212. package/dist/components/tag-chip.js.map +1 -1
  213. package/dist/components/textarea.js +3 -56
  214. package/dist/components/textarea.js.map +1 -1
  215. package/dist/components/toast.js +8 -809
  216. package/dist/components/toast.js.map +1 -1
  217. package/dist/components/toggle.js +2 -20
  218. package/dist/components/toggle.js.map +1 -1
  219. package/dist/components/tooltip.js +3 -80
  220. package/dist/components/tooltip.js.map +1 -1
  221. package/dist/hooks/use-dialog-footer-actions.js +1 -9
  222. package/dist/hooks/use-dialog-footer-actions.js.map +1 -1
  223. package/dist/hooks/use-form-field.js +1 -34
  224. package/dist/hooks/use-form-field.js.map +1 -1
  225. package/dist/hooks/use-mobile.js +2 -27
  226. package/dist/hooks/use-mobile.js.map +1 -1
  227. package/dist/hooks/useMobileBackToClose.js +3 -232
  228. package/dist/hooks/useMobileBackToClose.js.map +1 -1
  229. package/dist/icons/actions.js +4 -524
  230. package/dist/icons/actions.js.map +1 -1
  231. package/dist/icons/icon-style.js +1 -49
  232. package/dist/icons/icon-style.js.map +1 -1
  233. package/dist/icons/marks.js +1 -46
  234. package/dist/icons/marks.js.map +1 -1
  235. package/dist/icons/registry.js +2 -1194
  236. package/dist/icons/registry.js.map +1 -1
  237. package/dist/index.js +10 -651
  238. package/dist/index.js.map +1 -1
  239. package/dist/lib/colors.js +1 -63
  240. package/dist/lib/colors.js.map +1 -1
  241. package/dist/lib/merge-config.js +1 -18
  242. package/dist/lib/merge-config.js.map +1 -1
  243. package/dist/lib/pagination.js +1 -24
  244. package/dist/lib/pagination.js.map +1 -1
  245. package/dist/lib/tag-surface.js +5 -613
  246. package/dist/lib/tag-surface.js.map +1 -1
  247. package/dist/lib/utils.js +2 -24
  248. package/dist/lib/utils.js.map +1 -1
  249. package/dist/res-card-template/format.js +1 -21
  250. package/dist/res-card-template/format.js.map +1 -1
  251. package/dist/res-card-template/icon.js +1 -39
  252. package/dist/res-card-template/icon.js.map +1 -1
  253. package/dist/res-card-template/index.js +3 -329
  254. package/dist/res-card-template/index.js.map +1 -1
  255. package/dist/res-card-template/template.js +3 -331
  256. package/dist/res-card-template/template.js.map +1 -1
  257. package/dist/viewport.js +1 -11
  258. package/dist/viewport.js.map +1 -1
  259. package/package.json +3 -3
  260. package/src/components/image-crop-panel.dist.test.tsx +54 -0
@@ -0,0 +1,97 @@
1
+ import { useDialogFooterActions, DialogFooterActionsContext } from './chunk-6HAIUXNZ.js';
2
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogBody, DialogFooter } from './chunk-KOFWEPPB.js';
3
+ import { cn } from './chunk-M5OJN54O.js';
4
+ import { useEffect, useRef, useState, useMemo } from 'react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ var sizeClasses = {
8
+ sm: "sm:max-w-sm",
9
+ md: "sm:max-w-md",
10
+ lg: "sm:max-w-2xl",
11
+ xl: "sm:max-w-3xl",
12
+ "2xl": "sm:max-w-4xl"
13
+ };
14
+ function DialogFooterActions({ children }) {
15
+ const slot = useDialogFooterActions();
16
+ useEffect(() => {
17
+ if (slot === null) return;
18
+ slot.setFooterActions(children);
19
+ return () => slot.setFooterActions(null);
20
+ }, [slot, children]);
21
+ return null;
22
+ }
23
+ function AppDialog(props) {
24
+ const {
25
+ open,
26
+ onOpenChange,
27
+ title,
28
+ eyebrow,
29
+ icon,
30
+ danger,
31
+ size,
32
+ flush,
33
+ description,
34
+ children,
35
+ footer,
36
+ contentClassName,
37
+ overlayClassName,
38
+ contentMotion,
39
+ suppressAutoFocus = true,
40
+ contentTestId
41
+ } = props;
42
+ const contentRef = useRef(null);
43
+ const [footerActions, setFooterActions] = useState(null);
44
+ const actionsValue = useMemo(
45
+ () => ({ setFooterActions }),
46
+ [setFooterActions]
47
+ );
48
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
49
+ DialogContent,
50
+ {
51
+ ref: contentRef,
52
+ className: cn(
53
+ size !== void 0 && sizeClasses[size],
54
+ flush && "p-0",
55
+ contentClassName
56
+ ),
57
+ overlayClassName,
58
+ contentMotion,
59
+ initialFocus: suppressAutoFocus ? contentRef : void 0,
60
+ "data-testid": contentTestId,
61
+ children: [
62
+ /* @__PURE__ */ jsxs(DialogHeader, { className: flush ? "gap-4" : void 0, children: [
63
+ eyebrow !== void 0 ? /* @__PURE__ */ jsx(
64
+ "span",
65
+ {
66
+ className: cn(
67
+ "text-tiny font-semibold tracking-label uppercase",
68
+ danger ? "text-destructive" : "text-muted-foreground"
69
+ ),
70
+ children: eyebrow
71
+ }
72
+ ) : null,
73
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-3 pr-6", children: [
74
+ icon,
75
+ /* @__PURE__ */ jsx(
76
+ DialogTitle,
77
+ {
78
+ className: cn("truncate", danger && "text-destructive"),
79
+ children: title
80
+ }
81
+ )
82
+ ] }),
83
+ description !== void 0 ? /* @__PURE__ */ jsx(DialogDescription, { children: description }) : null
84
+ ] }),
85
+ /* @__PURE__ */ jsx(DialogBody, { className: flush ? "p-0" : void 0, children: /* @__PURE__ */ jsx(DialogFooterActionsContext.Provider, { value: actionsValue, children }) }),
86
+ footer !== void 0 && footer !== null || footerActions !== null ? /* @__PURE__ */ jsxs(DialogFooter, { flush, children: [
87
+ footer,
88
+ footerActions
89
+ ] }) : null
90
+ ]
91
+ }
92
+ ) });
93
+ }
94
+
95
+ export { AppDialog, DialogFooterActions };
96
+ //# sourceMappingURL=chunk-2BVZEYNW.js.map
97
+ //# sourceMappingURL=chunk-2BVZEYNW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/app-dialog.tsx"],"names":[],"mappings":"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","file":"chunk-2BVZEYNW.js","sourcesContent":["import {\n\tDialog,\n\tDialogBody,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from \"./dialog\"\nimport {\n\tDialogFooterActionsContext,\n\tuseDialogFooterActions,\n} from \"@hoardodile/ui/hooks/use-dialog-footer-actions\"\nimport { cn } from \"@hoardodile/ui/lib/utils\"\nimport {\n\ttype ReactNode,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\"\n\n/** Dialog width tiers: the 320–480 narrow slot plus\n the wide working tiers — edit hubs, pickers and selectors get\n real estate; confirmations never leave the narrow slot. */\nexport type AppDialogSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\"\n\nconst sizeClasses: Record<AppDialogSize, string> = {\n\tsm: \"sm:max-w-sm\",\n\tmd: \"sm:max-w-md\",\n\tlg: \"sm:max-w-2xl\",\n\txl: \"sm:max-w-3xl\",\n\t\"2xl\": \"sm:max-w-4xl\",\n}\n\nexport { useDialogFooterActions }\n\n/**\n * Declarative footer action: renders nothing in the body and contributes\n * the node to the surrounding dialog's footer (appended after the\n * dialog's own `footer` prop). Panels embed their primary action this way\n * so action buttons live in the footer, never in the body. Outside a\n * dialog (sheets, pickers) it renders nothing — callers keep their inline\n * action bar as the fallback.\n */\nexport function DialogFooterActions({ children }: { children: ReactNode }) {\n\tconst slot = useDialogFooterActions()\n\tuseEffect(() => {\n\t\tif (slot === null) return\n\t\tslot.setFooterActions(children)\n\t\treturn () => slot.setFooterActions(null)\n\t}, [slot, children])\n\treturn null\n}\n\nexport type AppDialogProps = Readonly<{\n\topen: boolean\n\tonOpenChange: (open: boolean) => void\n\ttitle: ReactNode\n\t/** Uppercase section marker above the title (feature dialogs). */\n\teyebrow?: ReactNode\n\t/** Leading icon tile in the title row (feature dialogs). */\n\ticon?: ReactNode\n\t/** Danger register — the title ink takes the destructive hue; the\n\t danger itself stays in copy and the confirm button. */\n\tdanger?: boolean\n\t/** Width tier; defaults to `md` (the narrow form slot). */\n\tsize?: AppDialogSize\n\t/**\n\t * Drops the body padding for workspace bodies that own their layout\n\t * edge to edge (the two-pane editors); the header keeps its padding\n\t * and the footer becomes a plain bottom bar.\n\t */\n\tflush?: boolean\n\tdescription?: ReactNode\n\tchildren: ReactNode\n\t/** Leading footer actions; body panels may append theirs via\n\t {@link DialogFooterActions}. */\n\tfooter?: ReactNode\n\tcontentClassName?: string\n\t/** Passed to dialog overlay (e.g. disable backdrop blur over WebGL). */\n\toverlayClassName?: string\n\t/** Fade-only motion — lighter than default slide/zoom when over heavy surfaces. */\n\tcontentMotion?: \"default\" | \"minimal\"\n\t/** Defaults to true. Set to false to honour native auto-focus (rare). */\n\tsuppressAutoFocus?: boolean\n\tcontentTestId?: string\n}>\n\n/**\n * Standard dialog shell. Wires up `Dialog`/`DialogContent`/`DialogHeader`/\n * `DialogTitle` and an optional eyebrow, icon, description and footer so\n * callers stop re-stating the boilerplate. Use {@link ConfirmDialog} for\n * the common \"cancel + primary action\" pattern.\n */\nexport function AppDialog(props: AppDialogProps) {\n\tconst {\n\t\topen,\n\t\tonOpenChange,\n\t\ttitle,\n\t\teyebrow,\n\t\ticon,\n\t\tdanger,\n\t\tsize,\n\t\tflush,\n\t\tdescription,\n\t\tchildren,\n\t\tfooter,\n\t\tcontentClassName,\n\t\toverlayClassName,\n\t\tcontentMotion,\n\t\tsuppressAutoFocus = true,\n\t\tcontentTestId,\n\t} = props\n\t// Focusing the first focusable element on open would steal the caret\n\t// from the page underneath, jump scroll position, and on iOS\n\t// occasionally pop the soft keyboard before the user even reaches an\n\t// input. Routing focus to the dialog container itself keeps the\n\t// dialog accessible without those side effects.\n\tconst contentRef = useRef<HTMLDivElement | null>(null)\n\n\t// Footer actions contributed by body panels (DialogFooterActions):\n\t// appended after the dialog's own footer, reset when the dialog closes.\n\tconst [footerActions, setFooterActions] = useState<ReactNode>(null)\n\tconst actionsValue = useMemo(\n\t\t() => ({ setFooterActions }),\n\t\t[setFooterActions],\n\t)\n\n\treturn (\n\t\t<Dialog open={open} onOpenChange={onOpenChange}>\n\t\t\t<DialogContent\n\t\t\t\tref={contentRef}\n\t\t\t\tclassName={cn(\n\t\t\t\t\tsize !== undefined && sizeClasses[size],\n\t\t\t\t\tflush && \"p-0\",\n\t\t\t\t\tcontentClassName,\n\t\t\t\t)}\n\t\t\t\toverlayClassName={overlayClassName}\n\t\t\t\tcontentMotion={contentMotion}\n\t\t\t\tinitialFocus={suppressAutoFocus ? contentRef : undefined}\n\t\t\t\tdata-testid={contentTestId}\n\t\t\t>\n\t\t\t\t<DialogHeader className={flush ? \"gap-4\" : undefined}>\n\t\t\t\t\t{eyebrow !== undefined ? (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"text-tiny font-semibold tracking-label uppercase\",\n\t\t\t\t\t\t\t\tdanger ? \"text-destructive\" : \"text-muted-foreground\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{eyebrow}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<div className=\"flex min-w-0 items-center gap-3 pr-6\">\n\t\t\t\t\t\t{icon}\n\t\t\t\t\t\t<DialogTitle\n\t\t\t\t\t\t\tclassName={cn(\"truncate\", danger && \"text-destructive\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t</DialogTitle>\n\t\t\t\t\t</div>\n\t\t\t\t\t{description !== undefined ? (\n\t\t\t\t\t\t<DialogDescription>{description}</DialogDescription>\n\t\t\t\t\t) : null}\n\t\t\t\t</DialogHeader>\n\t\t\t\t{/* The header, body and footer must stay direct children of\n\t\t\t\t DialogContent — its arrangement logic recognises them by\n\t\t\t\t type, and a wrapper in between would re-wrap the body in a\n\t\t\t\t second DialogBody. The footer-actions context therefore\n\t\t\t\t wraps only the body's own content. */}\n\t\t\t\t<DialogBody className={flush ? \"p-0\" : undefined}>\n\t\t\t\t\t<DialogFooterActionsContext.Provider value={actionsValue}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</DialogFooterActionsContext.Provider>\n\t\t\t\t</DialogBody>\n\t\t\t\t{(footer !== undefined && footer !== null) ||\n\t\t\t\tfooterActions !== null ? (\n\t\t\t\t\t<DialogFooter flush={flush}>\n\t\t\t\t\t\t{footer}\n\t\t\t\t\t\t{footerActions}\n\t\t\t\t\t</DialogFooter>\n\t\t\t\t) : null}\n\t\t\t</DialogContent>\n\t\t</Dialog>\n\t)\n}\n"]}
@@ -0,0 +1,47 @@
1
+ import { isSpecialTagStyle, computeTagChipColors } from './chunk-AEHTAUAQ.js';
2
+ import { getSpecialTagStyleConfig } from './chunk-GKSX5ULZ.js';
3
+ import { cn } from './chunk-M5OJN54O.js';
4
+
5
+ // src/lib/tag-surface.ts
6
+ function resolveTagChipSurface(color, active) {
7
+ if (isSpecialTagStyle(color)) {
8
+ const config = getSpecialTagStyleConfig(color);
9
+ return {
10
+ className: cn(
11
+ "relative isolate group",
12
+ config.default.className,
13
+ active ? config.active?.className : void 0
14
+ ),
15
+ style: {
16
+ ...config.default.style,
17
+ ...active ? config.active?.style : {}
18
+ },
19
+ texture: color
20
+ };
21
+ }
22
+ if (color === "") {
23
+ return active ? {
24
+ className: "bg-primary text-primary-foreground hover:bg-primary/90",
25
+ style: void 0,
26
+ texture: null
27
+ } : {
28
+ className: "bg-muted text-foreground hover:bg-accent",
29
+ style: void 0,
30
+ texture: null
31
+ };
32
+ }
33
+ const chipColors = computeTagChipColors(color);
34
+ return {
35
+ className: "bg-(--chip-bg) hover:bg-(--chip-hover-bg)",
36
+ style: {
37
+ ["--chip-bg"]: active ? chipColors.hoverBg : chipColors.baseBg,
38
+ ["--chip-hover-bg"]: chipColors.hoverBg,
39
+ color: chipColors.fg
40
+ },
41
+ texture: null
42
+ };
43
+ }
44
+
45
+ export { resolveTagChipSurface };
46
+ //# sourceMappingURL=chunk-2DTR6CD5.js.map
47
+ //# sourceMappingURL=chunk-2DTR6CD5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/tag-surface.ts"],"names":[],"mappings":";;;;;AA0BO,SAAS,qBAAA,CACf,OACA,MAAA,EACyB;AACzB,EAAA,IAAI,iBAAA,CAAkB,KAAK,CAAA,EAAG;AAC7B,IAAA,MAAM,MAAA,GAAS,yBAAyB,KAAK,CAAA;AAC7C,IAAA,OAAO;AAAA,MACN,SAAA,EAAW,EAAA;AAAA,QACV,wBAAA;AAAA,QACA,OAAO,OAAA,CAAQ,SAAA;AAAA,QACf,MAAA,GAAS,MAAA,CAAO,MAAA,EAAQ,SAAA,GAAY;AAAA,OACrC;AAAA,MACA,KAAA,EAAO;AAAA,QACN,GAAG,OAAO,OAAA,CAAQ,KAAA;AAAA,QAClB,GAAI,MAAA,GAAS,MAAA,CAAO,MAAA,EAAQ,QAAQ;AAAC,OACtC;AAAA,MACA,OAAA,EAAS;AAAA,KACV;AAAA,EACD;AAEA,EAAA,IAAI,UAAU,EAAA,EAAI;AACjB,IAAA,OAAO,MAAA,GACJ;AAAA,MACA,SAAA,EAAW,wDAAA;AAAA,MACX,KAAA,EAAO,MAAA;AAAA,MACP,OAAA,EAAS;AAAA,KACV,GACC;AAAA,MACA,SAAA,EAAW,0CAAA;AAAA,MACX,KAAA,EAAO,MAAA;AAAA,MACP,OAAA,EAAS;AAAA,KACV;AAAA,EACH;AAEA,EAAA,MAAM,UAAA,GAAa,qBAAqB,KAAK,CAAA;AAC7C,EAAA,OAAO;AAAA,IACN,SAAA,EAAW,2CAAA;AAAA,IACX,KAAA,EAAO;AAAA,MACN,CAAC,WAAqB,GAAG,MAAA,GAAS,UAAA,CAAW,UAAU,UAAA,CAAW,MAAA;AAAA,MAClE,CAAC,iBAA2B,GAAG,UAAA,CAAW,OAAA;AAAA,MAC1C,OAAO,UAAA,CAAW;AAAA,KACnB;AAAA,IACA,OAAA,EAAS;AAAA,GACV;AACD","file":"chunk-2DTR6CD5.js","sourcesContent":["import { getSpecialTagStyleConfig } from \"@hoardodile/ui/components/special-tag-surface\"\nimport {\n\tcomputeTagChipColors,\n\tisSpecialTagStyle,\n\ttype TagSpecialStyle,\n} from \"@hoardodile/ui/lib/colors\"\nimport { cn } from \"@hoardodile/ui/lib/utils\"\nimport type { CSSProperties } from \"react\"\n\nexport type ResolvedTagChipSurface = {\n\treadonly className: string\n\treadonly style: CSSProperties | undefined\n\t/** The special SVG texture to layer under the chip's content, or null. */\n\treadonly texture: TagSpecialStyle | null\n}\n\n/**\n * Resolves a chip's visual surface for a user-assigned color — the single\n * source of chip coloring shared by every tag/category pill in the app.\n *\n * A plain color tints the whole chip (a 6% wash as fill, the color as ink,\n * deepening to the hover tint when `active`); the five special styles\n * (silver, gold, rainbow, oilslick, kintsugi) render their SVG texture;\n * an empty color falls back to the default muted chip, taking the primary\n * fill when `active`.\n */\nexport function resolveTagChipSurface(\n\tcolor: string,\n\tactive: boolean,\n): ResolvedTagChipSurface {\n\tif (isSpecialTagStyle(color)) {\n\t\tconst config = getSpecialTagStyleConfig(color)\n\t\treturn {\n\t\t\tclassName: cn(\n\t\t\t\t\"relative isolate group\",\n\t\t\t\tconfig.default.className,\n\t\t\t\tactive ? config.active?.className : undefined,\n\t\t\t),\n\t\t\tstyle: {\n\t\t\t\t...config.default.style,\n\t\t\t\t...(active ? config.active?.style : {}),\n\t\t\t},\n\t\t\ttexture: color,\n\t\t}\n\t}\n\n\tif (color === \"\") {\n\t\treturn active\n\t\t\t? {\n\t\t\t\t\tclassName: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n\t\t\t\t\tstyle: undefined,\n\t\t\t\t\ttexture: null,\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tclassName: \"bg-muted text-foreground hover:bg-accent\",\n\t\t\t\t\tstyle: undefined,\n\t\t\t\t\ttexture: null,\n\t\t\t\t}\n\t}\n\n\tconst chipColors = computeTagChipColors(color)\n\treturn {\n\t\tclassName: \"bg-(--chip-bg) hover:bg-(--chip-hover-bg)\",\n\t\tstyle: {\n\t\t\t[\"--chip-bg\" as string]: active ? chipColors.hoverBg : chipColors.baseBg,\n\t\t\t[\"--chip-hover-bg\" as string]: chipColors.hoverBg,\n\t\t\tcolor: chipColors.fg,\n\t\t},\n\t\ttexture: null,\n\t}\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import { extendTailwindMerge } from 'tailwind-merge';
2
+
3
+ // src/lib/merge-config.ts
4
+ var mergeTheme = {
5
+ text: ["tiny", "ui", "doc", "doc-title", "doc-heading", "quote"],
6
+ spacing: ["chip", "control", "nav", "sidebar", "panel"],
7
+ tracking: ["label"],
8
+ shadow: ["card", "dialog"],
9
+ container: ["reading", "medium", "content"],
10
+ font: ["doc", "heading"],
11
+ ease: ["standard"],
12
+ animate: ["skel", "pop"]
13
+ };
14
+ var twMerge = extendTailwindMerge({
15
+ extend: { theme: mergeTheme }
16
+ });
17
+
18
+ export { mergeTheme, twMerge };
19
+ //# sourceMappingURL=chunk-2HWSCY4T.js.map
20
+ //# sourceMappingURL=chunk-2HWSCY4T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/merge-config.ts"],"names":[],"mappings":";;;AAQO,IAAM,UAAA,GAAa;AAAA,EACzB,MAAM,CAAC,MAAA,EAAQ,MAAM,KAAA,EAAO,WAAA,EAAa,eAAe,OAAO,CAAA;AAAA,EAC/D,SAAS,CAAC,MAAA,EAAQ,SAAA,EAAW,KAAA,EAAO,WAAW,OAAO,CAAA;AAAA,EACtD,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,EAClB,MAAA,EAAQ,CAAC,MAAA,EAAQ,QAAQ,CAAA;AAAA,EACzB,SAAA,EAAW,CAAC,SAAA,EAAW,QAAA,EAAU,SAAS,CAAA;AAAA,EAC1C,IAAA,EAAM,CAAC,KAAA,EAAO,SAAS,CAAA;AAAA,EACvB,IAAA,EAAM,CAAC,UAAU,CAAA;AAAA,EACjB,OAAA,EAAS,CAAC,MAAA,EAAQ,KAAK;AACxB;AAEO,IAAM,UAAU,mBAAA,CAAoB;AAAA,EAC1C,MAAA,EAAQ,EAAE,KAAA,EAAO,UAAA;AAClB,CAAC","file":"chunk-2HWSCY4T.js","sourcesContent":["import { extendTailwindMerge } from \"tailwind-merge\"\n\n// The app's `@theme inline` tokens (theme.css) generate utility names\n// tailwind-merge doesn't know, so it misclassifies them — e.g. `text-ui` is\n// parsed as a text color and dropped next to any `text-*` color. The default\n// class groups are theme-backed, so extending the theme (keys mirror the v4\n// token namespaces one-to-one) registers every custom utility with correct\n// conflict semantics. merge-config.test.ts pins this list against theme.css.\nexport const mergeTheme = {\n\ttext: [\"tiny\", \"ui\", \"doc\", \"doc-title\", \"doc-heading\", \"quote\"],\n\tspacing: [\"chip\", \"control\", \"nav\", \"sidebar\", \"panel\"],\n\ttracking: [\"label\"],\n\tshadow: [\"card\", \"dialog\"],\n\tcontainer: [\"reading\", \"medium\", \"content\"],\n\tfont: [\"doc\", \"heading\"],\n\tease: [\"standard\"],\n\tanimate: [\"skel\", \"pop\"],\n} as const\n\nexport const twMerge = extendTailwindMerge({\n\textend: { theme: mergeTheme },\n})\n"]}
@@ -0,0 +1,75 @@
1
+ import { Icon } from './chunk-TMQ5OMBK.js';
2
+ import { Magnifier } from './chunk-7MWWHI6T.js';
3
+ import { cn } from './chunk-M5OJN54O.js';
4
+ import { useState, useEffect } from 'react';
5
+ import { useDebounce } from 'react-use';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ function SearchField(props) {
9
+ const {
10
+ value,
11
+ placeholder,
12
+ className,
13
+ actions,
14
+ maxLength,
15
+ onCommit,
16
+ onSubmit,
17
+ commitOnEnterOnly,
18
+ delayMs,
19
+ inputRef,
20
+ testId
21
+ } = props;
22
+ const [draft, setDraft] = useState(value);
23
+ useEffect(() => {
24
+ setDraft(value);
25
+ }, [value]);
26
+ useDebounce(
27
+ () => {
28
+ if (commitOnEnterOnly) return;
29
+ if (draft !== value) onCommit?.(draft);
30
+ },
31
+ delayMs ?? 300,
32
+ [draft]
33
+ );
34
+ function handleKeyDown(event) {
35
+ if (event.key !== "Enter") return;
36
+ event.preventDefault();
37
+ if (commitOnEnterOnly) {
38
+ onSubmit?.(draft);
39
+ return;
40
+ }
41
+ if (draft !== value) onCommit?.(draft);
42
+ onSubmit?.(draft);
43
+ }
44
+ return /* @__PURE__ */ jsxs(
45
+ "div",
46
+ {
47
+ onKeyDown: handleKeyDown,
48
+ className: cn(
49
+ "flex h-nav items-center gap-2 rounded-lg bg-muted px-3",
50
+ className
51
+ ),
52
+ children: [
53
+ /* @__PURE__ */ jsx(Icon, { icon: Magnifier, className: "shrink-0 text-muted-foreground" }),
54
+ /* @__PURE__ */ jsx(
55
+ "input",
56
+ {
57
+ ref: inputRef,
58
+ type: "text",
59
+ value: draft,
60
+ onChange: (ev) => setDraft(ev.target.value),
61
+ placeholder,
62
+ maxLength,
63
+ className: "min-w-0 flex-1 bg-transparent text-ui text-foreground outline-none placeholder:text-muted-foreground",
64
+ "data-testid": testId ?? "global-search-input"
65
+ }
66
+ ),
67
+ actions
68
+ ]
69
+ }
70
+ );
71
+ }
72
+
73
+ export { SearchField };
74
+ //# sourceMappingURL=chunk-363CCKQ7.js.map
75
+ //# sourceMappingURL=chunk-363CCKQ7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/search-field.tsx"],"names":[],"mappings":";;;;;;;AAwDO,SAAS,YAAY,KAAA,EAAyB;AACpD,EAAA,MAAM;AAAA,IACL,KAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA,iBAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACD,GAAI,KAAA;AACJ,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,KAAK,CAAA;AAExC,EAAA,SAAA,CAAU,MAAM;AACf,IAAA,QAAA,CAAS,KAAK,CAAA;AAAA,EACf,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,WAAA;AAAA,IACC,MAAM;AACL,MAAA,IAAI,iBAAA,EAAmB;AACvB,MAAA,IAAI,KAAA,KAAU,KAAA,EAAO,QAAA,GAAW,KAAK,CAAA;AAAA,IACtC,CAAA;AAAA,IACA,OAAA,IAAW,GAAA;AAAA,IACX,CAAC,KAAK;AAAA,GACP;AAEA,EAAA,SAAS,cAAc,KAAA,EAAwC;AAC9D,IAAA,IAAI,KAAA,CAAM,QAAQ,OAAA,EAAS;AAC3B,IAAA,KAAA,CAAM,cAAA,EAAe;AACrB,IAAA,IAAI,iBAAA,EAAmB;AACtB,MAAA,QAAA,GAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACD;AACA,IAAA,IAAI,KAAA,KAAU,KAAA,EAAO,QAAA,GAAW,KAAK,CAAA;AACrC,IAAA,QAAA,GAAW,KAAK,CAAA;AAAA,EACjB;AAEA,EAAA,uBACC,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,SAAA,EAAW,aAAA;AAAA,MACX,SAAA,EAAW,EAAA;AAAA,QACV,wDAAA;AAAA,QACA;AAAA,OACD;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,SAAA,EAAW,SAAA,EAAU,gCAAA,EAAiC,CAAA;AAAA,wBAClE,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACA,GAAA,EAAK,QAAA;AAAA,YACL,IAAA,EAAK,MAAA;AAAA,YACL,KAAA,EAAO,KAAA;AAAA,YACP,UAAU,CAAC,EAAA,KAAO,QAAA,CAAS,EAAA,CAAG,OAAO,KAAK,CAAA;AAAA,YAC1C,WAAA;AAAA,YACA,SAAA;AAAA,YACA,SAAA,EAAU,sGAAA;AAAA,YACV,eAAa,MAAA,IAAU;AAAA;AAAA,SACxB;AAAA,QACC;AAAA;AAAA;AAAA,GACF;AAEF","file":"chunk-363CCKQ7.js","sourcesContent":["import { Icon } from \"@hoardodile/ui/components/icon\"\nimport { Magnifier } from \"@hoardodile/ui/icons/registry\"\nimport { cn } from \"@hoardodile/ui/lib/utils\"\nimport {\n\ttype KeyboardEvent,\n\ttype ReactNode,\n\ttype Ref,\n\tuseEffect,\n\tuseState,\n} from \"react\"\nimport { useDebounce } from \"react-use\"\n\nexport type SearchFieldProps = {\n\t/** The committed value; the input re-syncs to it on external changes. */\n\treadonly value: string\n\treadonly placeholder?: string\n\t/**\n\t * Layout overrides — the hero form passes `h-11 px-4` (the sidebar\n\t * h-nav and the hero h-11 share one anatomy).\n\t */\n\treadonly className?: string\n\t/** Optional actions rendered at the trailing edge of the field. */\n\treadonly actions?: ReactNode\n\t/** Input length cap (e.g. the app's max search-query length). */\n\treadonly maxLength?: number\n\t/**\n\t * Debounced commit of the draft (unless {@link commitOnEnterOnly}).\n\t * Filter bars pass their live patch here.\n\t */\n\treadonly onCommit?: (value: string) => void\n\t/** Enter / form submit — navigation and apply-on-demand surfaces. */\n\treadonly onSubmit?: (value: string) => void\n\t/**\n\t * When true, keystrokes never debounce-commit; the value is delivered\n\t * only through {@link onSubmit} (Enter). Used by apply-on-demand\n\t * surfaces where typing stages and Enter applies.\n\t */\n\treadonly commitOnEnterOnly?: boolean\n\treadonly delayMs?: number\n\t/** Optional ref to the inner input (sidebar \"/\" and Ctrl/Cmd+K). */\n\treadonly inputRef?: Ref<HTMLInputElement>\n\treadonly testId?: string\n}\n\n/**\n * The one search field: muted fill, rounded-lg, leading magnifier,\n * muted placeholder — sidebar (h-nav) and hero (h-11) share this\n * anatomy, as do the index-page filter bars. Commit semantics are the\n * caller's: debounced {@link onCommit} for live filtering, Enter through\n * {@link onSubmit} for navigation and apply-on-demand surfaces.\n *\n * The root is a div, not a form: the field nests inside page forms (the\n * new character/resource editors, which wrap their whole body in one), so\n * a nested form would be invalid HTML. Enter is captured on keydown and\n * preventDefaulted, so it never submits an enclosing form either.\n */\nexport function SearchField(props: SearchFieldProps) {\n\tconst {\n\t\tvalue,\n\t\tplaceholder,\n\t\tclassName,\n\t\tactions,\n\t\tmaxLength,\n\t\tonCommit,\n\t\tonSubmit,\n\t\tcommitOnEnterOnly,\n\t\tdelayMs,\n\t\tinputRef,\n\t\ttestId,\n\t} = props\n\tconst [draft, setDraft] = useState(value)\n\n\tuseEffect(() => {\n\t\tsetDraft(value)\n\t}, [value])\n\n\tuseDebounce(\n\t\t() => {\n\t\t\tif (commitOnEnterOnly) return\n\t\t\tif (draft !== value) onCommit?.(draft)\n\t\t},\n\t\tdelayMs ?? 300,\n\t\t[draft],\n\t)\n\n\tfunction handleKeyDown(event: KeyboardEvent<HTMLInputElement>) {\n\t\tif (event.key !== \"Enter\") return\n\t\tevent.preventDefault()\n\t\tif (commitOnEnterOnly) {\n\t\t\tonSubmit?.(draft)\n\t\t\treturn\n\t\t}\n\t\tif (draft !== value) onCommit?.(draft)\n\t\tonSubmit?.(draft)\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tonKeyDown={handleKeyDown}\n\t\t\tclassName={cn(\n\t\t\t\t\"flex h-nav items-center gap-2 rounded-lg bg-muted px-3\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<Icon icon={Magnifier} className=\"shrink-0 text-muted-foreground\" />\n\t\t\t<input\n\t\t\t\tref={inputRef}\n\t\t\t\ttype=\"text\"\n\t\t\t\tvalue={draft}\n\t\t\t\tonChange={(ev) => setDraft(ev.target.value)}\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\tmaxLength={maxLength}\n\t\t\t\tclassName=\"min-w-0 flex-1 bg-transparent text-ui text-foreground outline-none placeholder:text-muted-foreground\"\n\t\t\t\tdata-testid={testId ?? \"global-search-input\"}\n\t\t\t/>\n\t\t\t{actions}\n\t\t</div>\n\t)\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import { Check } from './chunk-XBPQEZES.js';
2
+ import { cn } from './chunk-M5OJN54O.js';
3
+ import { Checkbox as Checkbox$1 } from '@base-ui/react/checkbox';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ function Checkbox({ className, ...props }) {
7
+ return /* @__PURE__ */ jsx(
8
+ Checkbox$1.Root,
9
+ {
10
+ "data-slot": "checkbox",
11
+ className: cn(
12
+ "peer relative flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-sm bg-muted outline-none group-has-disabled/field:opacity-50 focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:bg-destructive/20 aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-checked:bg-primary data-checked:text-primary-foreground",
13
+ className
14
+ ),
15
+ ...props,
16
+ children: /* @__PURE__ */ jsx(
17
+ Checkbox$1.Indicator,
18
+ {
19
+ "data-slot": "checkbox-indicator",
20
+ className: "grid place-content-center text-current [&>svg]:size-3",
21
+ children: /* @__PURE__ */ jsx(Check, {})
22
+ }
23
+ )
24
+ }
25
+ );
26
+ }
27
+
28
+ export { Checkbox };
29
+ //# sourceMappingURL=chunk-3ZQJWBVB.js.map
30
+ //# sourceMappingURL=chunk-3ZQJWBVB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/checkbox.tsx"],"names":["CheckboxPrimitive"],"mappings":";;;;;AAOA,SAAS,QAAA,CAAS,EAAE,SAAA,EAAW,GAAG,OAAM,EAAiC;AACvE,EAAA,uBACE,GAAA;AAAA,IAACA,UAAA,CAAkB,IAAA;AAAA,IAAlB;AAAA,MACC,WAAA,EAAU,UAAA;AAAA,MACV,SAAA,EAAW,EAAA;AAAA,QACT,qYAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA;AAAA,QAACA,UAAA,CAAkB,SAAA;AAAA,QAAlB;AAAA,UACC,WAAA,EAAU,oBAAA;AAAA,UACV,SAAA,EAAU,uDAAA;AAAA,UAEV,8BAAC,KAAA,EAAA,EAAM;AAAA;AAAA;AACT;AAAA,GACF;AAEJ","file":"chunk-3ZQJWBVB.js","sourcesContent":["\"use client\"\n\nimport { Checkbox as CheckboxPrimitive } from \"@base-ui/react/checkbox\"\n\nimport { cn } from \"@hoardodile/ui/lib/utils\"\nimport { Check } from \"@hoardodile/ui/icons/marks\"\n\nfunction Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n \"peer relative flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-sm bg-muted outline-none group-has-disabled/field:opacity-50 focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:bg-destructive/20 aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-checked:bg-primary data-checked:text-primary-foreground\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"grid place-content-center text-current [&>svg]:size-3\"\n >\n <Check />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport { Checkbox }\n"]}
@@ -0,0 +1,277 @@
1
+ import { parseIconRef } from './chunk-POX7TXBH.js';
2
+ import { formatClockDuration, formatBytes } from './chunk-UEVND7AS.js';
3
+ import { parseTemplateFragments, parseTemplateExpression } from '@hoardodile/sdk-types/template';
4
+
5
+ function resolvePath(segments, scope) {
6
+ const [namespace, ...rest] = segments;
7
+ const root = namespace === "file" ? scope.file : namespace === "searchMeta" ? scope.searchMeta : namespace === "data" ? scope.data : namespace === "coverMeta" ? scope.coverMeta : scope.source;
8
+ if (root === void 0 || root === null) return void 0;
9
+ let current = root;
10
+ for (const key of rest) {
11
+ if (typeof current !== "object" || current === null) return void 0;
12
+ current = current[key];
13
+ }
14
+ return current;
15
+ }
16
+ function resolveLocaleString(value, locale) {
17
+ if (typeof value === "string") return value;
18
+ const exact = value[locale];
19
+ if (exact !== void 0) return exact;
20
+ const base = locale.split("-")[0] ?? locale;
21
+ const partial = value[base];
22
+ if (partial !== void 0) return partial;
23
+ const first = Object.values(value)[0];
24
+ return first ?? "";
25
+ }
26
+ function evaluateExpression(expr, scope, ctx) {
27
+ if (expr.kind === "path") {
28
+ const value = resolvePath(expr.segments, scope);
29
+ if (value === void 0 || value === null) return "";
30
+ return String(value);
31
+ }
32
+ return evaluateCall(expr.name, expr.args, scope, ctx);
33
+ }
34
+ function evaluateCall(name, args, scope, ctx) {
35
+ switch (name) {
36
+ case "bytes":
37
+ return callPipe(
38
+ args,
39
+ scope,
40
+ ctx,
41
+ (value) => typeof value === "number" ? formatBytes(value) : ""
42
+ );
43
+ case "duration":
44
+ return callPipe(
45
+ args,
46
+ scope,
47
+ ctx,
48
+ (value) => typeof value === "number" ? formatClockDuration(value) : ""
49
+ );
50
+ case "number":
51
+ return callPipe(
52
+ args,
53
+ scope,
54
+ ctx,
55
+ (value) => typeof value === "number" && Number.isFinite(value) ? value.toLocaleString() : ""
56
+ );
57
+ case "inc":
58
+ return callPipe(
59
+ args,
60
+ scope,
61
+ ctx,
62
+ (value) => typeof value === "number" && Number.isFinite(value) ? String(value + 1) : ""
63
+ );
64
+ case "eq":
65
+ return compareCall(args, scope, ctx, (a, b) => a === b);
66
+ case "ne":
67
+ return compareCall(args, scope, ctx, (a, b) => a !== b);
68
+ case "gt":
69
+ return compareCall(args, scope, ctx, (a, b) => {
70
+ if (typeof a !== "number" || typeof b !== "number") return false;
71
+ return a > b;
72
+ });
73
+ case "lt":
74
+ return compareCall(args, scope, ctx, (a, b) => {
75
+ if (typeof a !== "number" || typeof b !== "number") return false;
76
+ return a < b;
77
+ });
78
+ case "gte":
79
+ return compareCall(args, scope, ctx, (a, b) => {
80
+ if (typeof a !== "number" || typeof b !== "number") return false;
81
+ return a >= b;
82
+ });
83
+ case "lte":
84
+ return compareCall(args, scope, ctx, (a, b) => {
85
+ if (typeof a !== "number" || typeof b !== "number") return false;
86
+ return a <= b;
87
+ });
88
+ case "if":
89
+ return callIf(args, scope, ctx);
90
+ case "t":
91
+ return callT(args, ctx);
92
+ case "icon":
93
+ return callIcon(args, ctx);
94
+ case "asset":
95
+ return callAsset(args, ctx);
96
+ case "kind":
97
+ return callKind(args, scope, ctx);
98
+ case "searchKindIcons":
99
+ return callSearchKindIcons(scope, ctx);
100
+ case "join":
101
+ return callJoin(args, scope, ctx);
102
+ default:
103
+ return "";
104
+ }
105
+ }
106
+ function callPipe(args, scope, ctx, pipeFn) {
107
+ const value = evaluateArgAsPrimitive(args[0], scope, ctx);
108
+ return pipeFn(value);
109
+ }
110
+ function callT(args, ctx) {
111
+ const key = evaluateArgAsString(args[0]);
112
+ if (key.length === 0) return "";
113
+ const map = ctx.manifest.i18n;
114
+ if (map === void 0) return "";
115
+ const value = map[key];
116
+ if (value === void 0) return "";
117
+ return resolveLocaleString(value, ctx.locale);
118
+ }
119
+ function callIcon(args, ctx) {
120
+ const name = evaluateArgAsString(args[0]);
121
+ if (name.length === 0) return null;
122
+ return ctx.renderIcon({ kind: "icon", name }, ctx.iconClassName);
123
+ }
124
+ function callAsset(args, ctx) {
125
+ const path = evaluateArgAsString(args[0]);
126
+ if (path.length === 0) return null;
127
+ const ref = parseIconRef(path, ctx.pluginId, ctx.buildAssetUrl);
128
+ if (ref === void 0) return null;
129
+ return ctx.renderIcon(ref, ctx.iconClassName);
130
+ }
131
+ function callKind(args, scope, ctx) {
132
+ const key = evaluateArgAsString(args[0]);
133
+ if (key.length === 0) return null;
134
+ const kinds = ctx.manifest.ui?.search?.kinds;
135
+ if (kinds === void 0) return null;
136
+ const match = kinds.find((k) => k.key === key);
137
+ if (match === void 0 || match.icon === void 0) return null;
138
+ const rendered = renderCardTemplate(match.icon, scope, ctx);
139
+ if (rendered === null || rendered === void 0 || rendered === "")
140
+ return null;
141
+ return rendered;
142
+ }
143
+ function callSearchKindIcons(scope, ctx) {
144
+ if (scope.searchMeta === void 0 || scope.searchMeta === null || typeof scope.searchMeta !== "object")
145
+ return [];
146
+ const facets = scope.searchMeta.facets;
147
+ if (facets === void 0 || typeof facets !== "object" || facets === null)
148
+ return [];
149
+ const kinds = ctx.manifest.ui?.search?.kinds;
150
+ if (kinds === void 0) return [];
151
+ const results = [];
152
+ for (const kind of kinds) {
153
+ if (kind.icon === void 0) continue;
154
+ const active = facets[kind.key];
155
+ if (active !== true) continue;
156
+ const rendered = renderCardTemplate(kind.icon, scope, ctx);
157
+ if (rendered === null || rendered === void 0 || rendered === "") continue;
158
+ results.push(rendered);
159
+ }
160
+ return results;
161
+ }
162
+ function callJoin(args, scope, ctx) {
163
+ if (args.length === 0) return "";
164
+ const separator = evaluateArgAsString(args[0]);
165
+ const items = [];
166
+ for (let i = 1; i < args.length; i++) {
167
+ const val = evaluateArg(args[i], scope, ctx);
168
+ if (Array.isArray(val)) {
169
+ for (const item of val) {
170
+ if (item !== null && item !== void 0 && item !== "") {
171
+ items.push(item);
172
+ }
173
+ }
174
+ continue;
175
+ }
176
+ if (val !== null && val !== void 0 && val !== "") {
177
+ items.push(val);
178
+ }
179
+ }
180
+ if (items.length === 0) return "";
181
+ if (items.every((item) => typeof item === "string")) {
182
+ return items.join(separator);
183
+ }
184
+ if (separator.length === 0) return items;
185
+ const interleaved = [];
186
+ for (let i = 0; i < items.length; i++) {
187
+ if (i > 0) interleaved.push(separator);
188
+ interleaved.push(items[i]);
189
+ }
190
+ return interleaved;
191
+ }
192
+ function evaluateArgAsPrimitive(arg, scope, ctx) {
193
+ if (arg === void 0) return void 0;
194
+ if (arg.kind === "string") return arg.value;
195
+ if (arg.expr.kind === "path") {
196
+ const segments = arg.expr.segments;
197
+ if (segments.length === 1) {
198
+ const seg = segments[0];
199
+ const num = Number(seg);
200
+ if (!Number.isNaN(num)) return num;
201
+ }
202
+ return resolvePath(segments, scope);
203
+ }
204
+ if (arg.expr.kind === "call") {
205
+ const result = evaluateCall(arg.expr.name, arg.expr.args, scope, ctx);
206
+ if (typeof result === "string" || typeof result === "number") return result;
207
+ if (Array.isArray(result)) return result;
208
+ return void 0;
209
+ }
210
+ return void 0;
211
+ }
212
+ function evaluateArg(arg, scope, ctx) {
213
+ if (arg === void 0) return void 0;
214
+ if (arg.kind === "string") return arg.value;
215
+ return evaluateExpression(arg.expr, scope, ctx);
216
+ }
217
+ function compareCall(args, scope, ctx, cmp) {
218
+ const a = evaluateArgAsPrimitive(args[0], scope, ctx);
219
+ const b = evaluateArgAsPrimitive(args[1], scope, ctx);
220
+ return cmp(a, b) ? "true" : "";
221
+ }
222
+ function callIf(args, scope, ctx) {
223
+ const cond = evaluateArgAsPrimitive(args[0], scope, ctx);
224
+ const truthy = cond !== void 0 && cond !== null && cond !== "" && cond !== false && cond !== 0;
225
+ if (truthy) {
226
+ const raw = evaluateArgAsPrimitive(args[1], scope, ctx);
227
+ if (raw !== void 0) return raw;
228
+ return evaluateArg(args[1], scope, ctx);
229
+ }
230
+ if (args.length > 2) {
231
+ const raw = evaluateArgAsPrimitive(args[2], scope, ctx);
232
+ if (raw !== void 0) return raw;
233
+ return evaluateArg(args[2], scope, ctx);
234
+ }
235
+ return "";
236
+ }
237
+ function evaluateArgAsString(arg) {
238
+ if (arg === void 0) return "";
239
+ if (arg.kind === "string") return arg.value;
240
+ return "";
241
+ }
242
+ function renderCardTemplate(template, scope, ctx) {
243
+ if (template.length === 0) return "";
244
+ const fragments = parseTemplateFragments(template);
245
+ if (fragments.length === 0) return "";
246
+ const results = [];
247
+ for (const frag of fragments) {
248
+ if (frag.kind === "text") {
249
+ results.push(frag.value);
250
+ continue;
251
+ }
252
+ const expr = parseTemplateExpression(frag.source);
253
+ if (expr === void 0) {
254
+ continue;
255
+ }
256
+ const value = evaluateExpression(expr, scope, ctx);
257
+ if (value !== null && value !== void 0 && value !== "") {
258
+ results.push(value);
259
+ }
260
+ }
261
+ if (results.length === 0) return null;
262
+ if (results.length === 1) return results[0];
263
+ const allStrings = results.every((r) => typeof r === "string");
264
+ if (allStrings) return results.join("");
265
+ return results;
266
+ }
267
+ function renderSlotBadges(slotValues, scope, ctx) {
268
+ return slotValues.map((template) => renderCardTemplate(template, scope, ctx)).filter((n) => {
269
+ if (n === null || n === void 0 || n === "") return false;
270
+ if (Array.isArray(n) && n.length === 0) return false;
271
+ return true;
272
+ });
273
+ }
274
+
275
+ export { renderCardTemplate, renderSlotBadges, resolveLocaleString };
276
+ //# sourceMappingURL=chunk-4D36OO5W.js.map
277
+ //# sourceMappingURL=chunk-4D36OO5W.js.map