@eightshift/ui-components 6.1.0 → 6.2.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 (82) hide show
  1. package/dist/{Button-BTCA69Lt.js → Button-CFnNdpNZ.js} +3 -3
  2. package/dist/{Dialog-BbNWvB5_.js → Dialog-DDfABlp4.js} +38 -29
  3. package/dist/{FocusScope-BxT4xfe9.js → FocusScope-BJhC1-1e.js} +1 -1
  4. package/dist/{Input-Wrnm2nxy.js → Input-B4X6-x6r.js} +4 -4
  5. package/dist/{List-CWheI3JH.js → List-CQFXnN4w.js} +1 -1
  6. package/dist/{ListBox-yHUyUAAH.js → ListBox-ByPsaVVK.js} +15 -13
  7. package/dist/{OverlayArrow-NzRV9wsn.js → OverlayArrow-Dy0qw7WL.js} +1 -1
  8. package/dist/{PortalProvider-CHPnqDSH.js → PortalProvider-BQ1X8vGX.js} +1 -1
  9. package/dist/{RadioGroup-BFDueqHz.js → RadioGroup-CjCAbUr4.js} +8 -8
  10. package/dist/{SearchField-CmRhtrQf.js → SearchField-BME59dt-.js} +5 -5
  11. package/dist/{SelectionManager-VgpR-1Ri.js → SelectionManager-iru59gc4.js} +36 -35
  12. package/dist/{SharedElementTransition-B_vnQ1uR.js → SharedElementTransition-CtoWSaF0.js} +1 -1
  13. package/dist/{Slider-Bl5G0ZHE.js → Slider-BIbaMdUE.js} +6 -6
  14. package/dist/{VisuallyHidden-DXVaR_RC.js → VisuallyHidden-CqnizvzQ.js} +1 -1
  15. package/dist/{animation-B2sADg3I.js → animation-Dfl8uEb3.js} +1 -1
  16. package/dist/assets/style-admin.css +9 -0
  17. package/dist/assets/style-editor.css +9 -0
  18. package/dist/assets/style.css +9 -0
  19. package/dist/{color-swatch-DtaLObbd.js → color-swatch-bUFkK7ox.js} +2 -2
  20. package/dist/components/button/button.js +3 -3
  21. package/dist/components/checkbox/checkbox.js +7 -7
  22. package/dist/components/color-pickers/color-picker.js +1 -1
  23. package/dist/components/color-pickers/color-swatch.js +1 -1
  24. package/dist/components/color-pickers/gradient-editor.js +2 -2
  25. package/dist/components/color-pickers/solid-color-picker.js +11 -11
  26. package/dist/components/draggable/draggable-handle.js +1 -1
  27. package/dist/components/draggable/draggable.js +841 -633
  28. package/dist/components/draggable-list/draggable-list-item.js +1 -1
  29. package/dist/components/draggable-list/draggable-list.js +1 -1
  30. package/dist/components/expandable/expandable.js +6 -6
  31. package/dist/components/index.js +1 -1
  32. package/dist/components/input-field/input-field.js +3 -3
  33. package/dist/components/link-input/link-input.js +13 -13
  34. package/dist/components/matrix-align/matrix-align.js +1 -1
  35. package/dist/components/menu/menu.js +1 -1
  36. package/dist/components/modal/modal.js +6 -6
  37. package/dist/components/number-picker/number-picker.js +4 -4
  38. package/dist/components/placeholders/file-picker-shell.js +1 -1
  39. package/dist/components/popover/popover.js +1 -1
  40. package/dist/components/portal-provider/portal-provider.js +1 -1
  41. package/dist/components/radio/radio.js +1 -1
  42. package/dist/components/repeater/repeater.js +1 -1
  43. package/dist/components/rich-label/rich-label.js +6 -2
  44. package/dist/components/select/async-multi-select.js +126 -67
  45. package/dist/components/select/async-select.js +82 -42
  46. package/dist/components/select/multi-select.js +153 -113
  47. package/dist/components/select/shared.js +6 -5
  48. package/dist/components/select/single-select.js +154 -112
  49. package/dist/components/slider/column-config-slider.js +2 -2
  50. package/dist/components/slider/slider.js +2 -2
  51. package/dist/components/smart-image/smart-image-next.js +1 -1
  52. package/dist/components/smart-image/smart-image.js +2 -2
  53. package/dist/components/smart-image/worker-inline.js +1 -1
  54. package/dist/components/tabs/tabs.js +9 -9
  55. package/dist/components/toggle/switch.js +5 -5
  56. package/dist/components/toggle-button/toggle-button.js +4 -4
  57. package/dist/components/tooltip/tooltip.js +6 -6
  58. package/dist/{general-C8Q0dvEx.js → general-BfKmjm56.js} +3 -4
  59. package/dist/icons/jsx-svg.js +1 -1
  60. package/dist/{index-sSixe2j_.js → index-BL5gdWX4.js} +52 -52
  61. package/dist/index.js +1 -1
  62. package/dist/{proxy-CgLBbUpw.js → proxy-DFlYXk07.js} +130 -47
  63. package/dist/{react-jsx-parser.min-B_hvYYa1.js → react-jsx-parser.min-DAh4myol.js} +35 -35
  64. package/dist/{shared-DSTKnPjF.js → shared-HdRrpnhs.js} +48 -14
  65. package/dist/{textSelection-D_BSbtab.js → textSelection-CeoEP4rL.js} +1 -1
  66. package/dist/{useButton-DofKjCES.js → useButton-5YL_nmpZ.js} +2 -2
  67. package/dist/{useEvent-ADVZr4I3.js → useEvent-Zze2g7CX.js} +1 -1
  68. package/dist/{useFilter-Cqw0-KoB.js → useFilter-NhAlifsK.js} +1 -1
  69. package/dist/{useFocusRing-Ct2N5S1b.js → useFocusRing-rUOwLdTK.js} +1 -1
  70. package/dist/{useFormReset-KT27O1en.js → useFormReset-BxtOoO5Q.js} +1 -1
  71. package/dist/{useFormValidation-DwbcW-pN.js → useFormValidation-DTmPrTD8.js} +2 -2
  72. package/dist/{useHover-VPZwb-1l.js → useHover-CmyvqeWX.js} +4 -4
  73. package/dist/{useListState-jHobZH6F.js → useListState-HOvCQJFf.js} +1 -1
  74. package/dist/{useNumberField-CrLevIP3.js → useNumberField-CTkI-U9a.js} +7 -7
  75. package/dist/{usePress-BPCda-AF.js → usePress-CNefMs8d.js} +3 -3
  76. package/dist/{useSingleSelectListState-sLg_MnX8.js → useSingleSelectListState-BtrMHGeE.js} +2 -2
  77. package/dist/{useToggle-D0-c9HPm.js → useToggle-CFFOmZWi.js} +3 -3
  78. package/dist/{useToggleState-BhJn-Dz7.js → useToggleState-BWrKKisg.js} +1 -1
  79. package/dist/utilities/general.js +1 -1
  80. package/dist/utilities/index.js +1 -1
  81. package/dist/workers/image-analysis.worker.js +1 -1
  82. package/package.json +12 -12
@@ -2,20 +2,20 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { s as sprintf } from "../../sprintf-DmNrJSYG.js";
3
3
  import { _ as __, a as _n } from "../../default-i18n-CnQeC5Pl.js";
4
4
  import { BaseControl } from "../base-control/base-control.js";
5
- import { $ as $d2f53cda644affe3$export$2f2b9559550c7bbc, a as $440f4836bcb56932$export$b94867ecbd698f21 } from "../../SearchField-CmRhtrQf.js";
6
- import { $ as $d2b4bc8c273e7be6$export$353f5b6fc5456de1 } from "../../Button-BTCA69Lt.js";
7
- import { $ as $3985021b0ad6602f$export$f5b8910cec6cf069 } from "../../Input-Wrnm2nxy.js";
5
+ import { $ as $d2f53cda644affe3$export$2f2b9559550c7bbc, a as $440f4836bcb56932$export$b94867ecbd698f21 } from "../../SearchField-BME59dt-.js";
6
+ import { $ as $d2b4bc8c273e7be6$export$353f5b6fc5456de1 } from "../../Button-CFnNdpNZ.js";
7
+ import { f as $07b14b47974efb58$export$5b6b19405a83ff9d, i as $72a5793c14baf454$export$8b251419efc915eb } from "../../Dialog-DDfABlp4.js";
8
+ import { $ as $3985021b0ad6602f$export$f5b8910cec6cf069 } from "../../Input-B4X6-x6r.js";
8
9
  import { $ as $01b77f81d0f07f68$export$b04be29aa201d4f5 } from "../../Label-BDlf9vIY.js";
9
- import { $ as $eed445e0843c11d0$export$41f133550aa26f48 } from "../../ListBox-yHUyUAAH.js";
10
- import { f as $07b14b47974efb58$export$5b6b19405a83ff9d } from "../../Dialog-BbNWvB5_.js";
11
- import { $ as $82d7e5349645de74$export$ef9b1a59e592288f, a as $82d7e5349645de74$export$e288731fd71264f0, S as SelectClearButton, O as OptionItemBase } from "../../shared-DSTKnPjF.js";
12
- import { useRef, cloneElement } from "react";
10
+ import { $ as $eed445e0843c11d0$export$41f133550aa26f48, a as $eed445e0843c11d0$export$dca12b0bb56e4fc } from "../../ListBox-ByPsaVVK.js";
11
+ import { g as getGroupedOptions, $ as $82d7e5349645de74$export$ef9b1a59e592288f, a as $82d7e5349645de74$export$e288731fd71264f0, S as SelectClearButton, O as OptionItemBase } from "../../shared-HdRrpnhs.js";
12
+ import { $ as $e1995378a142960e$export$fb8073518f34e6ec } from "../../SelectionManager-iru59gc4.js";
13
+ import { useMemo, useRef, cloneElement } from "react";
13
14
  import { icons } from "../../icons/icons.js";
14
- import "../../react-jsx-parser.min-B_hvYYa1.js";
15
+ import "../../react-jsx-parser.min-DAh4myol.js";
15
16
  import { Spinner } from "../../icons/spinner.js";
16
17
  import { RichLabel } from "../rich-label/rich-label.js";
17
18
  import { unescapeHTML } from "../../utilities/text-helpers.js";
18
- import { randomId } from "../../utilities/hash.js";
19
19
  import { c as clsx } from "../../clsx-DgYk2OaC.js";
20
20
  import { c as cva } from "../../index-BHpUy2Ix.js";
21
21
  import { TriggeredPopover } from "../popover/popover.js";
@@ -43,6 +43,7 @@ import { $ as $f86e6c1ec7da6ebb$export$bc3384a35de93d66 } from "../../useAsyncLi
43
43
  * @param {Function} [props.getMeta] - Function to get the metadata for the item from the fetched data. `(item: Object<string, any>) => Object<string, any>` (optional)
44
44
  * @param {Function} [props.getIcon] - Function to get the icon for the item from the fetched data. `(item: Object<string, any>) => JSX.Element | string`
45
45
  * @param {Function} [props.getSubtitle] - Function to get the subtitle for the item from the fetched data. `(item: Object<string, any>) => string`
46
+ * @param {Function} [props.getGroup] - Function to get the group name for the item from the fetched data. `(item: Object<string, any>) => string`
46
47
  * @param {Function} [props.getData] - Function to pre-process the fetched data before it is used in the select. `(data: Object<string, any>[]) => Object<string, any>[]`
47
48
  * @param {Function} [props.fetchUrl] - Function to get the URL for fetching data. Provides typed search text if entered. `(searchText: string) => string`
48
49
  * @param {Object} [props.fetchConfig] - Configuration object for the fetch request, passed to the `fetch` function.
@@ -52,6 +53,8 @@ import { $ as $f86e6c1ec7da6ebb$export$bc3384a35de93d66 } from "../../useAsyncLi
52
53
  * @param {JSX.Element} [props.customValueDisplay] - If provided, replaces the default current value display of each selected item. `({ value: string, label: string, subtitle: string, metadata: any }) => JSX.Element`
53
54
  * @param {JSX.Element} [props.customDropdownArrow] - If provided, replaces the default dropdown arrow indicator.
54
55
  * @param {string} props.className - Classes to pass to the select menu.
56
+ * @param {string} [props.groupKey] - If provided, the options will be grouped by this key.
57
+ * @param {Object} [props.groupValueMapping] - If provided, the group headers will be mapped to these labels/icons.
55
58
  * @param {boolean} [props.noMinWidth=false] - If `true`, the select menu will not have a minimum width.
56
59
  * @param {boolean} [props.flat] - If `true`, component will look more flat. Useful for nested layer of controls.
57
60
  * @param {boolean} [props.noReorder] - If `true`, the option for reordering selected items is disabled.
@@ -98,11 +101,14 @@ const AsyncMultiSelect = (props) => {
98
101
  getMeta,
99
102
  getIcon,
100
103
  getSubtitle,
104
+ getGroup,
101
105
  getData = (data) => data,
102
106
  customMenuOption,
103
107
  customValueDisplay,
104
108
  customDropdownArrow,
105
109
  className,
110
+ groupKey,
111
+ groupValueMapping,
106
112
  flat,
107
113
  size = "default",
108
114
  noMinWidth = false,
@@ -121,7 +127,8 @@ const AsyncMultiSelect = (props) => {
121
127
  json = processLoadedOptions ? processLoadedOptions(getData(res)) : getData(res);
122
128
  } else {
123
129
  const res = await fetch(fetchUrl(filterText), { ...fetchConfig, signal });
124
- json = processLoadedOptions ? processLoadedOptions(getData(await res.json())) : getData(res);
130
+ const data = await res.json();
131
+ json = processLoadedOptions ? processLoadedOptions(getData(data)) : getData(data);
125
132
  }
126
133
  const output = json?.map((item, index) => {
127
134
  const id = getValue?.(item) ?? index;
@@ -132,6 +139,9 @@ const AsyncMultiSelect = (props) => {
132
139
  if (getSubtitle) {
133
140
  entry.subtitle = unescapeHTML(getSubtitle(item));
134
141
  }
142
+ if (getGroup) {
143
+ entry[groupKey ?? "_group"] = getGroup(item);
144
+ }
135
145
  return entry;
136
146
  });
137
147
  if (filterText.length > 0) {
@@ -150,9 +160,58 @@ const AsyncMultiSelect = (props) => {
150
160
  };
151
161
  }
152
162
  });
163
+ const groupedItems = useMemo(
164
+ () => getGroupedOptions(list?.items, groupKey ?? (getGroup ? "_group" : null), groupValueMapping),
165
+ [list?.items, groupKey, groupValueMapping, getGroup]
166
+ );
167
+ const renderItem = (item) => {
168
+ let icon2 = item?.icon ?? null;
169
+ if (typeof item?.icon === "string") {
170
+ icon2 = icons?.[item.icon] ?? null;
171
+ }
172
+ if (getIcon && !icon2) {
173
+ icon2 = getIcon(item);
174
+ }
175
+ return /* @__PURE__ */ jsxs(
176
+ OptionItemBase,
177
+ {
178
+ id: item.value,
179
+ textValue: item.label,
180
+ selectIndicator: true,
181
+ children: [
182
+ customMenuOption && customMenuOption(item),
183
+ !customMenuOption && /* @__PURE__ */ jsx(
184
+ RichLabel,
185
+ {
186
+ icon: icon2,
187
+ label: item.label,
188
+ subtitle: item.subtitle,
189
+ noColor: true
190
+ }
191
+ )
192
+ ]
193
+ },
194
+ item.value
195
+ );
196
+ };
153
197
  const handleSelectionChange = (rawSelected) => {
154
- const selected = list.filterText.length > 0 ? /* @__PURE__ */ new Set([...value?.map((item) => item?.value) ?? [], ...rawSelected]) : rawSelected;
155
- list.filterText = "";
198
+ let selected;
199
+ if (list.filterText.length > 0) {
200
+ const visibleItemKeys = new Set(list.items?.map((item) => item.value) ?? []);
201
+ selected = /* @__PURE__ */ new Set();
202
+ for (const item of value ?? []) {
203
+ const key = item?.value ?? item;
204
+ if (!visibleItemKeys.has(key)) {
205
+ selected.add(key);
206
+ }
207
+ }
208
+ for (const key of rawSelected) {
209
+ selected.add(key);
210
+ }
211
+ } else {
212
+ selected = rawSelected;
213
+ }
214
+ list.setSelectedKeys(selected);
156
215
  if (selected === null || selected === void 0) {
157
216
  onChange(null);
158
217
  return;
@@ -170,14 +229,7 @@ const AsyncMultiSelect = (props) => {
170
229
  ...option
171
230
  };
172
231
  }).filter(Boolean);
173
- onChange(
174
- selectedValues.map((item) => ({
175
- label: item?.label,
176
- value: item?.value,
177
- subtitle: item?.subtitle,
178
- meta: item?.meta
179
- }))
180
- );
232
+ onChange(selectedValues);
181
233
  };
182
234
  const ref = useRef();
183
235
  const currentValueKeys = value?.map((item) => item?.value ?? item);
@@ -260,6 +312,13 @@ const AsyncMultiSelect = (props) => {
260
312
  selectionMode: "multiple",
261
313
  isDisabled: disabled,
262
314
  value: currentValueKeys ?? [],
315
+ onOpenChange: (isOpen) => {
316
+ if (!isOpen) {
317
+ setTimeout(() => {
318
+ list.setFilterText("");
319
+ }, 100);
320
+ }
321
+ },
263
322
  onChange: (selected) => handleSelectionChange(selected),
264
323
  placeholder,
265
324
  ...rest,
@@ -282,35 +341,35 @@ const AsyncMultiSelect = (props) => {
282
341
  ref,
283
342
  children: [
284
343
  /* @__PURE__ */ jsxs($d2b4bc8c273e7be6$export$353f5b6fc5456de1, { className: buttonClass({ size }), children: [
285
- /* @__PURE__ */ jsx($82d7e5349645de74$export$e288731fd71264f0, { className: "es:select-none es:pointer-events-none", children: ({ isPlaceholder, selectedItems }) => {
286
- const [selectedItem] = selectedItems;
287
- if (!currentValueKeys?.length || isPlaceholder) {
344
+ /* @__PURE__ */ jsx($82d7e5349645de74$export$e288731fd71264f0, { className: "es:select-none es:pointer-events-none", children: () => {
345
+ if (!currentValueKeys?.length) {
288
346
  return /* @__PURE__ */ jsx("span", { className: "es:select-none es:pointer-events-none es:pr-6 es:text-sm es:text-surface-500", children: placeholder });
289
347
  }
290
- let icon2 = getIcon ? getIcon(selectedItem) : selectedItem?.icon ?? null;
291
- if (typeof selectedItem?.icon === "string") {
292
- icon2 = icons?.[selectedItem.icon] ?? null;
348
+ const currentItem = value?.[0];
349
+ let icon2 = getIcon ? getIcon(currentItem) : currentItem?.icon ?? null;
350
+ if (typeof currentItem?.icon === "string") {
351
+ icon2 = icons?.[currentItem.icon] ?? null;
293
352
  }
294
- if (selectedItems.length > 1) {
353
+ if (value?.length > 1) {
295
354
  return /* @__PURE__ */ jsx(
296
355
  RichLabel,
297
356
  {
298
357
  icon: icons.multiple,
299
- label: sprintf(_n("%s item", "%s items", selectedItems.length, "eightshift-ui-components"), selectedItems.length),
300
- subtitle: selectedItems.map((item) => item?.label ?? item).join(", "),
358
+ label: sprintf(_n("%s item", "%s items", value.length, "eightshift-ui-components"), value.length),
359
+ subtitle: value.map((item) => item?.label ?? item).join(", "),
301
360
  subtitleClassName: "es:line-clamp-1 es:max-w-56"
302
361
  }
303
362
  );
304
363
  }
305
- if (!isPlaceholder && value && customValueDisplay) {
306
- return customValueDisplay(selectedItem);
364
+ if (value && customValueDisplay) {
365
+ return customValueDisplay(currentItem);
307
366
  }
308
367
  return /* @__PURE__ */ jsx(
309
368
  RichLabel,
310
369
  {
311
370
  icon: icon2,
312
- label: selectedItem?.label,
313
- subtitle: selectedItem?.subtitle,
371
+ label: currentItem?.label,
372
+ subtitle: currentItem?.subtitle,
314
373
  className: clsx("es:pr-6 es:grow es:w-full", disabled && "es:grayscale es:pointer-events-none"),
315
374
  iconClassName: "es:pointer-events-none es:select-none",
316
375
  labelClassName: "es:line-clamp-1",
@@ -362,28 +421,34 @@ const AsyncMultiSelect = (props) => {
362
421
  DraggableList,
363
422
  {
364
423
  items: value ?? [],
365
- onChange: (value2) => {
366
- handleSelectionChange(new Set(value2?.map((item) => item?.value ?? item)));
424
+ onChange: (reordered) => {
425
+ onChange(
426
+ reordered.map((item) => ({
427
+ label: item?.label,
428
+ value: item?.value,
429
+ subtitle: item?.subtitle,
430
+ meta: item?.meta
431
+ }))
432
+ );
367
433
  },
368
434
  className: "es:contents",
369
435
  itemContainerClassName: "es:h-full es:max-h-60 es:overflow-y-auto es:pb-1.5 es:mt-0",
370
436
  itemClassName: "es:z-999999",
371
437
  children: (item) => {
372
- const realItem = list.getItem(item?.value);
373
- let icon2 = getIcon ? getIcon(realItem) : realItem?.icon ?? null;
374
- if (typeof realItem?.icon === "string") {
375
- icon2 = icons?.[realItem.icon] ?? null;
438
+ let icon2 = getIcon ? getIcon(item) : item?.icon ?? null;
439
+ if (typeof item?.icon === "string") {
440
+ icon2 = icons?.[item.icon] ?? null;
376
441
  }
377
442
  return /* @__PURE__ */ jsx(
378
443
  DraggableListItem,
379
444
  {
380
445
  icon: icon2,
381
- label: realItem?.label,
382
- subtitle: realItem?.subtitle,
446
+ label: item?.label,
447
+ subtitle: item?.subtitle,
383
448
  iconClassName: "es:pointer-events-none es:select-none",
384
449
  labelClassName: "es:line-clamp-1",
385
450
  subtitleClassName: "es:line-clamp-1",
386
- className: clsx("es:flex es:items-center es:justify-between", realItem?.icon ? "es:pl-1" : "es:pl-2")
451
+ className: clsx("es:flex es:items-center es:justify-between", item?.icon ? "es:pl-1" : "es:pl-2")
387
452
  }
388
453
  );
389
454
  }
@@ -441,7 +506,7 @@ const AsyncMultiSelect = (props) => {
441
506
  placeholder: __("Search...", "eightshift-ui-components"),
442
507
  className: clsx(
443
508
  "es:peer es:size-full es:h-9.5 es:outline-hidden! es:pl-3.5 es:pr-9 es:shadow-none! es:text-13! es:placeholder:text-surface-500 es:[&::-webkit-search-cancel-button]:hidden",
444
- "es:bg-accent-900/8 es:m-1.5 es:rounded-3xl es:border-none!",
509
+ "es:bg-accent-900/8 es:m-1.5 es:rounded-3xl! es:border-none!",
445
510
  "es:inset-ring! es:inset-ring-accent-950/7 es:focus:inset-ring-accent-950/20",
446
511
  "es:text-accent-950 es:placeholder:text-accent-700/50",
447
512
  "es:transition"
@@ -451,6 +516,7 @@ const AsyncMultiSelect = (props) => {
451
516
  /* @__PURE__ */ jsx(
452
517
  $d2b4bc8c273e7be6$export$353f5b6fc5456de1,
453
518
  {
519
+ slot: "clear",
454
520
  "aria-label": __("Clear", "eightshift-ui-components"),
455
521
  className: clsx(
456
522
  "es:absolute es:right-3 es:top-0 es:bottom-0 es:my-auto es:border-none es:bg-transparent",
@@ -464,16 +530,14 @@ const AsyncMultiSelect = (props) => {
464
530
  }
465
531
  ),
466
532
  list.isLoading && /* @__PURE__ */ jsx("div", { className: "es:p-3 es:min-h-16 es:flex es:items-center es:justify-center", children: /* @__PURE__ */ jsx(Spinner, {}) }),
467
- /* @__PURE__ */ jsx(
533
+ /* @__PURE__ */ jsxs(
468
534
  $eed445e0843c11d0$export$41f133550aa26f48,
469
535
  {
470
536
  className: clsx("es:space-y-0.75 es:p-1.5 es:pt-0 es:any-focus:outline-hidden es:h-full es:overflow-y-auto es:rounded-t-xl", list?.isLoading && "es:hidden"),
471
- items: list?.items ?? [],
472
537
  selectedKeys: list.selectedKeys,
473
538
  selectionMode: "multiple",
474
539
  selectionBehavior: "toggle",
475
540
  onSelectionChange: (selected) => {
476
- list.setSelectedKeys(selected);
477
541
  handleSelectionChange(selected);
478
542
  },
479
543
  renderEmptyState: () => /* @__PURE__ */ jsx(
@@ -487,34 +551,29 @@ const AsyncMultiSelect = (props) => {
487
551
  noColor: true
488
552
  }
489
553
  ),
490
- children: (item) => {
491
- let icon2 = getIcon ? getIcon(item) : item?.icon ?? null;
492
- if (typeof item?.icon === "string") {
493
- icon2 = icons?.[item.icon] ?? null;
494
- }
495
- return /* @__PURE__ */ jsxs(
496
- OptionItemBase,
554
+ children: [
555
+ groupedItems && /* @__PURE__ */ jsx($e1995378a142960e$export$fb8073518f34e6ec, { items: groupedItems, children: (section) => /* @__PURE__ */ jsxs(
556
+ $eed445e0843c11d0$export$dca12b0bb56e4fc,
497
557
  {
498
- id: item?.value ?? randomId(8),
499
- className: item?.className,
500
- selectIndicator: true,
558
+ id: section.key,
559
+ className: "es:flex es:flex-col es:gap-0.75",
501
560
  children: [
502
- customMenuOption && customMenuOption(item),
503
- !customMenuOption && /* @__PURE__ */ jsx(
561
+ /* @__PURE__ */ jsx($72a5793c14baf454$export$8b251419efc915eb, { className: "es:px-2.5 es:pb-1 es:pt-3 es:select-none", children: /* @__PURE__ */ jsx(
504
562
  RichLabel,
505
563
  {
506
- icon: icon2,
507
- label: item?.label,
508
- subtitle: item?.subtitle,
509
- labelClassName: "es:line-clamp-1",
510
- subtitleClassName: "es:line-clamp-1",
511
- noColor: true
564
+ icon: section?.icon,
565
+ label: section?.label,
566
+ subtitle: section?.subtitle,
567
+ endIcon: section?.endIcon,
568
+ fullWidth: true
512
569
  }
513
- )
570
+ ) }),
571
+ /* @__PURE__ */ jsx($e1995378a142960e$export$fb8073518f34e6ec, { items: section.options, children: (item) => renderItem(item) })
514
572
  ]
515
573
  }
516
- );
517
- }
574
+ ) }),
575
+ !groupedItems && /* @__PURE__ */ jsx($e1995378a142960e$export$fb8073518f34e6ec, { items: list.items ?? [], children: (item) => renderItem(item) })
576
+ ]
518
577
  }
519
578
  )
520
579
  ]
@@ -1,20 +1,20 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { _ as __ } from "../../default-i18n-CnQeC5Pl.js";
3
3
  import { BaseControl } from "../base-control/base-control.js";
4
- import { $ as $d2f53cda644affe3$export$2f2b9559550c7bbc, a as $440f4836bcb56932$export$b94867ecbd698f21 } from "../../SearchField-CmRhtrQf.js";
5
- import { $ as $d2b4bc8c273e7be6$export$353f5b6fc5456de1 } from "../../Button-BTCA69Lt.js";
6
- import { $ as $3985021b0ad6602f$export$f5b8910cec6cf069 } from "../../Input-Wrnm2nxy.js";
4
+ import { $ as $d2f53cda644affe3$export$2f2b9559550c7bbc, a as $440f4836bcb56932$export$b94867ecbd698f21 } from "../../SearchField-BME59dt-.js";
5
+ import { $ as $d2b4bc8c273e7be6$export$353f5b6fc5456de1 } from "../../Button-CFnNdpNZ.js";
6
+ import { f as $07b14b47974efb58$export$5b6b19405a83ff9d, i as $72a5793c14baf454$export$8b251419efc915eb } from "../../Dialog-DDfABlp4.js";
7
+ import { $ as $3985021b0ad6602f$export$f5b8910cec6cf069 } from "../../Input-B4X6-x6r.js";
7
8
  import { $ as $01b77f81d0f07f68$export$b04be29aa201d4f5 } from "../../Label-BDlf9vIY.js";
8
- import { $ as $eed445e0843c11d0$export$41f133550aa26f48 } from "../../ListBox-yHUyUAAH.js";
9
- import { f as $07b14b47974efb58$export$5b6b19405a83ff9d } from "../../Dialog-BbNWvB5_.js";
10
- import { $ as $82d7e5349645de74$export$ef9b1a59e592288f, a as $82d7e5349645de74$export$e288731fd71264f0, S as SelectClearButton, O as OptionItemBase } from "../../shared-DSTKnPjF.js";
11
- import { useRef, cloneElement } from "react";
9
+ import { $ as $eed445e0843c11d0$export$41f133550aa26f48, a as $eed445e0843c11d0$export$dca12b0bb56e4fc } from "../../ListBox-ByPsaVVK.js";
10
+ import { g as getGroupedOptions, $ as $82d7e5349645de74$export$ef9b1a59e592288f, a as $82d7e5349645de74$export$e288731fd71264f0, S as SelectClearButton, O as OptionItemBase } from "../../shared-HdRrpnhs.js";
11
+ import { $ as $e1995378a142960e$export$fb8073518f34e6ec } from "../../SelectionManager-iru59gc4.js";
12
+ import { useRef, useMemo, cloneElement } from "react";
12
13
  import { icons } from "../../icons/icons.js";
13
- import "../../react-jsx-parser.min-B_hvYYa1.js";
14
+ import "../../react-jsx-parser.min-DAh4myol.js";
14
15
  import { Spinner } from "../../icons/spinner.js";
15
16
  import { RichLabel } from "../rich-label/rich-label.js";
16
17
  import { unescapeHTML } from "../../utilities/text-helpers.js";
17
- import { randomId } from "../../utilities/hash.js";
18
18
  import { c as clsx } from "../../clsx-DgYk2OaC.js";
19
19
  import { c as cva } from "../../index-BHpUy2Ix.js";
20
20
  import { $ as $f86e6c1ec7da6ebb$export$bc3384a35de93d66 } from "../../useAsyncList-DsZvQXls.js";
@@ -39,6 +39,7 @@ import { $ as $f86e6c1ec7da6ebb$export$bc3384a35de93d66 } from "../../useAsyncLi
39
39
  * @param {Function} [props.getMeta] - Function to get the metadata for the item from the fetched data. `(item: Object<string, any>) => Object<string, any>` (optional)
40
40
  * @param {Function} [props.getIcon] - Function to get the icon for the item from the fetched data. `(item: Object<string, any>) => JSX.Element | string`
41
41
  * @param {Function} [props.getSubtitle] - Function to get the subtitle for the item from the fetched data. `(item: Object<string, any>) => string`
42
+ * @param {Function} [props.getGroup] - Function to get the group name for the item from the fetched data. `(item: Object<string, any>) => string`
42
43
  * @param {Function} [props.getData] - Function to pre-process the fetched data before it is used in the select. `(data: Object<string, any>[]) => Object<string, any>[]`
43
44
  * @param {Function} [props.fetchUrl] - Function to get the URL for fetching data. Provides typed search text if entered. `(searchText: string) => string`
44
45
  * @param {Object} [props.fetchConfig] - Configuration object for the fetch request, passed to the `fetch` function.
@@ -47,7 +48,9 @@ import { $ as $f86e6c1ec7da6ebb$export$bc3384a35de93d66 } from "../../useAsyncLi
47
48
  * @param {JSX.Element} [props.customMenuOption] - If provided, replaces the default item in the dropdown menu. `({ value: string, label: string, subtitle: string, metadata: any }) => JSX.Element`
48
49
  * @param {JSX.Element} [props.customValueDisplay] - If provided, replaces the default current value display of each selected item. `({ value: string, label: string, subtitle: string, metadata: any }) => JSX.Element`
49
50
  * @param {JSX.Element} [props.customDropdownArrow] - If provided, replaces the default dropdown arrow indicator.
50
- * @param {string} props.className - Classes to pass to the select menu.
51
+ * @param {string} [props.className] - Classes to pass to the select menu.
52
+ * @param {string} [props.groupKey] - If provided, the options will be grouped by this key.
53
+ * @param {Object} [props.groupValueMapping] - If provided, the group headers will be mapped to these labels/icons.
51
54
  * @param {boolean} [props.flat] - If `true`, component will look more flat. Useful for nested layer of controls.
52
55
  * @param {SelectSize} [props.size='default'] - Sets the size of the input field.
53
56
  * @param {boolean} [props.noMinWidth=false] - If `true`, the select menu will not have a minimum width.
@@ -98,9 +101,12 @@ const AsyncSelect = (props) => {
98
101
  getMeta,
99
102
  getIcon,
100
103
  getSubtitle,
104
+ getGroup,
101
105
  getData = (data) => data,
102
106
  extraItemProps,
103
107
  hidden,
108
+ groupKey,
109
+ groupValueMapping,
104
110
  flat,
105
111
  size = "default",
106
112
  noMinWidth = false,
@@ -116,7 +122,8 @@ const AsyncSelect = (props) => {
116
122
  json = processLoadedOptions ? processLoadedOptions(getData(res)) : getData(res);
117
123
  } else {
118
124
  const res = await fetch(fetchUrl(filterText), { ...fetchConfig, signal });
119
- json = processLoadedOptions ? processLoadedOptions(getData(await res.json())) : getData(res);
125
+ const data = await res.json();
126
+ json = processLoadedOptions ? processLoadedOptions(getData(data)) : getData(data);
120
127
  }
121
128
  const output = json?.map((item, index) => {
122
129
  const id = getValue?.(item) ?? index;
@@ -127,6 +134,9 @@ const AsyncSelect = (props) => {
127
134
  if (getSubtitle) {
128
135
  entry.subtitle = unescapeHTML(getSubtitle(item));
129
136
  }
137
+ if (getGroup) {
138
+ entry[groupKey ?? "_group"] = getGroup(item);
139
+ }
130
140
  return entry;
131
141
  });
132
142
  if (filterText.length > 0) {
@@ -145,6 +155,40 @@ const AsyncSelect = (props) => {
145
155
  }
146
156
  });
147
157
  const ref = useRef();
158
+ const groupedItems = useMemo(
159
+ () => getGroupedOptions(list?.items, groupKey ?? (getGroup ? "_group" : null), groupValueMapping),
160
+ [list?.items, groupKey, groupValueMapping, getGroup]
161
+ );
162
+ const renderItem = (item) => {
163
+ let icon2 = item?.icon ?? null;
164
+ if (typeof item?.icon === "string") {
165
+ icon2 = icons?.[item.icon] ?? null;
166
+ }
167
+ if (getIcon && !icon2) {
168
+ icon2 = getIcon(item);
169
+ }
170
+ return /* @__PURE__ */ jsxs(
171
+ OptionItemBase,
172
+ {
173
+ id: item.value,
174
+ textValue: item.label,
175
+ selectIndicator: true,
176
+ children: [
177
+ customMenuOption && customMenuOption(item),
178
+ !customMenuOption && /* @__PURE__ */ jsx(
179
+ RichLabel,
180
+ {
181
+ icon: icon2,
182
+ label: item.label,
183
+ subtitle: item.subtitle,
184
+ noColor: true
185
+ }
186
+ )
187
+ ]
188
+ },
189
+ item.value
190
+ );
191
+ };
148
192
  if (hidden) {
149
193
  return null;
150
194
  }
@@ -219,7 +263,6 @@ const AsyncSelect = (props) => {
219
263
  }
220
264
  );
221
265
  const handleSelectionChange = (selected) => {
222
- list.filterText = "";
223
266
  if (selected === null || selected === void 0) {
224
267
  onChange(null);
225
268
  return;
@@ -232,18 +275,20 @@ const AsyncSelect = (props) => {
232
275
  if (item && "id" in item) {
233
276
  delete item.id;
234
277
  }
235
- onChange({
236
- label: item?.label,
237
- value: item?.value,
238
- subtitle: item?.subtitle,
239
- meta: item?.meta
240
- });
278
+ onChange(item);
241
279
  };
242
280
  return /* @__PURE__ */ jsx(
243
281
  $82d7e5349645de74$export$ef9b1a59e592288f,
244
282
  {
245
283
  isDisabled: disabled,
246
284
  value: value?.value ?? null,
285
+ onOpenChange: (isOpen) => {
286
+ if (!isOpen) {
287
+ setTimeout(() => {
288
+ list.setFilterText("");
289
+ }, 100);
290
+ }
291
+ },
247
292
  onChange: (selected) => handleSelectionChange(selected),
248
293
  placeholder,
249
294
  ...rest,
@@ -363,7 +408,7 @@ const AsyncSelect = (props) => {
363
408
  placeholder: __("Search...", "eightshift-ui-components"),
364
409
  className: clsx(
365
410
  "es:peer es:size-full es:h-9.5 es:outline-hidden! es:pl-3.5 es:pr-9 es:shadow-none! es:text-13! es:placeholder:text-surface-500 es:[&::-webkit-search-cancel-button]:hidden",
366
- "es:bg-accent-900/8 es:m-1.5 es:rounded-3xl es:border-none!",
411
+ "es:bg-accent-900/8 es:m-1.5 es:rounded-3xl! es:border-none!",
367
412
  "es:inset-ring! es:inset-ring-accent-950/7 es:focus:inset-ring-accent-950/20",
368
413
  "es:text-accent-950 es:placeholder:text-accent-700/50",
369
414
  "es:transition"
@@ -373,6 +418,7 @@ const AsyncSelect = (props) => {
373
418
  /* @__PURE__ */ jsx(
374
419
  $d2b4bc8c273e7be6$export$353f5b6fc5456de1,
375
420
  {
421
+ slot: "clear",
376
422
  "aria-label": __("Clear", "eightshift-ui-components"),
377
423
  className: clsx(
378
424
  "es:absolute es:right-3 es:top-0 es:bottom-0 es:my-auto es:border-none es:bg-transparent",
@@ -386,11 +432,10 @@ const AsyncSelect = (props) => {
386
432
  }
387
433
  ),
388
434
  list.isLoading && /* @__PURE__ */ jsx("div", { className: "es:p-3 es:min-h-16 es:flex es:items-center es:justify-center", children: /* @__PURE__ */ jsx(Spinner, {}) }),
389
- /* @__PURE__ */ jsx(
435
+ /* @__PURE__ */ jsxs(
390
436
  $eed445e0843c11d0$export$41f133550aa26f48,
391
437
  {
392
438
  className: clsx("es:space-y-0.75 es:p-1.5 es:pt-0 es:any-focus:outline-hidden es:h-full es:overflow-y-auto es:rounded-t-xl", list?.isLoading && "es:hidden"),
393
- items: list.items,
394
439
  selectedKeys: list.selectedKeys,
395
440
  onSelectionChange: (selected) => {
396
441
  list.setSelectedKeys(selected);
@@ -407,34 +452,29 @@ const AsyncSelect = (props) => {
407
452
  noColor: true
408
453
  }
409
454
  ),
410
- children: (item) => {
411
- let icon2 = getIcon ? getIcon(item) : item?.icon ?? null;
412
- if (typeof item?.icon === "string") {
413
- icon2 = icons?.[item.icon] ?? null;
414
- }
415
- return /* @__PURE__ */ jsxs(
416
- OptionItemBase,
455
+ children: [
456
+ groupedItems && /* @__PURE__ */ jsx($e1995378a142960e$export$fb8073518f34e6ec, { items: groupedItems, children: (section) => /* @__PURE__ */ jsxs(
457
+ $eed445e0843c11d0$export$dca12b0bb56e4fc,
417
458
  {
418
- id: item?.value ?? randomId(8),
419
- className: item?.className,
420
- selectIndicator: true,
459
+ id: section.key,
460
+ className: "es:flex es:flex-col es:gap-0.75",
421
461
  children: [
422
- customMenuOption && customMenuOption(item),
423
- !customMenuOption && /* @__PURE__ */ jsx(
462
+ /* @__PURE__ */ jsx($72a5793c14baf454$export$8b251419efc915eb, { className: "es:px-2.5 es:pb-1 es:pt-3 es:select-none", children: /* @__PURE__ */ jsx(
424
463
  RichLabel,
425
464
  {
426
- icon: icon2,
427
- label: item?.label,
428
- subtitle: item?.subtitle,
429
- labelClassName: "es:line-clamp-1",
430
- subtitleClassName: "es:line-clamp-1",
431
- noColor: true
465
+ icon: section?.icon,
466
+ label: section?.label,
467
+ subtitle: section?.subtitle,
468
+ endIcon: section?.endIcon,
469
+ fullWidth: true
432
470
  }
433
- )
471
+ ) }),
472
+ /* @__PURE__ */ jsx($e1995378a142960e$export$fb8073518f34e6ec, { items: section.options, children: (item) => renderItem(item) })
434
473
  ]
435
474
  }
436
- );
437
- }
475
+ ) }),
476
+ !groupedItems && /* @__PURE__ */ jsx($e1995378a142960e$export$fb8073518f34e6ec, { items: list.items, children: (item) => renderItem(item) })
477
+ ]
438
478
  }
439
479
  )
440
480
  ]