@scattered-light/loomiere-base-ui 0.6.1 → 0.7.0

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 (100) hide show
  1. package/README.md +135 -5
  2. package/dist/chunk-JUUPOOQQ.js +3723 -0
  3. package/dist/chunk-JUUPOOQQ.js.map +1 -0
  4. package/dist/chunk-M7KJASGK.js +802 -0
  5. package/dist/chunk-M7KJASGK.js.map +1 -0
  6. package/dist/chunk-Y2CPBMFJ.js +147 -0
  7. package/dist/chunk-Y2CPBMFJ.js.map +1 -0
  8. package/dist/custom/collection/index.d.ts +534 -0
  9. package/dist/custom/collection/index.js +1471 -0
  10. package/dist/custom/collection/index.js.map +1 -0
  11. package/dist/custom/index.d.ts +5 -0
  12. package/dist/custom/index.js +4 -0
  13. package/dist/custom/index.js.map +1 -0
  14. package/dist/design-system/components/Badge/README.md +35 -0
  15. package/dist/design-system/components/Badge/preview.html +19 -0
  16. package/dist/design-system/components/Collection/README.md +14 -0
  17. package/dist/design-system/components/CollectionPagination/README.md +15 -0
  18. package/dist/design-system/components/CollectionToolbar/README.md +24 -0
  19. package/dist/design-system/components/DataList/README.md +39 -0
  20. package/dist/design-system/components/DataList/preview.html +475 -0
  21. package/dist/design-system/components/DataTable/README.md +41 -0
  22. package/dist/design-system/components/DataTable/preview.html +475 -0
  23. package/dist/design-system/components/DatePicker/README.md +55 -0
  24. package/dist/design-system/components/DatePicker/preview.html +475 -0
  25. package/dist/design-system/components/EditableList/README.md +33 -0
  26. package/dist/design-system/components/EditableList/preview.html +475 -0
  27. package/dist/design-system/components/EmptyState/README.md +60 -0
  28. package/dist/design-system/components/EmptyState/preview.html +475 -0
  29. package/dist/design-system/components/ListDetail/README.md +43 -0
  30. package/dist/design-system/components/ListDetail/preview.html +475 -0
  31. package/dist/design-system/components/MoneyField/README.md +52 -0
  32. package/dist/design-system/components/MoneyField/preview.html +475 -0
  33. package/dist/design-system/components/Splitter/README.md +42 -0
  34. package/dist/design-system/components/Splitter/preview.html +475 -0
  35. package/dist/design-system/components/Table/README.md +2 -1
  36. package/dist/design-system/components/Table/preview.html +1 -1
  37. package/dist/design-system/components/bundle.js +7 -5
  38. package/dist/design-system/components/index.d.ts +3 -21
  39. package/dist/design-system/components/styles.css +2266 -186
  40. package/dist/index-ChJXlxzq.d.ts +809 -0
  41. package/dist/index.d.ts +3 -21
  42. package/dist/index.js +176 -891
  43. package/dist/index.js.map +1 -1
  44. package/dist/styles/components/Accordion.css +1 -1
  45. package/dist/styles/components/AlertDialog.css +1 -1
  46. package/dist/styles/components/Autocomplete.css +1 -1
  47. package/dist/styles/components/Avatar.css +1 -1
  48. package/dist/styles/components/Button.css +1 -1
  49. package/dist/styles/components/Checkbox.css +1 -1
  50. package/dist/styles/components/CheckboxGroup.css +1 -1
  51. package/dist/styles/components/Collapsible.css +1 -1
  52. package/dist/styles/components/Combobox.css +1 -1
  53. package/dist/styles/components/ContextMenu.css +1 -1
  54. package/dist/styles/components/Dialog.css +1 -1
  55. package/dist/styles/components/Drawer.css +1 -1
  56. package/dist/styles/components/Field.css +1 -1
  57. package/dist/styles/components/Fieldset.css +1 -1
  58. package/dist/styles/components/Form.css +1 -1
  59. package/dist/styles/components/Input.css +1 -1
  60. package/dist/styles/components/Menu.css +1 -1
  61. package/dist/styles/components/Menubar.css +1 -1
  62. package/dist/styles/components/Meter.css +1 -1
  63. package/dist/styles/components/NavigationMenu.css +1 -1
  64. package/dist/styles/components/NumberField.css +1 -1
  65. package/dist/styles/components/OTPField.css +1 -1
  66. package/dist/styles/components/Popover.css +1 -1
  67. package/dist/styles/components/PreviewCard.css +1 -1
  68. package/dist/styles/components/Progress.css +1 -1
  69. package/dist/styles/components/Radio.css +1 -1
  70. package/dist/styles/components/ScrollArea.css +1 -1
  71. package/dist/styles/components/Select.css +1 -1
  72. package/dist/styles/components/Separator.css +1 -1
  73. package/dist/styles/components/Slider.css +1 -1
  74. package/dist/styles/components/Switch.css +1 -1
  75. package/dist/styles/components/Tabs.css +1 -1
  76. package/dist/styles/components/Toast.css +1 -1
  77. package/dist/styles/components/Toggle.css +1 -1
  78. package/dist/styles/components/ToggleGroup.css +1 -1
  79. package/dist/styles/components/Toolbar.css +1 -1
  80. package/dist/styles/components/Tooltip.css +1 -1
  81. package/dist/styles/custom/Badge.css +104 -0
  82. package/dist/styles/custom/Collection.css +15 -0
  83. package/dist/styles/custom/CollectionPagination.css +24 -0
  84. package/dist/styles/custom/CollectionToolbar.css +57 -0
  85. package/dist/styles/custom/DataList.css +123 -0
  86. package/dist/styles/custom/DataTable.css +120 -0
  87. package/dist/styles/custom/DatePicker.css +572 -0
  88. package/dist/styles/custom/EditableList.css +98 -0
  89. package/dist/styles/custom/EmptyState.css +255 -0
  90. package/dist/styles/custom/ListDetail.css +126 -0
  91. package/dist/styles/custom/MoneyField.css +344 -0
  92. package/dist/styles/custom/Splitter.css +207 -0
  93. package/dist/styles/{components → custom}/Table.css +31 -4
  94. package/dist/styles/index.css +12 -2
  95. package/dist/styles/reset/accessibility.css +1 -1
  96. package/dist/styles/reset/reset-accessibility.css +1 -1
  97. package/dist/styles/reset/reset-tailwind.css +1 -1
  98. package/dist/styles/reset/reset.css +1 -1
  99. package/dist/styles/tailwind.css +12 -2
  100. package/package.json +35 -7
@@ -0,0 +1,802 @@
1
+ import * as React4 from 'react';
2
+ import { Button as Button$1 } from '@base-ui/react/button';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import { Select as Select$1 } from '@base-ui/react/select';
5
+ import { Combobox as Combobox$1 } from '@base-ui/react/combobox';
6
+
7
+ // src/utils/cn.ts
8
+ function cn(...inputs) {
9
+ const out = [];
10
+ for (const input of inputs) {
11
+ if (input == null || input === false) continue;
12
+ if (typeof input === "string" || typeof input === "number") {
13
+ out.push(String(input));
14
+ } else if (Array.isArray(input)) {
15
+ const inner = cn(...input);
16
+ if (inner) out.push(inner);
17
+ } else if (typeof input === "object") {
18
+ for (const [k, v] of Object.entries(input)) {
19
+ if (v) out.push(k);
20
+ }
21
+ }
22
+ }
23
+ return out.join(" ");
24
+ }
25
+ function cnState(base, className, state) {
26
+ return cn(base, typeof className === "function" ? className(state) : className);
27
+ }
28
+ function styledPart(Base, displayName, baseClass) {
29
+ const Comp = React4.forwardRef(function StyledPart(props, ref) {
30
+ const { className, ...rest } = props;
31
+ return /* @__PURE__ */ jsx(
32
+ Base,
33
+ {
34
+ ref,
35
+ ...rest,
36
+ className: (state) => cnState(baseClass, className, state)
37
+ }
38
+ );
39
+ });
40
+ Comp.displayName = displayName;
41
+ return Comp;
42
+ }
43
+ function styledPartUnless(Base, displayName, baseClass, skipClass) {
44
+ const Comp = React4.forwardRef(function StyledPart(props, ref) {
45
+ const { className, ...rest } = props;
46
+ return /* @__PURE__ */ jsx(
47
+ Base,
48
+ {
49
+ ref,
50
+ ...rest,
51
+ className: (state) => {
52
+ const extra = typeof className === "function" ? className(state) : className;
53
+ const skip = extra?.split(/\s+/).includes(skipClass);
54
+ return cn(skip ? void 0 : baseClass, extra);
55
+ }
56
+ }
57
+ );
58
+ });
59
+ Comp.displayName = displayName;
60
+ return Comp;
61
+ }
62
+ function isIconOnly(children) {
63
+ const items = React4.Children.toArray(children);
64
+ return items.length === 1 && React4.isValidElement(items[0]);
65
+ }
66
+ function buttonPart(Base, displayName, { partClass, optIn = false, otherClass, skipClass } = {}) {
67
+ const Comp = React4.forwardRef(function ButtonPart(props, ref) {
68
+ const { className, emphasis, palette, ...rest } = props;
69
+ const asked = emphasis !== void 0 || palette !== void 0;
70
+ return /* @__PURE__ */ jsx(
71
+ Base,
72
+ {
73
+ ref,
74
+ "data-emphasis": emphasis,
75
+ "data-color": palette,
76
+ "data-icon-only": isIconOnly(rest.children) ? "" : void 0,
77
+ ...rest,
78
+ className: (state) => {
79
+ const extra = typeof className === "function" ? className(state) : className;
80
+ const classes = extra?.split(/\s+/) ?? [];
81
+ const isButton = !(skipClass && classes.includes(skipClass)) && (!optIn || asked || classes.includes("Button"));
82
+ return cn(
83
+ partClass,
84
+ isButton && !classes.includes("Button") ? "Button" : void 0,
85
+ isButton ? void 0 : otherClass,
86
+ extra
87
+ );
88
+ }
89
+ }
90
+ );
91
+ });
92
+ Comp.displayName = displayName;
93
+ return Comp;
94
+ }
95
+ var Button = React4.forwardRef(function Button2({ className, emphasis, palette, children, ...props }, ref) {
96
+ return /* @__PURE__ */ jsx(
97
+ Button$1,
98
+ {
99
+ ref,
100
+ "data-emphasis": emphasis,
101
+ "data-color": palette,
102
+ "data-icon-only": isIconOnly(children) ? "" : void 0,
103
+ ...props,
104
+ className: (state) => cnState("Button", className, state),
105
+ children
106
+ }
107
+ );
108
+ });
109
+ Button.displayName = "Button";
110
+ var Trigger = buttonPart(
111
+ Select$1.Trigger,
112
+ "SelectTrigger",
113
+ { optIn: true, otherClass: "SelectTrigger" }
114
+ );
115
+ var Value = styledPart(
116
+ Select$1.Value,
117
+ "SelectValue",
118
+ "SelectValue"
119
+ );
120
+ var Icon = styledPart(
121
+ Select$1.Icon,
122
+ "SelectIcon",
123
+ "SelectIcon"
124
+ );
125
+ var Backdrop = styledPart(
126
+ Select$1.Backdrop,
127
+ "SelectBackdrop",
128
+ "SelectBackdrop"
129
+ );
130
+ var Positioner = styledPart(
131
+ Select$1.Positioner,
132
+ "SelectPositioner",
133
+ "SelectPositioner"
134
+ );
135
+ var Popup = styledPart(
136
+ Select$1.Popup,
137
+ "SelectPopup",
138
+ "SelectPopup"
139
+ );
140
+ var List = styledPart(
141
+ Select$1.List,
142
+ "SelectList",
143
+ "SelectList"
144
+ );
145
+ var Item = styledPart(
146
+ Select$1.Item,
147
+ "SelectItem",
148
+ "SelectItem"
149
+ );
150
+ var ItemIndicator = styledPart(
151
+ Select$1.ItemIndicator,
152
+ "SelectItemIndicator",
153
+ "SelectItemIndicator"
154
+ );
155
+ var ItemText = styledPart(
156
+ Select$1.ItemText,
157
+ "SelectItemText",
158
+ "SelectItemText"
159
+ );
160
+ var Arrow = styledPart(
161
+ Select$1.Arrow,
162
+ "SelectArrow",
163
+ "SelectArrow"
164
+ );
165
+ var ScrollDownArrow = styledPart(
166
+ Select$1.ScrollDownArrow,
167
+ "SelectScrollDownArrow",
168
+ "SelectScrollArrow"
169
+ );
170
+ var ScrollUpArrow = styledPart(
171
+ Select$1.ScrollUpArrow,
172
+ "SelectScrollUpArrow",
173
+ "SelectScrollArrow"
174
+ );
175
+ var Group = styledPart(
176
+ Select$1.Group,
177
+ "SelectGroup",
178
+ "SelectGroup"
179
+ );
180
+ var GroupLabel = styledPart(
181
+ Select$1.GroupLabel,
182
+ "SelectGroupLabel",
183
+ "SelectGroupLabel"
184
+ );
185
+ var Separator = styledPart(
186
+ Select$1.Separator,
187
+ "SelectSeparator",
188
+ "SelectSeparator"
189
+ );
190
+ var Select = {
191
+ Root: Select$1.Root,
192
+ Label: Select$1.Label,
193
+ Trigger,
194
+ Value,
195
+ Icon,
196
+ Portal: Select$1.Portal,
197
+ Backdrop,
198
+ Positioner,
199
+ Popup,
200
+ List,
201
+ Item,
202
+ ItemIndicator,
203
+ ItemText,
204
+ Arrow,
205
+ ScrollDownArrow,
206
+ ScrollUpArrow,
207
+ Group,
208
+ GroupLabel,
209
+ Separator
210
+ };
211
+ function Root({
212
+ className,
213
+ style,
214
+ ...props
215
+ }) {
216
+ return /* @__PURE__ */ jsx("div", { className: cn("ComboboxRoot", className), style, children: /* @__PURE__ */ jsx(Combobox$1.Root, { ...props }) });
217
+ }
218
+ var Trigger2 = React4.forwardRef(
219
+ function ComboboxTrigger({ className, ...props }, ref) {
220
+ return /* @__PURE__ */ jsx(
221
+ Combobox$1.Trigger,
222
+ {
223
+ ref,
224
+ ...props,
225
+ className: (state) => {
226
+ const extra = typeof className === "function" ? className(state) : className;
227
+ const selectTrigger = extra?.split(/\s+/).includes("ComboboxSelectTrigger");
228
+ return cn(selectTrigger ? void 0 : "ComboboxTrigger", extra);
229
+ }
230
+ }
231
+ );
232
+ }
233
+ );
234
+ var Label = styledPart(
235
+ Combobox$1.Label,
236
+ "ComboboxLabel",
237
+ "ComboboxLabel"
238
+ );
239
+ var Input = styledPart(
240
+ Combobox$1.Input,
241
+ "ComboboxInput",
242
+ "ComboboxInput"
243
+ );
244
+ var Clear = styledPart(
245
+ Combobox$1.Clear,
246
+ "ComboboxClear",
247
+ "ComboboxClear"
248
+ );
249
+ var Icon2 = styledPart(
250
+ Combobox$1.Icon,
251
+ "ComboboxIcon",
252
+ "ComboboxIcon"
253
+ );
254
+ var Chips = styledPart(
255
+ Combobox$1.Chips,
256
+ "ComboboxChips",
257
+ "ComboboxChips"
258
+ );
259
+ var Chip = styledPart(
260
+ Combobox$1.Chip,
261
+ "ComboboxChip",
262
+ "ComboboxChip"
263
+ );
264
+ var ChipRemove = styledPart(
265
+ Combobox$1.ChipRemove,
266
+ "ComboboxChipRemove",
267
+ "ComboboxChipRemove"
268
+ );
269
+ var Positioner2 = styledPart(
270
+ Combobox$1.Positioner,
271
+ "ComboboxPositioner",
272
+ "ComboboxPositioner"
273
+ );
274
+ var Popup2 = styledPart(
275
+ Combobox$1.Popup,
276
+ "ComboboxPopup",
277
+ "ComboboxPopup"
278
+ );
279
+ var List2 = styledPart(
280
+ Combobox$1.List,
281
+ "ComboboxList",
282
+ "ComboboxList"
283
+ );
284
+ var Item2 = styledPart(
285
+ Combobox$1.Item,
286
+ "ComboboxItem",
287
+ "ComboboxItem"
288
+ );
289
+ var ItemIndicator2 = styledPart(
290
+ Combobox$1.ItemIndicator,
291
+ "ComboboxItemIndicator",
292
+ "ComboboxItemIndicator"
293
+ );
294
+ var GroupLabel2 = styledPart(
295
+ Combobox$1.GroupLabel,
296
+ "ComboboxGroupLabel",
297
+ "ComboboxGroupLabel"
298
+ );
299
+ var Separator2 = styledPart(
300
+ Combobox$1.Separator,
301
+ "ComboboxSeparator",
302
+ "ComboboxSeparator"
303
+ );
304
+ var Empty = styledPart(
305
+ Combobox$1.Empty,
306
+ "ComboboxEmpty",
307
+ "ComboboxEmpty"
308
+ );
309
+ var Status = styledPart(
310
+ Combobox$1.Status,
311
+ "ComboboxStatus",
312
+ "ComboboxStatus"
313
+ );
314
+ var Combobox = {
315
+ Root,
316
+ Label,
317
+ Value: Combobox$1.Value,
318
+ Input,
319
+ InputGroup: Combobox$1.InputGroup,
320
+ Trigger: Trigger2,
321
+ List: List2,
322
+ Status,
323
+ Portal: Combobox$1.Portal,
324
+ Backdrop: Combobox$1.Backdrop,
325
+ Positioner: Positioner2,
326
+ Popup: Popup2,
327
+ Arrow: Combobox$1.Arrow,
328
+ Icon: Icon2,
329
+ Group: Combobox$1.Group,
330
+ GroupLabel: GroupLabel2,
331
+ Item: Item2,
332
+ ItemIndicator: ItemIndicator2,
333
+ Chips,
334
+ Chip,
335
+ ChipRemove,
336
+ Row: Combobox$1.Row,
337
+ Collection: Combobox$1.Collection,
338
+ Empty,
339
+ Clear,
340
+ Separator: Separator2,
341
+ useFilter: Combobox$1.useFilter,
342
+ useFilteredItems: Combobox$1.useFilteredItems,
343
+ createItems: Combobox$1.createItems
344
+ };
345
+ var ICONS = {
346
+ start: "inbox",
347
+ "no-results": "search_off",
348
+ error: "error",
349
+ done: "check_circle",
350
+ "no-access": "lock",
351
+ // A pointer, not an empty inbox: the pane is waiting for a choice in the list beside it.
352
+ unselected: "left_click"
353
+ };
354
+ var MEDIA_STATUS = {
355
+ error: "error",
356
+ done: "success"
357
+ };
358
+ function announcedRole(kind, announce) {
359
+ if (announce === false) return void 0;
360
+ if (kind === "error") return announce ? "alert" : void 0;
361
+ if (announce || kind === "no-results" || kind === "done") return "status";
362
+ return void 0;
363
+ }
364
+ function titleTag(size, headingLevel) {
365
+ if (headingLevel) return `h${headingLevel}`;
366
+ if (size === "compact") return "p";
367
+ return "h2";
368
+ }
369
+ function textOf(node) {
370
+ if (typeof node === "string" || typeof node === "number") return String(node);
371
+ return null;
372
+ }
373
+ var EmptyStateContext = React4.createContext(null);
374
+ var EmptyStateRoot = React4.forwardRef(function EmptyStateRoot2({ className, kind = "start", size = "standard", announce, children, ...props }, ref) {
375
+ const role = announcedRole(kind, announce);
376
+ const [copy, setCopy] = React4.useState({ title: null, description: null });
377
+ const [live, setLive] = React4.useState("");
378
+ const openedAsDone = React4.useRef(kind === "done");
379
+ const report = React4.useCallback((part, value) => {
380
+ setCopy((current) => current[part] === value ? current : { ...current, [part]: value });
381
+ }, []);
382
+ const message = [copy.title, copy.description].filter(Boolean).join(" ");
383
+ React4.useEffect(() => {
384
+ if (kind !== "done") openedAsDone.current = false;
385
+ if (!role || kind === "done" && openedAsDone.current) return;
386
+ const frame = requestAnimationFrame(() => setLive(message));
387
+ return () => cancelAnimationFrame(frame);
388
+ }, [kind, message, role]);
389
+ const context = React4.useMemo(() => ({ kind, size, report }), [kind, report, size]);
390
+ return /* @__PURE__ */ jsx(EmptyStateContext.Provider, { value: context, children: /* @__PURE__ */ jsxs("div", { ref, "data-kind": kind, "data-size": size, className: cn("EmptyState", className), ...props, children: [
391
+ role ? /* @__PURE__ */ jsx("span", { className: "visually-hidden", role, children: live }) : null,
392
+ children
393
+ ] }) });
394
+ });
395
+ var EmptyStateMedia = React4.forwardRef(function EmptyStateMedia2({ className, kind, custom, ...props }, ref) {
396
+ const state = React4.useContext(EmptyStateContext);
397
+ const tone = kind ?? state?.kind;
398
+ return /* @__PURE__ */ jsx(
399
+ "div",
400
+ {
401
+ ref,
402
+ "data-status": tone ? MEDIA_STATUS[tone] : void 0,
403
+ "data-custom": custom ? "" : void 0,
404
+ className: cn("EmptyStateMedia", className),
405
+ ...props
406
+ }
407
+ );
408
+ });
409
+ var EmptyStateTitle = React4.forwardRef(function EmptyStateTitle2({ className, size, headingLevel, children, ...props }, ref) {
410
+ const state = React4.useContext(EmptyStateContext);
411
+ const Tag = titleTag(size ?? state?.size ?? "standard", headingLevel);
412
+ const text = textOf(children);
413
+ React4.useLayoutEffect(() => {
414
+ state?.report("title", text);
415
+ return () => state?.report("title", null);
416
+ }, [state, text]);
417
+ return /* @__PURE__ */ jsx(Tag, { ref, className: cn("EmptyStateTitle", className), ...props, children });
418
+ });
419
+ var EmptyStateDescription = React4.forwardRef(
420
+ function EmptyStateDescription2({ className, children, ...props }, ref) {
421
+ const state = React4.useContext(EmptyStateContext);
422
+ const text = textOf(children);
423
+ React4.useLayoutEffect(() => {
424
+ state?.report("description", text);
425
+ return () => state?.report("description", null);
426
+ }, [state, text]);
427
+ return /* @__PURE__ */ jsx("p", { ref, className: cn("EmptyStateDescription", className), ...props, children });
428
+ }
429
+ );
430
+ var EmptyStateActions = React4.forwardRef(function EmptyStateActions2({ className, ...props }, ref) {
431
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("EmptyStateActions", className), ...props });
432
+ });
433
+ function Glyph({ name }) {
434
+ return /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined", "aria-hidden": "true", children: name });
435
+ }
436
+ var EmptyState = Object.assign(
437
+ React4.forwardRef(function EmptyState2({
438
+ className,
439
+ kind = "start",
440
+ size = "standard",
441
+ icon,
442
+ media,
443
+ title,
444
+ description,
445
+ actions,
446
+ headingLevel,
447
+ announce,
448
+ children,
449
+ ...props
450
+ }, ref) {
451
+ const showMedia = media !== void 0 || icon !== null;
452
+ return /* @__PURE__ */ jsxs(EmptyStateRoot, { ref, kind, size, announce, className, ...props, children: [
453
+ showMedia ? /* @__PURE__ */ jsx(EmptyStateMedia, { custom: media !== void 0, children: media !== void 0 ? media : typeof icon === "string" || icon === void 0 ? /* @__PURE__ */ jsx(Glyph, { name: typeof icon === "string" ? icon : ICONS[kind] }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: icon }) }) : null,
454
+ /* @__PURE__ */ jsxs("div", { className: "EmptyStateText", children: [
455
+ /* @__PURE__ */ jsx(EmptyStateTitle, { headingLevel, children: title }),
456
+ description ? /* @__PURE__ */ jsx(EmptyStateDescription, { children: description }) : null
457
+ ] }),
458
+ actions ? /* @__PURE__ */ jsx(EmptyStateActions, { children: actions }) : null,
459
+ children
460
+ ] });
461
+ }),
462
+ {
463
+ Root: EmptyStateRoot,
464
+ Media: EmptyStateMedia,
465
+ Title: EmptyStateTitle,
466
+ Description: EmptyStateDescription,
467
+ Actions: EmptyStateActions
468
+ }
469
+ );
470
+
471
+ // src/custom/collection/collection-utils.ts
472
+ var collators = /* @__PURE__ */ new Map();
473
+ function collatorFor(locale) {
474
+ let collator = collators.get(locale);
475
+ if (!collator) {
476
+ collator = new Intl.Collator(locale, { numeric: true, sensitivity: "base" });
477
+ collators.set(locale, collator);
478
+ }
479
+ return collator;
480
+ }
481
+ function normalizeSearch(value) {
482
+ return value.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase();
483
+ }
484
+ function isEmptyValue(value) {
485
+ return value == null || value === "";
486
+ }
487
+ function fractionDigitsOf(currency) {
488
+ try {
489
+ return new Intl.NumberFormat("en", { style: "currency", currency }).resolvedOptions().maximumFractionDigits ?? 2;
490
+ } catch {
491
+ return 2;
492
+ }
493
+ }
494
+ function toMinor(value, digits) {
495
+ if (isEmptyValue(value)) return null;
496
+ const scale = 10n ** BigInt(digits);
497
+ const text = typeof value === "number" ? numberToDecimal(value) : String(value);
498
+ if (text == null) return null;
499
+ const match = text.trim().replace(/,/g, "").replace(/^\((.*)\)$/, "-$1").match(/^([+-])?(\d+)(?:\.(\d+))?$/);
500
+ if (!match) return null;
501
+ const sign = match[1] === "-" ? -1n : 1n;
502
+ const whole = BigInt(match[2] || "0");
503
+ const fracRaw = match[3] ?? "";
504
+ const frac = BigInt(fracRaw.padEnd(digits, "0").slice(0, digits) || "0");
505
+ let minor = whole * scale + frac;
506
+ const roundDigit = fracRaw.charAt(digits);
507
+ if (roundDigit && roundDigit >= "5") minor += 1n;
508
+ return minor * sign;
509
+ }
510
+ function numberToDecimal(value) {
511
+ if (!Number.isFinite(value)) return null;
512
+ const text = Object.is(value, -0) ? "-0" : String(value);
513
+ if (!/[eE]/.test(text)) return text;
514
+ return value.toLocaleString("en", { useGrouping: false, maximumFractionDigits: 20 });
515
+ }
516
+ function minorToDecimal(minor, digits) {
517
+ const sign = minor < 0n ? "-" : "";
518
+ const abs = minor < 0n ? -minor : minor;
519
+ const scale = 10n ** BigInt(digits);
520
+ const whole = abs / scale;
521
+ if (!digits) return `${sign}${whole}`;
522
+ const frac = (abs % scale).toString().padStart(digits, "0");
523
+ return `${sign}${whole}.${frac}`;
524
+ }
525
+ function compareDecimal(a, b) {
526
+ const places = Math.max(decimalPlaces(a), decimalPlaces(b));
527
+ const left = toMinor(a, places);
528
+ const right = toMinor(b, places);
529
+ if (left == null || right == null) return 0;
530
+ if (left < right) return -1;
531
+ if (left > right) return 1;
532
+ return 0;
533
+ }
534
+ function decimalPlaces(value) {
535
+ const text = (typeof value === "number" ? numberToDecimal(value) : String(value)) ?? "";
536
+ const plain = text.replace(/,/g, "");
537
+ const dot = plain.indexOf(".");
538
+ return dot === -1 ? 0 : plain.length - dot - 1;
539
+ }
540
+ var DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
541
+ function calendarDate(value) {
542
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
543
+ if (typeof value === "string") {
544
+ const match = DATE_ONLY.exec(value);
545
+ if (match) return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
546
+ }
547
+ if (typeof value === "string" || typeof value === "number") {
548
+ const date = new Date(value);
549
+ return Number.isNaN(date.getTime()) ? null : date;
550
+ }
551
+ return null;
552
+ }
553
+ function sortRows(items, kind, desc, locale) {
554
+ const collator = collatorFor(locale);
555
+ const sorted = [...items].sort((a, b) => {
556
+ const aEmpty = isEmptyValue(a.value);
557
+ const bEmpty = isEmptyValue(b.value);
558
+ if (aEmpty || bEmpty) {
559
+ if (aEmpty && bEmpty) return a.index - b.index;
560
+ return aEmpty ? 1 : -1;
561
+ }
562
+ const compared = comparePresent(a.value, b.value, kind, collator);
563
+ if (compared === 0) return a.index - b.index;
564
+ return desc ? -compared : compared;
565
+ });
566
+ return sorted.map((item) => item.row);
567
+ }
568
+ function comparePresent(a, b, kind, collator) {
569
+ if (kind === "number" || kind === "money" || kind === "percent") {
570
+ return compareDecimal(a, b);
571
+ }
572
+ if (kind === "date") {
573
+ const at = dateStamp(a);
574
+ const bt = dateStamp(b);
575
+ if (at == null || bt == null) return 0;
576
+ return at < bt ? -1 : at > bt ? 1 : 0;
577
+ }
578
+ if (kind === "boolean") return Number(Boolean(a)) - Number(Boolean(b));
579
+ return collator.compare(String(a), String(b));
580
+ }
581
+ function dateStamp(value) {
582
+ return calendarDate(value)?.getTime() ?? null;
583
+ }
584
+ function formatMoney(value, options) {
585
+ const digits = options.fractionDigits ?? fractionDigitsOf(options.currency);
586
+ const minor = toMinor(value, digits);
587
+ if (minor == null) return "";
588
+ return new Intl.NumberFormat(options.locale, {
589
+ style: "currency",
590
+ currency: options.currency,
591
+ minimumFractionDigits: digits,
592
+ maximumFractionDigits: digits,
593
+ currencySign: options.negative === "parens" ? "accounting" : "standard"
594
+ }).format(minorToDecimal(minor, digits));
595
+ }
596
+ function formatNumber(value, locale, fractionDigits) {
597
+ if (isEmptyValue(value)) return "";
598
+ const numeric = typeof value === "number" ? value : Number(String(value).replace(/,/g, ""));
599
+ if (!Number.isFinite(numeric)) return String(value);
600
+ return new Intl.NumberFormat(locale, {
601
+ minimumFractionDigits: fractionDigits,
602
+ maximumFractionDigits: fractionDigits ?? 20
603
+ }).format(numeric);
604
+ }
605
+ function formatPercent(value, locale) {
606
+ if (isEmptyValue(value)) return "";
607
+ const numeric = typeof value === "number" ? value : Number(value);
608
+ if (!Number.isFinite(numeric)) return String(value);
609
+ return new Intl.NumberFormat(locale, { style: "percent", maximumFractionDigits: 2 }).format(numeric);
610
+ }
611
+ function formatDate(value, locale, dateFormat) {
612
+ const date = calendarDate(value);
613
+ if (!date) return "";
614
+ return new Intl.DateTimeFormat(locale, dateFormat ?? { dateStyle: "medium" }).format(date);
615
+ }
616
+ function isoDate(value) {
617
+ if (typeof value === "string" && DATE_ONLY.test(value)) return value;
618
+ const date = value instanceof Date ? value : calendarDate(value);
619
+ if (!date) return "";
620
+ const month = String(date.getMonth() + 1).padStart(2, "0");
621
+ const day = String(date.getDate()).padStart(2, "0");
622
+ return `${date.getFullYear()}-${month}-${day}`;
623
+ }
624
+ function moneySearchForms(value, currency, locale, fractionDigits) {
625
+ const digits = fractionDigits ?? fractionDigitsOf(currency);
626
+ const minor = toMinor(value, digits);
627
+ if (minor == null) return [];
628
+ const plain = minorToDecimal(minor, digits);
629
+ const trimmed = plain.replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
630
+ const formatted = formatMoney(plain, { locale, currency, fractionDigits: digits });
631
+ const grouped = new Intl.NumberFormat(locale, {
632
+ style: "currency",
633
+ currency,
634
+ minimumFractionDigits: digits,
635
+ maximumFractionDigits: digits
636
+ }).formatToParts(plain).filter((part) => part.type === "integer" || part.type === "group" || part.type === "decimal" || part.type === "fraction" || part.type === "minusSign").map((part) => part.value).join("");
637
+ return [plain, trimmed, grouped, formatted];
638
+ }
639
+ function searchHaystack(parts) {
640
+ return parts.filter((part) => part != null && part !== "").join(" ");
641
+ }
642
+ function searchMatches(query, haystack) {
643
+ const normalized = normalizeSearch(query).trim();
644
+ if (!normalized) return true;
645
+ const words = normalized.split(/\s+/);
646
+ const text = normalizeSearch(haystack).replace(/,/g, "");
647
+ return words.every((word) => text.includes(word.replace(/,/g, "")));
648
+ }
649
+ function sumMoney(values, fractionDigits) {
650
+ const currencies = new Set(values.map((value) => value.currency).filter(Boolean));
651
+ if (currencies.size > 1) return { currency: null, minor: null, mixed: true };
652
+ const currency = [...currencies][0] ?? null;
653
+ if (!currency) return { currency: null, minor: 0n, mixed: false };
654
+ const digits = fractionDigits ?? fractionDigitsOf(currency);
655
+ let total = 0n;
656
+ for (const value of values) {
657
+ const minor = toMinor(value.amount, digits);
658
+ if (minor != null) total += minor;
659
+ }
660
+ return { currency, minor: total, mixed: false };
661
+ }
662
+ function balanceOf(amounts, control, currency) {
663
+ const digits = fractionDigitsOf(currency);
664
+ const allocated = amounts.reduce((sum, amount) => sum + (toMinor(amount, digits) ?? 0n), 0n);
665
+ const target = toMinor(control, digits) ?? 0n;
666
+ const delta = target - allocated;
667
+ const tone = delta === 0n ? "balanced" : delta > 0n ? "under" : "over";
668
+ return { tone, allocated, control: target, delta, digits };
669
+ }
670
+ function pageBounds(pageIndex, pageSize, total) {
671
+ const size = pageSize > 0 ? pageSize : total || 1;
672
+ const pageCount = total === 0 ? 1 : Math.ceil(total / size);
673
+ const safe = Math.min(Math.max(0, pageIndex), pageCount - 1);
674
+ const start = total === 0 ? 0 : safe * size;
675
+ const end = Math.min(total, start + size);
676
+ return { pageIndex: safe, pageCount, start, end };
677
+ }
678
+ function pageFlat(entries, pageIndex, pageSize) {
679
+ const leaves = entries.filter((entry) => entry.kind === "leaf");
680
+ const bounds = pageBounds(pageIndex, pageSize, leaves.length);
681
+ const pageLeaves = new Set(leaves.slice(bounds.start, bounds.end));
682
+ const out = [];
683
+ let currentGroup = null;
684
+ let leavesBeforeGroupOnPage = 0;
685
+ let emittedGroup = false;
686
+ let groupHadLeaves = false;
687
+ const closeGroup = () => {
688
+ if (currentGroup && !emittedGroup && !groupHadLeaves) out.push(currentGroup);
689
+ };
690
+ for (const entry of entries) {
691
+ if (entry.kind === "group") {
692
+ closeGroup();
693
+ currentGroup = entry;
694
+ emittedGroup = false;
695
+ groupHadLeaves = false;
696
+ leavesBeforeGroupOnPage = 0;
697
+ continue;
698
+ }
699
+ groupHadLeaves = true;
700
+ if (!pageLeaves.has(entry)) {
701
+ if (!emittedGroup) leavesBeforeGroupOnPage += 1;
702
+ continue;
703
+ }
704
+ if (currentGroup && !emittedGroup) {
705
+ out.push({ ...currentGroup, continued: leavesBeforeGroupOnPage > 0 });
706
+ emittedGroup = true;
707
+ }
708
+ out.push(entry);
709
+ }
710
+ closeGroup();
711
+ return { entries: out, leafCount: leaves.length, bounds };
712
+ }
713
+ function treeVisibleIds(rows, getId, getChildren, matches) {
714
+ const visible = /* @__PURE__ */ new Set();
715
+ const walk = (row, ancestors) => {
716
+ const id = getId(row);
717
+ let childHit = false;
718
+ for (const child of getChildren(row) ?? []) {
719
+ if (walk(child, [...ancestors, id])) childHit = true;
720
+ }
721
+ if (matches(row) || childHit) {
722
+ visible.add(id);
723
+ for (const ancestor of ancestors) visible.add(ancestor);
724
+ return true;
725
+ }
726
+ return false;
727
+ };
728
+ for (const row of rows) walk(row, []);
729
+ return visible;
730
+ }
731
+ function countFacets(rows, valueOf) {
732
+ const counts = /* @__PURE__ */ new Map();
733
+ for (const row of rows) {
734
+ const key = isEmptyValue(valueOf(row)) ? "" : String(valueOf(row));
735
+ counts.set(key, (counts.get(key) ?? 0) + 1);
736
+ }
737
+ return counts;
738
+ }
739
+ function selectableIds(ids, rows, getRowId, canSelect, getSubRows) {
740
+ const known = /* @__PURE__ */ new Map();
741
+ const walk = (list) => {
742
+ for (const row of list) {
743
+ known.set(getRowId(row), row);
744
+ const children = getSubRows?.(row);
745
+ if (children) walk(children);
746
+ }
747
+ };
748
+ walk(rows);
749
+ return ids.filter((id) => {
750
+ const row = known.get(id);
751
+ return row != null && (canSelect?.(row) ?? true);
752
+ });
753
+ }
754
+ function hiddenSelectedCount(selectedIds, filteredIds) {
755
+ let hidden = 0;
756
+ for (const id of selectedIds) if (!filteredIds.has(id)) hidden += 1;
757
+ return hidden;
758
+ }
759
+ function sameSort(a, b) {
760
+ if (a == null || b == null) return a == null && b == null;
761
+ return a.id === b.id && a.desc === b.desc;
762
+ }
763
+ function nextSort(current, columnId, initial) {
764
+ const onColumn = current?.id === columnId;
765
+ let next;
766
+ if (!onColumn) next = { id: columnId, desc: false };
767
+ else if (!current?.desc) next = { id: columnId, desc: true };
768
+ else next = initial;
769
+ if (sameSort(next, current)) return { id: columnId, desc: false };
770
+ return next;
771
+ }
772
+ function useUnderWidth(token) {
773
+ const ref = React4.useRef(null);
774
+ const [under, setUnder] = React4.useState(false);
775
+ React4.useEffect(() => {
776
+ const node = ref.current;
777
+ if (!node) return;
778
+ const probe = document.createElement("div");
779
+ probe.style.width = `var(${token})`;
780
+ probe.style.position = "absolute";
781
+ probe.style.visibility = "hidden";
782
+ probe.style.pointerEvents = "none";
783
+ document.body.appendChild(probe);
784
+ const watch = () => {
785
+ if (probe.offsetWidth <= 0) return;
786
+ setUnder(node.clientWidth <= probe.offsetWidth);
787
+ };
788
+ const observer = new ResizeObserver(watch);
789
+ observer.observe(node);
790
+ observer.observe(probe);
791
+ watch();
792
+ return () => {
793
+ observer.disconnect();
794
+ probe.remove();
795
+ };
796
+ }, [token]);
797
+ return { ref, under };
798
+ }
799
+
800
+ export { Button, Combobox, EmptyState, Select, balanceOf, buttonPart, cn, cnState, collatorFor, compareDecimal, comparePresent, countFacets, formatDate, formatMoney, formatNumber, formatPercent, fractionDigitsOf, hiddenSelectedCount, isEmptyValue, isoDate, minorToDecimal, moneySearchForms, nextSort, pageBounds, pageFlat, searchHaystack, searchMatches, selectableIds, sortRows, styledPart, styledPartUnless, sumMoney, toMinor, treeVisibleIds, useUnderWidth };
801
+ //# sourceMappingURL=chunk-M7KJASGK.js.map
802
+ //# sourceMappingURL=chunk-M7KJASGK.js.map