@spear-ai/spectral 1.6.17 → 1.8.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 (149) hide show
  1. package/dist/.js +201 -200
  2. package/dist/Accordion.d.ts +13 -15
  3. package/dist/Accordion.js +184 -179
  4. package/dist/Alert/AlertBase.d.ts +7 -7
  5. package/dist/Alert/AlertBase.js +21 -21
  6. package/dist/Alert.d.ts +2 -2
  7. package/dist/Alert.js +31 -31
  8. package/dist/Avatar.d.ts +2 -2
  9. package/dist/Avatar.js +30 -22
  10. package/dist/Badge.d.ts +1 -1
  11. package/dist/Badge.js +3 -2
  12. package/dist/Button.d.ts +3 -3
  13. package/dist/Button.js +108 -46
  14. package/dist/ButtonGroup/ButtonGroupButton.d.ts +1 -1
  15. package/dist/ButtonGroup/ButtonGroupButton.js +5 -5
  16. package/dist/ButtonGroup.d.ts +5 -5
  17. package/dist/ButtonGroup.js +21 -21
  18. package/dist/ButtonIcon.d.ts +2 -2
  19. package/dist/ButtonIcon.js +30 -31
  20. package/dist/Checkbox/CheckboxBase.d.ts +2 -2
  21. package/dist/Checkbox/CheckboxBase.js +50 -57
  22. package/dist/Checkbox.js +15 -19
  23. package/dist/DataCard/Card.d.ts +1 -1
  24. package/dist/DataCard/Card.js +1 -1
  25. package/dist/DataCard.js +1 -1
  26. package/dist/DateTimePicker/Calendar.d.ts +4 -4
  27. package/dist/DateTimePicker/Calendar.js +3 -3
  28. package/dist/DateTimePicker/DateTimeDisplayInput.js +126 -136
  29. package/dist/DateTimePicker/DateTimeInput.js +4 -4
  30. package/dist/DateTimePicker/DateTimeUtils.d.ts +31 -31
  31. package/dist/DateTimePicker/DateTimeUtils.js +139 -197
  32. package/dist/DateTimePicker/TimePicker.d.ts +4 -4
  33. package/dist/DateTimePicker/TimePicker.js +3 -3
  34. package/dist/DateTimePicker.d.ts +5 -5
  35. package/dist/DateTimePicker.js +90 -70
  36. package/dist/Dialog.d.ts +13 -13
  37. package/dist/Dialog.js +57 -84
  38. package/dist/Drawer.d.ts +2 -2
  39. package/dist/Drawer.js +8 -8
  40. package/dist/HoverCard.d.ts +6 -5
  41. package/dist/HoverCard.js +64 -64
  42. package/dist/Icons/PolygonIcon.d.ts +5 -0
  43. package/dist/Icons/PolygonIcon.js +40 -0
  44. package/dist/Icons/index.d.ts +1 -1
  45. package/dist/Icons.js +34 -34
  46. package/dist/IconsAnimated/PanelLeftCloseIcon.js +2 -2
  47. package/dist/IconsAnimated/PanelLeftOpenIcon.js +2 -2
  48. package/dist/Input/InputUtils.d.ts +2 -2
  49. package/dist/Input/InputUtils.js +4 -4
  50. package/dist/Input.d.ts +1 -1
  51. package/dist/Input.js +19 -19
  52. package/dist/InputOTP.d.ts +10 -10
  53. package/dist/InputOTP.js +114 -114
  54. package/dist/Kbd.d.ts +8 -5
  55. package/dist/Kbd.js +85 -20
  56. package/dist/Label.d.ts +4 -2
  57. package/dist/Label.js +3 -3
  58. package/dist/MultiSelect/MultiSelectBase.d.ts +1 -1
  59. package/dist/MultiSelect/MultiSelectBase.js +278 -202
  60. package/dist/MultiSelect.d.ts +6 -6
  61. package/dist/MultiSelect.js +9 -9
  62. package/dist/Popover.js +22 -237
  63. package/dist/RadioButtonGroup/RadioButtonGroupBase.d.ts +11 -11
  64. package/dist/RadioButtonGroup/RadioButtonGroupBase.js +28 -28
  65. package/dist/RadioButtonGroup.d.ts +1 -1
  66. package/dist/RadioGroup.d.ts +15 -15
  67. package/dist/RadioGroup.js +253 -236
  68. package/dist/Select.d.ts +3 -1
  69. package/dist/Select.js +91 -88
  70. package/dist/Separator.js +4 -4
  71. package/dist/Skeleton.d.ts +1 -2
  72. package/dist/Skeleton.js +2 -4
  73. package/dist/Slider.d.ts +6 -6
  74. package/dist/Slider.js +78 -78
  75. package/dist/Switch/SwitchBase.d.ts +4 -4
  76. package/dist/Switch/SwitchBase.js +75 -111
  77. package/dist/Switch.d.ts +4 -4
  78. package/dist/Switch.js +122 -33
  79. package/dist/Tabs/TabsBase.js +39 -38
  80. package/dist/Tabs/tabsUtils.js +7 -7
  81. package/dist/Tabs.d.ts +0 -4
  82. package/dist/Tabs.js +62 -66
  83. package/dist/Textarea/TextareaUtils.d.ts +7 -7
  84. package/dist/Textarea/TextareaUtils.js +13 -13
  85. package/dist/Textarea.js +28 -18
  86. package/dist/Toast.d.ts +43 -0
  87. package/dist/Toast.js +883 -0
  88. package/dist/Toggle/ToggleBase.d.ts +4 -4
  89. package/dist/Toggle/ToggleBase.js +32 -33
  90. package/dist/Toggle.d.ts +1 -1
  91. package/dist/Toggle.js +7 -12
  92. package/dist/ToggleGroup/ToggleGroupBase.d.ts +5 -5
  93. package/dist/ToggleGroup/ToggleGroupBase.js +30 -30
  94. package/dist/ToggleGroup.d.ts +1 -1
  95. package/dist/ToggleGroup.js +27 -30
  96. package/dist/Tooltip.d.ts +1 -1
  97. package/dist/Tooltip.js +97 -97
  98. package/dist/Tray.d.ts +9 -9
  99. package/dist/Tray.js +71 -70
  100. package/dist/hooks/useAccordionAutoScroll.d.ts.map +1 -1
  101. package/dist/hooks/useAccordionAutoScroll.js +42 -39
  102. package/dist/hooks/useControllableState.d.ts +2 -2
  103. package/dist/hooks/useControllableState.d.ts.map +1 -1
  104. package/dist/hooks/useControllableState.js +2 -2
  105. package/dist/index-C12FUuIW.js +13 -0
  106. package/dist/{index-yU8jOTzS.js → index-CpovUAO-.js} +1 -1
  107. package/dist/{index-BdS7Ix8W.js → index-CqbPiOid.js} +1 -1
  108. package/dist/{index-B3UpsZ2x.js → index-CrjD9cAD.js} +1 -1
  109. package/dist/index-DEYs15GP.js +66 -0
  110. package/dist/index-DdFoGvON.js +146 -0
  111. package/dist/index-Q3N6lgwg.js +225 -0
  112. package/dist/index.d.ts +3 -3
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/primitives/button.d.ts +1 -1
  115. package/dist/primitives/button.js +4 -4
  116. package/dist/primitives/input.d.ts.map +1 -1
  117. package/dist/primitives/input.js +8 -5
  118. package/dist/primitives/select.d.ts +12 -13
  119. package/dist/primitives/select.d.ts.map +1 -1
  120. package/dist/primitives/select.js +59 -88
  121. package/dist/primitives/slot.d.ts +5 -5
  122. package/dist/primitives/slot.d.ts.map +1 -1
  123. package/dist/primitives/slot.js +24 -33
  124. package/dist/primitives/textarea.d.ts.map +1 -1
  125. package/dist/primitives/textarea.js +4 -3
  126. package/dist/{proxy-Cukf-VVj.js → proxy-CgaCj1WQ.js} +7 -3
  127. package/dist/styles/base-colors.css +30 -30
  128. package/dist/styles/horizon/base-colors.css +30 -30
  129. package/dist/styles/horizon/colors.css +43 -13
  130. package/dist/styles/horizon/utilities.css +26 -3
  131. package/dist/styles/main.css +1 -1
  132. package/dist/styles/spectral.css +2 -2
  133. package/dist/styles/theme.css +99 -46
  134. package/dist/{use-animation-zNd5Nq85.js → use-animation-CR-SdV2l.js} +1 -1
  135. package/dist/utils/formFieldUtils.d.ts +2 -2
  136. package/dist/utils/formFieldUtils.d.ts.map +1 -1
  137. package/dist/utils/formFieldUtils.js +14 -11
  138. package/dist/utils/sharedUtils.d.ts +3 -3
  139. package/dist/utils/sharedUtils.d.ts.map +1 -1
  140. package/dist/utils/sharedUtils.js +1 -4
  141. package/dist/utils/twUtils.d.ts +1 -1
  142. package/dist/utils/twUtils.d.ts.map +1 -1
  143. package/dist/utils/twUtils.js +1 -4
  144. package/package.json +6 -1
  145. package/dist/Icons/LineToolIcon2.d.ts +0 -5
  146. package/dist/Icons/LineToolIcon2.js +0 -49
  147. package/dist/createLucideIcon-D4r5Phnh.js +0 -70
  148. package/dist/index-CeP1E2kK.js +0 -209
  149. package/dist/index-Dy-Hzr7y.js +0 -13
@@ -31,7 +31,7 @@ export interface MultiSelectBaseProps extends Omit<ButtonHTMLAttributes<HTMLButt
31
31
  'aria-describedby'?: string;
32
32
  }
33
33
  export declare const MultiSelectBase: {
34
- ({ ref, className, clearAllLabel, closeOnSelect, emptyMessage, errorMessage, id, label, loadingMessage, maxCount, name, onChange, options, placeholder, searchPlaceholder, selectAllLabel, showClearAll, showSearch, showSelectAll, sortAlphabetically, state, value, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, ...props }: MultiSelectBaseProps & {
34
+ ({ className, clearAllLabel, closeOnSelect, emptyMessage, errorMessage, id, label, loadingMessage, maxCount, name, onChange, options, placeholder, ref, searchPlaceholder, selectAllLabel, showClearAll, showSearch, showSelectAll, sortAlphabetically, state, value, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, ...props }: MultiSelectBaseProps & {
35
35
  ref?: Ref<HTMLButtonElement>;
36
36
  }): import("react/jsx-runtime").JSX.Element;
37
37
  displayName: string;
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import "../styles/main.css";
3
- import { jsxs as o, jsx as r, Fragment as de } from "react/jsx-runtime";
3
+ import { jsxs as d, jsx as s, Fragment as ce } from "react/jsx-runtime";
4
4
  import "../Icons/AnalyzeIcon.js";
5
5
  import "../Icons/AnnotationsIcon.js";
6
6
  import "../Icons/ApprovedIcon.js";
@@ -9,12 +9,12 @@ import "../Icons/ArrowUpIcon.js";
9
9
  import "../Icons/CalendarIcon.js";
10
10
  import "../Icons/CheckCircleIcon.js";
11
11
  import "../Icons/CheckSquareIcon.js";
12
- import { CheckmarkIcon as ce } from "../Icons/CheckmarkIcon.js";
12
+ import { CheckmarkIcon as pe } from "../Icons/CheckmarkIcon.js";
13
13
  import { ChevronDownIcon as ue } from "../Icons/ChevronDownIcon.js";
14
14
  import "../Icons/ChevronUpIcon.js";
15
15
  import "../Icons/ClockIcon.js";
16
16
  import "../Icons/CloseCircleIcon.js";
17
- import { CloseIcon as T } from "../Icons/CloseIcon.js";
17
+ import { CloseIcon as Q } from "../Icons/CloseIcon.js";
18
18
  import "../Icons/DashboardIcon.js";
19
19
  import "../Icons/DatabaseIcon.js";
20
20
  import "../Icons/DeleteIcon.js";
@@ -34,9 +34,8 @@ import "../Icons/KeyboardIcon.js";
34
34
  import "../Icons/LabelIcon.js";
35
35
  import "../Icons/LassoIcon.js";
36
36
  import "../Icons/LineToolIcon.js";
37
- import "../Icons/LineToolIcon2.js";
38
37
  import "../Icons/LiveViewIcon.js";
39
- import { LoaderIcon as pe } from "../Icons/LoaderIcon.js";
38
+ import { LoaderIcon as me } from "../Icons/LoaderIcon.js";
40
39
  import "../Icons/LocationIcon.js";
41
40
  import "../Icons/LogoutIcon.js";
42
41
  import "../Icons/MeasureIcon.js";
@@ -48,10 +47,11 @@ import "../Icons/PanelIconClose.js";
48
47
  import "../Icons/PanelIconOpen.js";
49
48
  import "../Icons/PlayIcon.js";
50
49
  import "../Icons/PlusIcon.js";
50
+ import "../Icons/PolygonIcon.js";
51
51
  import "../Icons/ResetIcon.js";
52
52
  import "../Icons/ReviewedIcon.js";
53
53
  import "../Icons/ScissorsIcon.js";
54
- import "../Icons/SearchIcon.js";
54
+ import { SearchIcon as fe } from "../Icons/SearchIcon.js";
55
55
  import "../Icons/SettingsIcon.js";
56
56
  import "../Icons/SortAscendingIcon.js";
57
57
  import "../Icons/SortAtoZIcon.js";
@@ -67,260 +67,336 @@ import "../Icons/WarningIcon.js";
67
67
  import "../Icons/ZoomAllIcon.js";
68
68
  import "../Icons/ZoomXIcon.js";
69
69
  import "../Icons/ZoomYIcon.js";
70
- import { ErrorMessage as me } from "../utils/formFieldUtils.js";
71
- import { cn as x } from "../utils/twUtils.js";
72
- import { useId as be, useState as L, useRef as $, useMemo as _, useCallback as b, useEffect as fe } from "react";
73
- import { c as ge } from "../createLucideIcon-D4r5Phnh.js";
74
- const he = [
75
- ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
76
- ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
77
- ], xe = ge("search", he), ye = "h-4 w-4", ve = (s) => ({
70
+ import { R as be, T as ge, P as he, C as xe } from "../index-Q3N6lgwg.js";
71
+ import { ErrorMessage as ye } from "../utils/formFieldUtils.js";
72
+ import { cn as y } from "../utils/twUtils.js";
73
+ import { useId as ve, useState as V, useRef as we, useMemo as v, useCallback as w, useEffect as Ne } from "react";
74
+ const Ie = "h-4 w-4", Ce = (b) => ({
78
75
  error: "border-danger hover:border-danger focus-visible:border-danger focus-visible:ring-danger",
79
76
  loading: "cursor-wait border-input-border--disabled",
80
77
  disabled: "cursor-not-allowed opacity-50 border-input-border--disabled bg-input-bg--disabled",
81
78
  default: ""
82
- })[s], we = (s, n, d) => x(
83
- "flex h-12 w-full items-center justify-between rounded-lg border border-input-border bg-input-bg px-4 py-3 text-sm",
84
- "hover:border-input-border--hover focus:border-input-border--focus focus:outline-none",
85
- "focus:ring-2 focus:ring-black focus:ring-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2",
79
+ })[b], ke = (b, g, m) => y(
80
+ "flex min-h-12 max-h-[5.5rem] w-full items-center justify-between rounded-lg border border-input-border bg-input-bg px-4 py-2 text-sm",
81
+ "hover:border-input-border--hover focus-visible:border-input-border--focus",
82
+ "focus-visible:outline focus-visible:outline-accent focus-visible:outline-offset-2 focus:outline-none",
86
83
  "disabled:cursor-not-allowed disabled:opacity-50 disabled:border-input-border--disabled disabled:bg-input-bg--disabled",
87
- "transition duration-200 text-input-text",
88
- n && "border-input-border--focus ring-2 ring-black ring-offset-2",
89
- ve(s),
90
- d
91
- ), Ne = (s) => x(
92
- "absolute top-full left-0 right-0 z-50 mt-1 max-h-80 overflow-hidden rounded-lg border border-input-border bg-input-bg shadow-lg",
93
- "transition-all duration-200 origin-top",
94
- s ? "scale-100 opacity-100 translate-y-0" : "scale-95 opacity-0 -translate-y-1 pointer-events-none"
95
- ), ke = (s) => {
96
- const n = $(null);
97
- return fe(() => {
98
- const d = (l) => {
99
- n.current && !n.current.contains(l.target) && s();
100
- };
101
- return document.addEventListener("mousedown", d), () => document.removeEventListener("mousedown", d);
102
- }, [s]), n;
103
- }, Ce = (s, n, d) => {
104
- const [l, y] = L(-1), N = b(
105
- (u) => {
106
- const k = {
84
+ "transition duration-200 text-input-text overflow-hidden",
85
+ g && "border-input-border--focus",
86
+ Ce(b),
87
+ m
88
+ ), Oe = () => y(
89
+ "z-50 max-h-80 overflow-hidden rounded-lg border border-input-border bg-input-bg shadow-lg",
90
+ "motion-safe:data-[state=open]:animate-in motion-safe:data-[state=closed]:animate-out",
91
+ "motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=open]:fade-in-0",
92
+ "motion-safe:data-[state=closed]:zoom-out-95 motion-safe:data-[state=open]:zoom-in-95",
93
+ "motion-safe:data-[side=bottom]:slide-in-from-top-2",
94
+ "motion-safe:data-[side=top]:slide-in-from-bottom-2",
95
+ "origin-(--radix-popover-content-transform-origin)"
96
+ ), De = (b, g, m, I, N, D, S, F, j) => {
97
+ const [t, c] = V(-1), r = v(() => {
98
+ const o = [];
99
+ return S && o.push({ type: "search" }), F && o.push({ type: "select-all" }), b.forEach((p, f) => {
100
+ p.disabled || o.push({ type: "option", index: f, value: p.value });
101
+ }), o;
102
+ }, [b, S, F, j]), x = w(
103
+ (o) => {
104
+ if (o < 0 || o >= r.length) return;
105
+ r[o].type === "search" && D.current?.focus();
106
+ },
107
+ [r, D]
108
+ ), E = w(
109
+ (o) => {
110
+ const p = t >= 0 && t < r.length ? r[t] : null;
111
+ if (o.key === " " && p?.type === "search" || o.key === "Enter" && p?.type === "search")
112
+ return;
113
+ const n = {
107
114
  ArrowDown: () => {
108
- u.preventDefault(), y((f) => Math.min(f + 1, s.length - 1));
115
+ o.preventDefault();
116
+ const l = Math.min(t + 1, r.length - 1);
117
+ c(l), x(l);
109
118
  },
110
119
  ArrowUp: () => {
111
- u.preventDefault(), y((f) => Math.max(f - 1, -1));
120
+ o.preventDefault();
121
+ const l = Math.max(t - 1, 0);
122
+ c(l), x(l);
123
+ },
124
+ Tab: () => {
125
+ if (o.shiftKey)
126
+ if (t <= 0)
127
+ m();
128
+ else {
129
+ o.preventDefault();
130
+ const l = t - 1;
131
+ c(l), x(l);
132
+ }
133
+ else if (t >= r.length - 1)
134
+ m();
135
+ else {
136
+ o.preventDefault();
137
+ const l = t + 1;
138
+ c(l), x(l);
139
+ }
112
140
  },
113
141
  Enter: () => {
114
- u.preventDefault(), l >= 0 && s[l] && n(s[l].value);
142
+ if (o.preventDefault(), t >= 0 && t < r.length) {
143
+ const l = r[t];
144
+ l.type === "select-all" ? N() : l.type === "clear-all" ? g() : l.type === "option" && I(l.value);
145
+ }
115
146
  },
116
147
  " ": () => {
117
- u.preventDefault(), l >= 0 && s[l] && n(s[l].value);
148
+ if (o.preventDefault(), t >= 0 && t < r.length) {
149
+ const l = r[t];
150
+ l.type === "select-all" ? N() : l.type === "clear-all" ? g() : l.type === "option" && I(l.value);
151
+ }
118
152
  },
119
153
  Escape: () => {
120
- u.preventDefault(), d();
154
+ o.preventDefault(), m();
121
155
  }
122
- }[u.key];
123
- k && k();
156
+ }[o.key];
157
+ n && n();
124
158
  },
125
- [s, l, n, d]
126
- );
127
- return { focusedIndex: l, setFocusedIndex: y, handleKeyDown: N };
128
- }, Ie = ({
129
- ref: s,
130
- className: n,
131
- clearAllLabel: d = "Clear all",
132
- closeOnSelect: l = !1,
133
- emptyMessage: y = "No options found",
159
+ [r, t, I, N, g, m, x]
160
+ ), M = w(
161
+ (o) => {
162
+ if (t < 0 || t >= r.length) return !1;
163
+ const p = r[t];
164
+ return p.type === "option" && p.index === o;
165
+ },
166
+ [t, r]
167
+ ), z = v(() => t < 0 || t >= r.length ? !1 : r[t].type === "search", [t, r]), P = v(() => t < 0 || t >= r.length ? !1 : r[t].type === "select-all", [t, r]), C = v(() => t < 0 || t >= r.length ? !1 : r[t].type === "clear-all", [t, r]);
168
+ return {
169
+ focusedIndex: t,
170
+ setFocusedIndex: c,
171
+ handleKeyDown: E,
172
+ getOptionFocusIndex: M,
173
+ isSearchFocused: z,
174
+ isSelectAllFocused: P,
175
+ isClearAllFocused: C
176
+ };
177
+ }, Se = ({
178
+ className: b,
179
+ clearAllLabel: g = "Clear all",
180
+ closeOnSelect: m = !1,
181
+ emptyMessage: I = "No options found",
134
182
  errorMessage: N,
135
- id: u,
136
- label: M,
137
- loadingMessage: k = "Loading options...",
138
- maxCount: f = 3,
139
- name: z,
140
- onChange: p,
141
- options: m = [],
142
- placeholder: B = "Select options",
143
- searchPlaceholder: H = "Search options...",
144
- selectAllLabel: V = "Select all",
145
- showClearAll: G = !0,
146
- showSearch: U = !0,
147
- showSelectAll: Z = !0,
148
- sortAlphabetically: K = !1,
149
- state: g = "default",
150
- value: a = [],
151
- "aria-label": q,
152
- "aria-describedby": J,
153
- ...R
183
+ id: D,
184
+ label: S,
185
+ loadingMessage: F = "Loading options",
186
+ maxCount: j = 3,
187
+ name: t,
188
+ onChange: c,
189
+ options: r = [],
190
+ placeholder: x = "Select options",
191
+ ref: E,
192
+ searchPlaceholder: M = "Search options…",
193
+ selectAllLabel: z = "Select all",
194
+ showClearAll: P = !0,
195
+ showSearch: C = !0,
196
+ showSelectAll: o = !0,
197
+ sortAlphabetically: p = !1,
198
+ state: f = "default",
199
+ value: n = [],
200
+ "aria-label": l,
201
+ "aria-describedby": W,
202
+ ...H
154
203
  }) => {
155
- const Q = be(), S = u || `${z}-${Q}`, A = `${S}-error`, [h, C] = L(!1), [D, W] = L(""), X = ke(() => C(!1)), F = $(null), O = R.disabled || g === "disabled", Y = g === "loading", ee = g === "error", v = _(() => {
156
- let e = m.filter((i) => i.label.toLowerCase().includes(D.toLowerCase()));
157
- return K && (e = [...e].sort((i, t) => i.label.localeCompare(t.label))), e;
158
- }, [m, D, K]), w = _(() => {
159
- const e = {}, i = [];
160
- return v.forEach((t) => {
161
- t.group ? (e[t.group] || (e[t.group] = []), e[t.group].push(t)) : i.push(t);
162
- }), { groups: e, ungrouped: i, hasGroups: Object.keys(e).length > 0 };
163
- }, [v]), I = b(
204
+ const X = ve(), K = D ?? `${t}-${X}`, _ = `${K}-listbox`, G = `${K}-error`, [h, L] = V(!1), [T, Y] = V(""), R = we(null), ee = H.disabled ?? f === "disabled", te = f === "loading", re = f === "error", k = v(() => {
205
+ let e = r.filter((a) => a.label.toLowerCase().includes(T.toLowerCase()));
206
+ return p && (e = [...e].sort((a, i) => a.label.localeCompare(i.label))), e;
207
+ }, [r, T, p]), O = v(() => {
208
+ const e = {}, a = [];
209
+ return k.forEach((i) => {
210
+ i.group ? (e[i.group] || (e[i.group] = []), e[i.group].push(i)) : a.push(i);
211
+ }), { groups: e, ungrouped: a, hasGroups: Object.keys(e).length > 0 };
212
+ }, [k]), $ = w(
164
213
  (e) => {
165
- if (m.find((c) => c.value === e)?.disabled) return;
166
- const t = a.includes(e) ? a.filter((c) => c !== e) : [...a, e];
167
- p(t), l && C(!1);
214
+ if (r.find((u) => u.value === e)?.disabled) return;
215
+ const i = n.includes(e) ? n.filter((u) => u !== e) : [...n, e];
216
+ c(i), m && L(!1);
168
217
  },
169
- [m, a, p, l]
170
- ), { focusedIndex: te, handleKeyDown: re } = Ce(v, I, () => C(!1)), ie = b(() => {
171
- O || C((e) => (e || setTimeout(() => F.current?.focus(), 0), !e));
172
- }, [O]), se = b(() => {
173
- const e = m.filter((t) => !t.disabled).map((t) => t.value), i = e.every((t) => a.includes(t));
174
- p(i ? [] : e);
175
- }, [m, a, p]), j = b(() => {
176
- p([]);
177
- }, [p]), oe = b((e) => {
178
- W(e.target.value);
179
- }, []), le = b(
180
- (e, i) => {
181
- i.stopPropagation(), I(e);
182
- },
183
- [I]
184
- ), ne = () => {
185
- if (a.length === 0)
186
- return /* @__PURE__ */ r("span", { className: "text-input-text-placeholder", children: B });
187
- const e = a.slice(0, f), i = a.length - f;
188
- return /* @__PURE__ */ o("div", { className: "flex flex-wrap items-center gap-1", children: [
189
- e.map((t) => {
190
- const c = m.find((E) => E.value === t);
191
- return c ? /* @__PURE__ */ o("span", { className: "bg-input-bg--selected text-input-text inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs", children: [
192
- c.label,
193
- /* @__PURE__ */ r("button", { "aria-label": `Remove ${c.label}`, className: "hover:text-danger focus:outline-none", "data-testid": "spectral-multiselect-remove-item-button", onClick: (E) => le(t, E), type: "button", children: /* @__PURE__ */ r(T, { size: 12 }) })
194
- ] }, t) : null;
218
+ [r, n, c, m]
219
+ ), U = w(() => {
220
+ const e = r.filter((i) => !i.disabled).map((i) => i.value), a = e.every((i) => n.includes(i));
221
+ c(a ? [] : e);
222
+ }, [r, n, c]), Z = w(() => {
223
+ c([]);
224
+ }, [c]), q = v(() => r.filter((e) => !e.disabled).map((e) => e.value), [r]), ie = q.length > 0 && q.every((e) => n.includes(e)), { getOptionFocusIndex: se, handleKeyDown: oe, isSelectAllFocused: le, setFocusedIndex: A } = De(
225
+ k,
226
+ Z,
227
+ () => L(!1),
228
+ $,
229
+ U,
230
+ R,
231
+ C,
232
+ o,
233
+ !1
234
+ // No separate clear-all button in dropdown
235
+ );
236
+ Ne(() => {
237
+ A(h ? 0 : -1);
238
+ }, [h, A]);
239
+ const ae = w((e) => {
240
+ Y(e.target.value);
241
+ }, []), ne = () => {
242
+ if (n.length === 0)
243
+ return /* @__PURE__ */ s("span", { className: "text-input-text-placeholder flex min-h-8 items-center", children: x });
244
+ const e = n.slice(0, j), a = n.length - j;
245
+ return /* @__PURE__ */ d("div", { className: "flex flex-wrap items-center gap-1 overflow-hidden", children: [
246
+ e.map((i) => {
247
+ const u = r.find((B) => B.value === i);
248
+ return u ? /* @__PURE__ */ d("span", { className: "bg-input-bg--selected text-input-text inline-flex max-w-48 items-center gap-1 rounded-md px-2 py-1 text-xs", children: [
249
+ /* @__PURE__ */ s("span", { className: "truncate", children: u.label }),
250
+ /* @__PURE__ */ s(
251
+ "button",
252
+ {
253
+ "aria-label": "Remove" + u.label,
254
+ className: "hover:text-danger focus-visible:ring-accent cursor-pointer rounded-sm focus-visible:ring-2 focus-visible:ring-offset-1",
255
+ "data-testid": "spectral-multiselect-remove-item-button",
256
+ onClick: (B) => {
257
+ B.stopPropagation(), $(i);
258
+ },
259
+ type: "button",
260
+ children: /* @__PURE__ */ s(Q, { size: 12 })
261
+ }
262
+ )
263
+ ] }, i) : null;
195
264
  }),
196
- i > 0 && /* @__PURE__ */ o("span", { className: "text-input-text-secondary text-xs", children: [
265
+ a > 0 && /* @__PURE__ */ d("span", { className: "text-input-text-secondary flex items-center py-1 text-xs", children: [
197
266
  "+",
198
- i,
267
+ a,
199
268
  " more"
200
269
  ] })
201
270
  ] });
202
- }, P = (e, i) => {
203
- const t = a.includes(e.value);
204
- return /* @__PURE__ */ o(
271
+ }, J = (e, a) => {
272
+ const i = n.includes(e.value), u = se(a);
273
+ return /* @__PURE__ */ d(
205
274
  "button",
206
275
  {
207
- className: x(
208
- "hover:bg-input-bg--hover focus:bg-input-bg--hover flex w-full items-center gap-3 px-3 py-2 text-left text-sm focus:outline-none",
209
- "disabled:cursor-not-allowed disabled:opacity-50",
210
- i === te && "bg-input-bg--hover",
211
- t && "text-input-text font-medium"
276
+ className: y(
277
+ "hover:bg-input-bg--hover focus-visible:bg-input-bg--hover flex w-full items-center gap-3 px-3 py-2 text-left text-sm focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
278
+ u && "bg-input-bg--hover",
279
+ i && "text-input-text font-medium"
212
280
  ),
213
281
  disabled: e.disabled,
214
- onClick: () => I(e.value),
282
+ onClick: () => $(e.value),
215
283
  type: "button",
216
284
  children: [
217
- /* @__PURE__ */ r("div", { "data-testid": "spectral-multiselect-selected-indicator", className: x("border-input-border flex h-4 w-4 items-center justify-center rounded border", t && "bg-primary border-primary"), children: t && /* @__PURE__ */ r(ce, { size: 12 }) }),
218
- /* @__PURE__ */ r("span", { children: e.label })
285
+ /* @__PURE__ */ s("div", { "data-testid": "spectral-multiselect-selected-indicator", className: y("border-input-border flex h-4 w-4 items-center justify-center rounded border", i && "bg-primary border-primary"), children: i && /* @__PURE__ */ s(pe, { size: 12 }) }),
286
+ /* @__PURE__ */ s("span", { children: e.label })
219
287
  ]
220
288
  },
221
289
  e.value
222
290
  );
223
- }, ae = () => ({
291
+ }, de = () => ({
224
292
  "--multiselect-border-radius": "0.5rem",
225
293
  "--multiselect-trigger-height": "3rem",
226
294
  "--multiselect-dropdown-max-height": "20rem"
227
295
  });
228
- return /* @__PURE__ */ o("div", { className: "w-full", "data-testid": "spectral-multiselect-root", children: [
229
- /* @__PURE__ */ o("div", { className: "relative", "data-testid": "spectral-multiselect-wrapper", onKeyDown: h ? re : void 0, ref: X, children: [
230
- /* @__PURE__ */ o(
296
+ return /* @__PURE__ */ d("div", { className: "w-full", "data-testid": "spectral-multiselect-root", children: [
297
+ /* @__PURE__ */ s(be, { open: h, onOpenChange: L, children: /* @__PURE__ */ d("div", { "data-testid": "spectral-multiselect-wrapper", onKeyDown: h ? oe : void 0, children: [
298
+ /* @__PURE__ */ s(ge, { asChild: !0, children: /* @__PURE__ */ d(
231
299
  "button",
232
300
  {
233
- "aria-controls": h ? S : void 0,
234
- "aria-describedby": [ee ? A : null, J].filter(Boolean).join(" ") || void 0,
301
+ "aria-controls": h ? _ : void 0,
302
+ "aria-describedby": [re ? G : null, W].filter(Boolean).join(" ") || void 0,
235
303
  "aria-expanded": h,
236
- "aria-label": q || M,
237
- className: we(g, h, n),
238
- "data-state": g,
304
+ "aria-label": l ?? S,
305
+ className: ke(f, h, b),
306
+ "data-state": f,
239
307
  "data-testid": "spectral-multiselect-trigger",
240
- disabled: O,
241
- id: S,
242
- name: z,
243
- onClick: ie,
244
- ref: s,
308
+ disabled: ee,
309
+ id: K,
310
+ name: t,
311
+ ref: E,
245
312
  role: "combobox",
246
- style: ae(),
313
+ style: de(),
247
314
  type: "button",
248
- ...R,
315
+ ...H,
249
316
  children: [
250
- /* @__PURE__ */ r("div", { className: "min-w-0 flex-1", "data-testid": "spectral-multiselect-selected-items", children: ne() }),
251
- /* @__PURE__ */ o("div", { className: "ml-2 flex items-center gap-2", children: [
252
- a.length > 0 && /* @__PURE__ */ r(
253
- "span",
317
+ /* @__PURE__ */ s("div", { className: "min-w-0 flex-1 overflow-hidden", "data-testid": "spectral-multiselect-selected-items", children: ne() }),
318
+ /* @__PURE__ */ d("div", { className: "ml-2 flex shrink-0 items-center gap-2", children: [
319
+ P && n.length > 0 && /* @__PURE__ */ s(
320
+ "button",
254
321
  {
255
322
  "aria-label": "Clear all selections",
256
- className: "text-input-icon hover:text-input-icon--hover cursor-pointer focus:outline-none",
323
+ className: "text-input-icon hover:text-input-icon--hover focus-visible:ring-accent cursor-pointer rounded-sm focus-visible:ring-2 focus-visible:ring-offset-1",
257
324
  "data-testid": "spectral-multiselect-clear-all-button",
258
325
  onClick: (e) => {
259
- e.stopPropagation(), j();
260
- },
261
- onKeyDown: (e) => {
262
- (e.key === "Enter" || e.key === " ") && (e.preventDefault(), e.stopPropagation(), j());
326
+ e.stopPropagation(), Z();
263
327
  },
264
- tabIndex: 0,
265
- children: /* @__PURE__ */ r(T, { size: 12 })
328
+ type: "button",
329
+ children: /* @__PURE__ */ s(Q, { size: 12 })
266
330
  }
267
331
  ),
268
- /* @__PURE__ */ r(ue, { className: x("text-input-icon transition-transform duration-200", h && "rotate-180"), size: 20 })
332
+ /* @__PURE__ */ s(ue, { className: y("text-input-icon transition-transform duration-200", h && "rotate-180"), size: 20 })
269
333
  ] })
270
334
  ]
271
335
  }
272
- ),
273
- /* @__PURE__ */ r("div", { className: Ne(h), "data-testid": "spectral-multiselect-dropdown", children: /* @__PURE__ */ o("div", { className: "p-1", children: [
274
- U && /* @__PURE__ */ o("div", { className: "relative mb-2", children: [
275
- /* @__PURE__ */ r(xe, { className: x(ye, "text-input-icon absolute top-1/2 left-3 -translate-y-1/2") }),
276
- /* @__PURE__ */ r(
277
- "input",
278
- {
279
- "aria-label": "Search options",
280
- className: "border-input-border bg-input-bg focus:border-input-border--focus w-full rounded-md border py-2 pr-3 pl-9 text-sm focus:ring-1 focus:ring-black focus:outline-none",
281
- "data-testid": "spectral-multiselect-search-input",
282
- onChange: oe,
283
- placeholder: H,
284
- ref: F,
285
- type: "text",
286
- value: D
287
- }
288
- )
289
- ] }),
290
- /* @__PURE__ */ r("div", { className: "max-h-64 overflow-y-auto", role: "listbox", "aria-multiselectable": "true", children: Y ? /* @__PURE__ */ o("div", { "data-testid": "spectral-multiselect-loading", className: "text-input-text-secondary flex items-center justify-center gap-2 py-6 text-sm", children: [
291
- /* @__PURE__ */ r(pe, {}),
292
- k
293
- ] }) : v.length === 0 ? /* @__PURE__ */ r("div", { "data-testid": "spectral-multiselect-empty-message", className: "text-input-text-secondary py-6 text-center text-sm", children: y }) : /* @__PURE__ */ o(de, { children: [
294
- Z && /* @__PURE__ */ o("div", { className: "mb-1", children: [
295
- /* @__PURE__ */ r(
296
- "button",
297
- {
298
- className: "text-input-text-secondary hover:bg-input-bg--hover focus:bg-input-bg--hover flex w-full items-center gap-3 px-3 py-2 text-sm font-medium focus:outline-none",
299
- "data-testid": "spectral-multiselect-select-all-button",
300
- onClick: se,
301
- type: "button",
302
- children: V
303
- }
304
- ),
305
- /* @__PURE__ */ r("div", { className: "bg-input-border mx-3 my-1 h-px" })
306
- ] }),
307
- w.ungrouped.length > 0 && /* @__PURE__ */ r("div", { className: "mb-1", children: w.ungrouped.map((e, i) => P(e, i)) }),
308
- Object.entries(w.groups).map(([e, i]) => /* @__PURE__ */ o("div", { className: "mb-1", "data-testid": "spectral-multiselect-group", children: [
309
- (w.ungrouped.length > 0 || Object.keys(w.groups).indexOf(e) > 0) && /* @__PURE__ */ r("div", { className: "bg-input-border mx-3 my-1 h-px" }),
310
- /* @__PURE__ */ r("div", { "data-testid": "spectral-multiselect-group-name", className: "text-input-text-secondary px-3 py-1 text-xs font-semibold tracking-wide uppercase", children: e }),
311
- i.map((t, c) => P(t, v.indexOf(t)))
312
- ] }, e)),
313
- G && a.length > 0 && /* @__PURE__ */ o("div", { className: "mt-1", children: [
314
- /* @__PURE__ */ r("div", { className: "bg-input-border mx-3 my-1 h-px" }),
315
- /* @__PURE__ */ r("button", { className: "text-danger hover:bg-danger-50 focus:bg-danger-50 flex w-full items-center gap-3 px-3 py-2 text-sm font-medium focus:outline-none", "data-testid": "spectral-multiselect-clear-all-button", onClick: j, type: "button", children: d })
336
+ ) }),
337
+ /* @__PURE__ */ s(he, { children: /* @__PURE__ */ s(
338
+ xe,
339
+ {
340
+ align: "start",
341
+ avoidCollisions: !0,
342
+ className: Oe(),
343
+ collisionPadding: 10,
344
+ "data-testid": "spectral-multiselect-dropdown",
345
+ onOpenAutoFocus: (e) => {
346
+ e.preventDefault(), C && R.current?.focus();
347
+ },
348
+ side: "bottom",
349
+ sideOffset: 4,
350
+ style: { width: "var(--radix-popover-trigger-width)" },
351
+ children: /* @__PURE__ */ d("div", { className: "p-1", children: [
352
+ C && /* @__PURE__ */ d("div", { className: "relative mb-2", children: [
353
+ /* @__PURE__ */ s(fe, { className: y(Ie, "text-input-icon absolute top-1/2 left-3 -translate-y-1/2") }),
354
+ /* @__PURE__ */ s(
355
+ "input",
356
+ {
357
+ "aria-label": "Search options",
358
+ className: "border-input-border bg-input-bg focus-visible:border-input-border--focus w-full rounded-md border py-2 pr-3 pl-9 text-sm focus-visible:ring-1 focus-visible:ring-black focus-visible:outline-none",
359
+ "data-testid": "spectral-multiselect-search-input",
360
+ onChange: ae,
361
+ placeholder: M,
362
+ ref: R,
363
+ type: "text",
364
+ value: T
365
+ }
366
+ )
367
+ ] }),
368
+ /* @__PURE__ */ s("div", { className: "max-h-64 overflow-y-auto", id: _, role: "listbox", "aria-multiselectable": "true", children: te ? /* @__PURE__ */ d("div", { "data-testid": "spectral-multiselect-loading", className: "text-input-text-secondary flex items-center justify-center gap-2 py-6 text-sm", children: [
369
+ /* @__PURE__ */ s(me, {}),
370
+ F
371
+ ] }) : k.length === 0 ? /* @__PURE__ */ s("div", { "data-testid": "spectral-multiselect-empty-message", className: "text-input-text-secondary py-6 text-center text-sm", children: I }) : /* @__PURE__ */ d(ce, { children: [
372
+ o && /* @__PURE__ */ d("div", { className: "mb-1", children: [
373
+ /* @__PURE__ */ s(
374
+ "button",
375
+ {
376
+ className: y("text-input-text-secondary hover:bg-input-bg--hover flex w-full items-center gap-3 px-3 py-2 text-sm font-medium focus:outline-none", le && "bg-input-bg--hover"),
377
+ "data-testid": "spectral-multiselect-select-all-button",
378
+ onClick: U,
379
+ type: "button",
380
+ children: ie ? g : z
381
+ }
382
+ ),
383
+ /* @__PURE__ */ s("div", { className: "bg-input-border mx-3 my-1 h-px" })
384
+ ] }),
385
+ O.ungrouped.length > 0 && /* @__PURE__ */ s("div", { className: "mb-1", children: O.ungrouped.map((e, a) => J(e, a)) }),
386
+ Object.entries(O.groups).map(([e, a]) => /* @__PURE__ */ d("div", { className: "mb-1", "data-testid": "spectral-multiselect-group", children: [
387
+ (O.ungrouped.length > 0 || Object.keys(O.groups).indexOf(e) > 0) && /* @__PURE__ */ s("div", { className: "bg-input-border mx-3 my-1 h-px" }),
388
+ /* @__PURE__ */ s("div", { "data-testid": "spectral-multiselect-group-name", className: "text-input-text-secondary px-3 py-1 text-xs font-semibold tracking-wide uppercase", children: e }),
389
+ a.map((i, u) => J(i, k.indexOf(i)))
390
+ ] }, e))
391
+ ] }) })
316
392
  ] })
317
- ] }) })
318
- ] }) })
319
- ] }),
320
- g === "error" && N && /* @__PURE__ */ r(me, { id: A, dataTestId: "spectral-multiselect-error-message", message: N })
393
+ }
394
+ ) })
395
+ ] }) }),
396
+ f === "error" && N && /* @__PURE__ */ s(ye, { dataTestId: "spectral-multiselect-error-message", id: G, message: N })
321
397
  ] });
322
398
  };
323
- Ie.displayName = "MultiSelectBase";
399
+ Se.displayName = "MultiSelectBase";
324
400
  export {
325
- Ie as MultiSelectBase
401
+ Se as MultiSelectBase
326
402
  };
@@ -1,21 +1,21 @@
1
1
  import { MultiSelectBaseProps } from './MultiSelectBase';
2
2
  import { Ref } from 'react';
3
3
  export interface MultiSelectProps extends Omit<MultiSelectBaseProps, 'onChange' | 'options' | 'value'> {
4
+ emptyText?: string;
5
+ loading?: boolean;
4
6
  onSearchChange?: (search: string) => void;
5
7
  onValueChange?: (value: string[]) => void;
6
- value?: string[];
7
- options: Array<{
8
+ options: {
8
9
  disabled?: boolean;
9
10
  group?: string;
10
11
  label: string;
11
12
  value: string;
12
- }>;
13
- emptyText?: string;
14
- loading?: boolean;
13
+ }[];
15
14
  sortAlphabetically?: boolean;
15
+ value?: string[];
16
16
  }
17
17
  export declare const MultiSelect: {
18
- ({ ref, emptyText, loading, onValueChange, options, state, value, ...props }: MultiSelectProps & {
18
+ ({ emptyText, loading, onValueChange, options, ref, state, value, ...props }: MultiSelectProps & {
19
19
  ref?: Ref<HTMLButtonElement>;
20
20
  }): import("react/jsx-runtime").JSX.Element;
21
21
  displayName: string;