@simplybusiness/mobius 10.3.2 → 10.3.4

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 (166) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/components/AddressLookup/AddressLookup.js +888 -5314
  3. package/dist/cjs/components/AddressLookup/AddressLookup.js.map +4 -4
  4. package/dist/cjs/components/AddressLookup/index.js +952 -5381
  5. package/dist/cjs/components/AddressLookup/index.js.map +4 -4
  6. package/dist/cjs/components/Checkbox/Checkbox.js +245 -5625
  7. package/dist/cjs/components/Checkbox/Checkbox.js.map +4 -4
  8. package/dist/cjs/components/Checkbox/CheckboxGroup.js +371 -5614
  9. package/dist/cjs/components/Checkbox/CheckboxGroup.js.map +4 -4
  10. package/dist/cjs/components/Checkbox/index.js +377 -5619
  11. package/dist/cjs/components/Checkbox/index.js.map +4 -4
  12. package/dist/cjs/components/Combobox/Combobox.js +829 -5344
  13. package/dist/cjs/components/Combobox/Combobox.js.map +4 -4
  14. package/dist/cjs/components/Combobox/index.js +813 -5327
  15. package/dist/cjs/components/Combobox/index.js.map +4 -4
  16. package/dist/cjs/components/DateField/DateField.js +379 -5505
  17. package/dist/cjs/components/DateField/DateField.js.map +4 -4
  18. package/dist/cjs/components/DateField/index.js +383 -5508
  19. package/dist/cjs/components/DateField/index.js.map +4 -4
  20. package/dist/cjs/components/ErrorMessage/ErrorMessage.js +120 -5643
  21. package/dist/cjs/components/ErrorMessage/ErrorMessage.js.map +4 -4
  22. package/dist/cjs/components/ErrorMessage/index.js +121 -5642
  23. package/dist/cjs/components/ErrorMessage/index.js.map +4 -4
  24. package/dist/cjs/components/ExpandableText/ExpandableText.js +511 -5604
  25. package/dist/cjs/components/ExpandableText/ExpandableText.js.map +4 -4
  26. package/dist/cjs/components/ExpandableText/index.js +512 -5604
  27. package/dist/cjs/components/ExpandableText/index.js.map +4 -4
  28. package/dist/cjs/components/MaskedField/MaskedField.js +394 -5511
  29. package/dist/cjs/components/MaskedField/MaskedField.js.map +4 -4
  30. package/dist/cjs/components/MaskedField/index.js +293 -5118
  31. package/dist/cjs/components/MaskedField/index.js.map +4 -4
  32. package/dist/cjs/components/NumberField/NumberField.js +357 -5523
  33. package/dist/cjs/components/NumberField/NumberField.js.map +4 -4
  34. package/dist/cjs/components/NumberField/index.js +358 -5523
  35. package/dist/cjs/components/NumberField/index.js.map +4 -4
  36. package/dist/cjs/components/PasswordField/PasswordField.js +330 -5511
  37. package/dist/cjs/components/PasswordField/PasswordField.js.map +4 -4
  38. package/dist/cjs/components/PasswordField/ShowHideButton.js +32 -5655
  39. package/dist/cjs/components/PasswordField/ShowHideButton.js.map +4 -4
  40. package/dist/cjs/components/PasswordField/index.js +332 -5512
  41. package/dist/cjs/components/PasswordField/index.js.map +4 -4
  42. package/dist/cjs/components/Radio/Radio.js +242 -5632
  43. package/dist/cjs/components/Radio/Radio.js.map +4 -4
  44. package/dist/cjs/components/Radio/RadioGroup.js +274 -5619
  45. package/dist/cjs/components/Radio/RadioGroup.js.map +4 -4
  46. package/dist/cjs/components/Radio/index.js +404 -5628
  47. package/dist/cjs/components/Radio/index.js.map +4 -4
  48. package/dist/cjs/components/Select/Select.js +233 -5588
  49. package/dist/cjs/components/Select/Select.js.map +4 -4
  50. package/dist/cjs/components/Select/index.js +234 -5588
  51. package/dist/cjs/components/Select/index.js.map +4 -4
  52. package/dist/cjs/components/TextArea/TextArea.js +229 -5531
  53. package/dist/cjs/components/TextArea/TextArea.js.map +4 -4
  54. package/dist/cjs/components/TextArea/index.js +230 -5531
  55. package/dist/cjs/components/TextArea/index.js.map +4 -4
  56. package/dist/cjs/components/TextField/TextField.js +265 -5522
  57. package/dist/cjs/components/TextField/TextField.js.map +4 -4
  58. package/dist/cjs/components/TextField/index.js +266 -5522
  59. package/dist/cjs/components/TextField/index.js.map +4 -4
  60. package/dist/cjs/components/index.js +4273 -5291
  61. package/dist/cjs/components/index.js.map +4 -4
  62. package/dist/cjs/index.js +4304 -5334
  63. package/dist/cjs/index.js.map +4 -4
  64. package/dist/cjs/meta.json +5734 -51529
  65. package/dist/esm/chunk-3O5DIIGS.js +1 -0
  66. package/dist/esm/chunk-3O5DIIGS.js.map +7 -0
  67. package/dist/esm/chunk-3PRSHEVX.js +1 -0
  68. package/dist/esm/chunk-3PRSHEVX.js.map +7 -0
  69. package/dist/esm/chunk-4NBLO5WK.js +54 -0
  70. package/dist/esm/chunk-4NBLO5WK.js.map +7 -0
  71. package/dist/esm/chunk-4WVJNNBK.js +157 -0
  72. package/dist/esm/chunk-4WVJNNBK.js.map +7 -0
  73. package/dist/esm/chunk-5L4G4VLM.js +1 -0
  74. package/dist/esm/chunk-5L4G4VLM.js.map +7 -0
  75. package/dist/esm/chunk-5OFXPT4J.js +135 -0
  76. package/dist/esm/chunk-5OFXPT4J.js.map +7 -0
  77. package/dist/esm/chunk-6O77SOOB.js +1 -0
  78. package/dist/esm/chunk-6O77SOOB.js.map +7 -0
  79. package/dist/esm/chunk-AFU7BFCD.js +151 -0
  80. package/dist/esm/chunk-AFU7BFCD.js.map +7 -0
  81. package/dist/esm/chunk-BGR2OTTR.js +1 -0
  82. package/dist/esm/chunk-BGR2OTTR.js.map +7 -0
  83. package/dist/esm/chunk-BIGO5EVC.js +1 -0
  84. package/dist/esm/chunk-BIGO5EVC.js.map +7 -0
  85. package/dist/esm/chunk-CUOVI2HT.js +1 -0
  86. package/dist/esm/chunk-CUOVI2HT.js.map +7 -0
  87. package/dist/esm/chunk-F4RQKLF7.js +1 -0
  88. package/dist/esm/chunk-F4RQKLF7.js.map +7 -0
  89. package/dist/esm/chunk-FKTDL7KO.js +355 -0
  90. package/dist/esm/chunk-FKTDL7KO.js.map +7 -0
  91. package/dist/esm/chunk-KQZ3MNK5.js +100 -0
  92. package/dist/esm/chunk-KQZ3MNK5.js.map +7 -0
  93. package/dist/esm/chunk-M2NDSQR5.js +106 -0
  94. package/dist/esm/chunk-M2NDSQR5.js.map +7 -0
  95. package/dist/esm/chunk-N4WQ6522.js +125 -0
  96. package/dist/esm/chunk-N4WQ6522.js.map +7 -0
  97. package/dist/esm/{chunk-CNOF66SV.js → chunk-NGNVAFBJ.js} +4 -4
  98. package/dist/esm/chunk-NOQ27VLY.js +1 -0
  99. package/dist/esm/chunk-NOQ27VLY.js.map +7 -0
  100. package/dist/esm/chunk-ONDOONBM.js +101 -0
  101. package/dist/esm/chunk-ONDOONBM.js.map +7 -0
  102. package/dist/esm/chunk-P34DI6BE.js +1 -0
  103. package/dist/esm/chunk-P34DI6BE.js.map +7 -0
  104. package/dist/esm/chunk-P5VEI574.js +97 -0
  105. package/dist/esm/chunk-P5VEI574.js.map +7 -0
  106. package/dist/esm/chunk-QPIA6BGW.js +64 -0
  107. package/dist/esm/chunk-QPIA6BGW.js.map +7 -0
  108. package/dist/esm/chunk-SZEFLEDA.js +1 -0
  109. package/dist/esm/chunk-SZEFLEDA.js.map +7 -0
  110. package/dist/esm/chunk-TXB4BOHB.js +1 -0
  111. package/dist/esm/chunk-TXB4BOHB.js.map +7 -0
  112. package/dist/esm/chunk-UIIXVY6K.js +123 -0
  113. package/dist/esm/chunk-UIIXVY6K.js.map +7 -0
  114. package/dist/esm/chunk-UQVAEWY2.js +44 -0
  115. package/dist/esm/chunk-UQVAEWY2.js.map +7 -0
  116. package/dist/esm/chunk-WC3D5GNN.js +29 -0
  117. package/dist/esm/chunk-WC3D5GNN.js.map +7 -0
  118. package/dist/esm/chunk-WNRO77YH.js +1 -0
  119. package/dist/esm/chunk-WNRO77YH.js.map +7 -0
  120. package/dist/esm/chunk-X6EPYQKX.js +96 -0
  121. package/dist/esm/chunk-X6EPYQKX.js.map +7 -0
  122. package/dist/esm/chunk-ZN5TRIVZ.js +41 -0
  123. package/dist/esm/chunk-ZN5TRIVZ.js.map +7 -0
  124. package/dist/esm/components/AddressLookup/AddressLookup.js +9 -106
  125. package/dist/esm/components/AddressLookup/index.js +10 -103
  126. package/dist/esm/components/Checkbox/Checkbox.js +3 -116
  127. package/dist/esm/components/Checkbox/CheckboxGroup.js +4 -114
  128. package/dist/esm/components/Checkbox/index.js +7 -114
  129. package/dist/esm/components/Combobox/Combobox.js +6 -107
  130. package/dist/esm/components/Combobox/index.js +8 -107
  131. package/dist/esm/components/DateField/DateField.js +6 -113
  132. package/dist/esm/components/DateField/index.js +7 -113
  133. package/dist/esm/components/ErrorMessage/ErrorMessage.js +1 -146
  134. package/dist/esm/components/ErrorMessage/index.js +2 -146
  135. package/dist/esm/components/ExpandableText/ExpandableText.js +1 -108
  136. package/dist/esm/components/ExpandableText/index.js +2 -108
  137. package/dist/esm/components/MaskedField/MaskedField.js +5 -114
  138. package/dist/esm/components/MaskedField/MaskedField.js.map +1 -1
  139. package/dist/esm/components/MaskedField/index.js +6 -114
  140. package/dist/esm/components/NumberField/NumberField.js +6 -114
  141. package/dist/esm/components/NumberField/index.js +7 -114
  142. package/dist/esm/components/PasswordField/PasswordField.js +7 -114
  143. package/dist/esm/components/PasswordField/ShowHideButton.js +1 -149
  144. package/dist/esm/components/PasswordField/index.js +8 -114
  145. package/dist/esm/components/Radio/Radio.js +3 -144
  146. package/dist/esm/components/Radio/RadioGroup.js +3 -114
  147. package/dist/esm/components/Radio/index.js +7 -115
  148. package/dist/esm/components/Select/Select.js +3 -114
  149. package/dist/esm/components/Select/index.js +4 -114
  150. package/dist/esm/components/Slider/Slider.js +2 -2
  151. package/dist/esm/components/Slider/index.js +2 -2
  152. package/dist/esm/components/TextArea/TextArea.js +3 -112
  153. package/dist/esm/components/TextArea/index.js +4 -112
  154. package/dist/esm/components/TextField/TextField.js +4 -114
  155. package/dist/esm/components/TextField/index.js +5 -114
  156. package/dist/esm/components/index.js +81 -44
  157. package/dist/esm/index.js +81 -39
  158. package/dist/esm/meta.json +6950 -19169
  159. package/dist/tsconfig.build.tsbuildinfo +1 -1
  160. package/package.json +2 -2
  161. package/src/components/ErrorMessage/ErrorMessage.tsx +1 -1
  162. package/src/components/ExpandableText/ExpandableText.tsx +3 -1
  163. package/src/components/PasswordField/ShowHideButton.tsx +1 -1
  164. package/dist/esm/chunk-W2RQH4WS.js +0 -1606
  165. package/dist/esm/chunk-W2RQH4WS.js.map +0 -7
  166. /package/dist/esm/{chunk-CNOF66SV.js.map → chunk-NGNVAFBJ.js.map} +0 -0
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-CUOVI2HT.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-F4RQKLF7.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,355 @@
1
+ import {
2
+ Listbox
3
+ } from "./chunk-PQSPISME.js";
4
+ import {
5
+ useComboboxHighlight
6
+ } from "./chunk-XZUQV54A.js";
7
+ import {
8
+ useComboboxOptions
9
+ } from "./chunk-GU5OMKTM.js";
10
+ import {
11
+ getOptionLabel,
12
+ getOptionValue,
13
+ isOptionGroup
14
+ } from "./chunk-2JLZNSLY.js";
15
+ import {
16
+ TextField
17
+ } from "./chunk-UIIXVY6K.js";
18
+ import {
19
+ VisuallyHidden
20
+ } from "./chunk-PRZRE6A5.js";
21
+ import {
22
+ useBreakpoint
23
+ } from "./chunk-7FQ7SXK4.js";
24
+
25
+ // src/components/Combobox/Combobox.tsx
26
+ import { useOnUnmount } from "@simplybusiness/mobius-hooks";
27
+ import classNames from "classnames/dedupe";
28
+ import { useEffect, useId, useRef, useState } from "react";
29
+ import "@simplybusiness/mobius/src/components/Combobox/Combobox.css";
30
+ import { jsx, jsxs } from "react/jsx-runtime";
31
+ var ComboboxInner = ({
32
+ ref,
33
+ ...props
34
+ }) => {
35
+ const {
36
+ id,
37
+ defaultValue,
38
+ value,
39
+ options,
40
+ asyncOptions,
41
+ delay,
42
+ minSearchLength,
43
+ onSelected,
44
+ className,
45
+ placeholder,
46
+ icon,
47
+ onBlur,
48
+ onFocus,
49
+ onChange,
50
+ // onSearched, // unused prop, consider removing
51
+ optionComponent,
52
+ optionTestIdPrefix,
53
+ errorMessage,
54
+ ...otherProps
55
+ } = props;
56
+ const skipNextDebounceRef = useRef(false);
57
+ const fallbackRef = useRef(null);
58
+ const [inputValue, setInputValue] = useState(defaultValue || "");
59
+ const [isOpen, setIsOpen] = useState(false);
60
+ const [isChanging, setIsChanging] = useState(false);
61
+ const { filteredOptions, updateFilteredOptions, isLoading, error } = useComboboxOptions({
62
+ options,
63
+ asyncOptions,
64
+ inputValue,
65
+ delay,
66
+ minSearchLength,
67
+ skipNextDebounceRef
68
+ });
69
+ const [validationError, setValidationError] = useState(
70
+ error?.message || errorMessage
71
+ );
72
+ const {
73
+ highlightedIndex,
74
+ highlightedGroupIndex,
75
+ highlightNextOption,
76
+ highlightPreviousOption,
77
+ highlightFirstOption,
78
+ highlightLastOption,
79
+ clearHighlight
80
+ } = useComboboxHighlight(filteredOptions);
81
+ const inputRef = ref || fallbackRef;
82
+ const listboxId = useId();
83
+ const statusId = useId();
84
+ const blurTimeoutRef = useRef(null);
85
+ const userInteractedRef = useRef(false);
86
+ const justSelectedRef = useRef(false);
87
+ const { down } = useBreakpoint();
88
+ const isMobile = down("md");
89
+ useEffect(() => {
90
+ setValidationError(error?.message || errorMessage);
91
+ }, [error, errorMessage]);
92
+ const getEmptyValue = () => {
93
+ const firstOption = filteredOptions ? isOptionGroup(filteredOptions) ? filteredOptions[0]?.options[0] : filteredOptions[0] : options ? isOptionGroup(options) ? options[0]?.options[0] : options[0] : void 0;
94
+ if (typeof firstOption === "string") {
95
+ return "";
96
+ }
97
+ return { label: "", value: "" };
98
+ };
99
+ const handleFocus = (e) => {
100
+ onFocus?.(e);
101
+ if (!filteredOptions || filteredOptions.length === 0) return;
102
+ if (blurTimeoutRef.current) {
103
+ clearTimeout(blurTimeoutRef.current);
104
+ blurTimeoutRef.current = null;
105
+ }
106
+ const isNaturalFocus = userInteractedRef.current || e.relatedTarget !== null;
107
+ if (userInteractedRef.current) {
108
+ userInteractedRef.current = false;
109
+ }
110
+ if (justSelectedRef.current && !isNaturalFocus) {
111
+ return;
112
+ }
113
+ if (isNaturalFocus) {
114
+ setIsOpen(true);
115
+ justSelectedRef.current = false;
116
+ }
117
+ };
118
+ useEffect(() => {
119
+ if (!inputRef || typeof inputRef === "function") return;
120
+ const inputElement = inputRef.current;
121
+ if (!inputElement) return;
122
+ const handleMouseDown = () => {
123
+ userInteractedRef.current = true;
124
+ };
125
+ inputElement.addEventListener("mousedown", handleMouseDown);
126
+ return () => {
127
+ inputElement.removeEventListener("mousedown", handleMouseDown);
128
+ };
129
+ }, [inputRef]);
130
+ useOnUnmount(() => {
131
+ if (blurTimeoutRef.current) {
132
+ clearTimeout(blurTimeoutRef.current);
133
+ }
134
+ });
135
+ const handleInputChange = (e) => {
136
+ const newValue = e.target.value;
137
+ setInputValue(newValue);
138
+ setValidationError(void 0);
139
+ justSelectedRef.current = false;
140
+ setIsChanging(true);
141
+ if (!asyncOptions) {
142
+ setIsOpen(true);
143
+ }
144
+ clearHighlight();
145
+ onChange?.(e);
146
+ };
147
+ const handleOptionSelect = (option) => {
148
+ const val = getOptionValue(option);
149
+ if (!val && val !== "") return;
150
+ if (typeof option === "object" && "callback" in option && option.callback && typeof option.callback === "function") {
151
+ justSelectedRef.current = true;
152
+ setTimeout(() => {
153
+ if (inputRef && typeof inputRef !== "function" && inputRef.current) {
154
+ inputRef.current.focus();
155
+ }
156
+ }, 0);
157
+ const callbackPromise = option.callback();
158
+ updateFilteredOptions(callbackPromise);
159
+ callbackPromise.then(() => {
160
+ setIsOpen(true);
161
+ setIsChanging(true);
162
+ }).catch(() => {
163
+ });
164
+ return;
165
+ }
166
+ skipNextDebounceRef.current = true;
167
+ justSelectedRef.current = true;
168
+ setIsChanging(false);
169
+ setValidationError(void 0);
170
+ setIsOpen(false);
171
+ setInputValue(val);
172
+ onSelected?.(option);
173
+ };
174
+ const getFirstOption = () => {
175
+ if (!filteredOptions) return void 0;
176
+ if (isOptionGroup(filteredOptions)) {
177
+ return filteredOptions[0]?.options[0];
178
+ }
179
+ return filteredOptions[0];
180
+ };
181
+ const getHighlightedOption = () => {
182
+ if (!filteredOptions) return void 0;
183
+ if (highlightedIndex === -1) return void 0;
184
+ if (isOptionGroup(filteredOptions)) {
185
+ const group = filteredOptions[highlightedGroupIndex];
186
+ return group?.options[highlightedIndex];
187
+ }
188
+ return filteredOptions[highlightedIndex];
189
+ };
190
+ const getHighlightedOptionId = () => {
191
+ const option = getHighlightedOption();
192
+ if (!option) return void 0;
193
+ if (isOptionGroup(filteredOptions)) {
194
+ return `${listboxId}-option-${highlightedGroupIndex}-${highlightedIndex}`;
195
+ }
196
+ return `${listboxId}-option-${highlightedIndex}`;
197
+ };
198
+ const handleBlur = (e) => {
199
+ if (!justSelectedRef.current) {
200
+ const typedText = inputValue.trim();
201
+ const typedTextLower = typedText.toLowerCase();
202
+ const highlightedOption = getHighlightedOption();
203
+ const label = getOptionLabel(highlightedOption);
204
+ if (typedTextLower === label?.toLowerCase()) {
205
+ setTimeout(() => {
206
+ handleOptionSelect(highlightedOption);
207
+ }, 0);
208
+ } else if (typedText === "") {
209
+ setTimeout(() => {
210
+ handleOptionSelect(getEmptyValue());
211
+ }, 0);
212
+ } else {
213
+ setValidationError(
214
+ errorMessage || "Please select an option from the list"
215
+ );
216
+ setTimeout(() => {
217
+ setInputValue("");
218
+ }, 0);
219
+ }
220
+ }
221
+ blurTimeoutRef.current = setTimeout(() => {
222
+ onBlur?.(e);
223
+ setIsOpen(false);
224
+ setIsChanging(false);
225
+ }, 150);
226
+ };
227
+ const handleKeyDown = (e) => {
228
+ switch (e.key) {
229
+ case "ArrowDown":
230
+ e.preventDefault();
231
+ justSelectedRef.current = false;
232
+ setIsOpen(true);
233
+ highlightNextOption();
234
+ break;
235
+ case "ArrowUp":
236
+ e.preventDefault();
237
+ justSelectedRef.current = false;
238
+ setIsOpen(true);
239
+ highlightPreviousOption();
240
+ break;
241
+ case "Home":
242
+ e.preventDefault();
243
+ justSelectedRef.current = false;
244
+ setIsOpen(true);
245
+ highlightFirstOption();
246
+ break;
247
+ case "End":
248
+ e.preventDefault();
249
+ justSelectedRef.current = false;
250
+ setIsOpen(true);
251
+ highlightLastOption();
252
+ break;
253
+ case "Enter":
254
+ e.preventDefault();
255
+ if (isOpen) {
256
+ const selectedOption = getHighlightedOption() || getFirstOption();
257
+ if (selectedOption) {
258
+ handleOptionSelect(selectedOption);
259
+ }
260
+ }
261
+ break;
262
+ case "Escape":
263
+ e.preventDefault();
264
+ setInputValue("");
265
+ setIsOpen(false);
266
+ clearHighlight();
267
+ break;
268
+ default:
269
+ }
270
+ };
271
+ useEffect(() => {
272
+ if (value) {
273
+ setInputValue(value);
274
+ }
275
+ }, [value]);
276
+ useEffect(() => {
277
+ if (asyncOptions && isChanging) {
278
+ setIsOpen(!!filteredOptions && filteredOptions.length > 0);
279
+ }
280
+ }, [filteredOptions, asyncOptions, isChanging]);
281
+ const classes = classNames(
282
+ "mobius mobius-combobox",
283
+ {
284
+ "mobius-combobox--is-expanded": isOpen,
285
+ "mobius-combobox--is-loading": isLoading,
286
+ "mobius-combobox--is-mobile": isMobile
287
+ },
288
+ className
289
+ );
290
+ const getStatusMessage = () => {
291
+ if (isLoading) return "Loading options";
292
+ if (!filteredOptions || filteredOptions.length === 0) {
293
+ return isChanging ? "No options found" : "";
294
+ }
295
+ const count = isOptionGroup(filteredOptions) ? filteredOptions.reduce((sum, group) => sum + group.options.length, 0) : filteredOptions.length;
296
+ return isOpen && isChanging ? `${count} option${count === 1 ? "" : "s"} available` : "";
297
+ };
298
+ return /* @__PURE__ */ jsxs("div", { id, "data-testid": "mobius-combobox__wrapper", className: classes, children: [
299
+ /* @__PURE__ */ jsx(
300
+ VisuallyHidden,
301
+ {
302
+ role: "status",
303
+ "aria-live": "polite",
304
+ id: statusId,
305
+ elementType: "div",
306
+ className: "mobius-combobox__status",
307
+ children: getStatusMessage()
308
+ }
309
+ ),
310
+ /* @__PURE__ */ jsx(
311
+ TextField,
312
+ {
313
+ ...otherProps,
314
+ className: "mobius-combobox__input",
315
+ role: "combobox",
316
+ value: inputValue,
317
+ placeholder,
318
+ onFocus: handleFocus,
319
+ onBlur: handleBlur,
320
+ onKeyDown: handleKeyDown,
321
+ onChange: handleInputChange,
322
+ autoComplete: "off",
323
+ "aria-describedby": isLoading ? statusId : void 0,
324
+ "aria-autocomplete": "list",
325
+ "aria-haspopup": "listbox",
326
+ "aria-controls": isOpen ? listboxId : void 0,
327
+ "aria-expanded": isOpen,
328
+ "aria-activedescendant": highlightedIndex === -1 ? void 0 : getHighlightedOptionId(),
329
+ prefixInside: icon,
330
+ ref: inputRef,
331
+ errorMessage: errorMessage || validationError || error?.message
332
+ }
333
+ ),
334
+ /* @__PURE__ */ jsx(
335
+ Listbox,
336
+ {
337
+ id: listboxId,
338
+ isOpen,
339
+ isLoading,
340
+ options: filteredOptions,
341
+ highlightedIndex,
342
+ highlightedGroupIndex,
343
+ onOptionSelect: handleOptionSelect,
344
+ optionComponent,
345
+ optionTestIdPrefix
346
+ }
347
+ )
348
+ ] });
349
+ };
350
+ var Combobox = ComboboxInner;
351
+
352
+ export {
353
+ Combobox
354
+ };
355
+ //# sourceMappingURL=chunk-FKTDL7KO.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/Combobox/Combobox.tsx"],
4
+ "sourcesContent": ["import { useOnUnmount } from \"@simplybusiness/mobius-hooks\";\nimport classNames from \"classnames/dedupe\";\nimport type React from \"react\";\nimport type { FocusEvent } from \"react\";\nimport { useEffect, useId, useRef, useState } from \"react\";\nimport { useBreakpoint } from \"../../hooks\";\nimport { TextField } from \"../TextField\";\nimport { VisuallyHidden } from \"../VisuallyHidden\";\nimport { Listbox } from \"./Listbox\"; // Import Listbox component\nimport type { ComboboxOption, ComboboxProps, ComboboxRef } from \"./types\";\nimport { useComboboxHighlight } from \"./useComboboxHighlight\";\nimport { useComboboxOptions } from \"./useComboboxOptions\";\nimport { getOptionLabel, getOptionValue, isOptionGroup } from \"./utils\";\nimport \"./Combobox.css\";\n\nconst ComboboxInner = <T extends ComboboxOption>({\n ref,\n ...props\n}: ComboboxProps<T>) => {\n const {\n id,\n defaultValue,\n value,\n options,\n asyncOptions,\n delay,\n minSearchLength,\n onSelected,\n className,\n placeholder,\n icon,\n onBlur,\n onFocus,\n onChange,\n // onSearched, // unused prop, consider removing\n optionComponent,\n optionTestIdPrefix,\n errorMessage,\n ...otherProps\n } = props;\n // Avoid re-fetching after selecting an option\n const skipNextDebounceRef = useRef(false);\n const fallbackRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState(defaultValue || \"\");\n const [isOpen, setIsOpen] = useState(false);\n const [isChanging, setIsChanging] = useState(false);\n const { filteredOptions, updateFilteredOptions, isLoading, error } =\n useComboboxOptions({\n options,\n asyncOptions,\n inputValue,\n delay,\n minSearchLength,\n skipNextDebounceRef,\n });\n const [validationError, setValidationError] = useState(\n error?.message || errorMessage,\n );\n const {\n highlightedIndex,\n highlightedGroupIndex,\n highlightNextOption,\n highlightPreviousOption,\n highlightFirstOption,\n highlightLastOption,\n clearHighlight,\n } = useComboboxHighlight(filteredOptions);\n\n const inputRef = ref || fallbackRef;\n const listboxId = useId();\n const statusId = useId();\n const blurTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const userInteractedRef = useRef(false);\n const justSelectedRef = useRef(false);\n const { down } = useBreakpoint();\n const isMobile = down(\"md\");\n\n useEffect(() => {\n setValidationError(error?.message || errorMessage);\n }, [error, errorMessage]);\n\n // Helper to create properly-typed empty value based on option type\n const getEmptyValue = (): T => {\n // Check first available option to determine if we're using string or object options\n const firstOption = filteredOptions\n ? isOptionGroup(filteredOptions)\n ? filteredOptions[0]?.options[0]\n : filteredOptions[0]\n : options\n ? isOptionGroup(options)\n ? options[0]?.options[0]\n : options[0]\n : undefined;\n\n // If options are strings, return empty string\n if (typeof firstOption === \"string\") {\n return \"\" as T;\n }\n\n // If options are objects, return empty object with same shape\n return { label: \"\", value: \"\" } as T;\n };\n\n const handleFocus = (e: FocusEvent) => {\n onFocus?.(e);\n if (!filteredOptions || filteredOptions.length === 0) return;\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n blurTimeoutRef.current = null;\n }\n\n // Check if this is natural focus (user click/Tab) or programmatic focus\n const isNaturalFocus =\n userInteractedRef.current || e.relatedTarget !== null;\n if (userInteractedRef.current) {\n userInteractedRef.current = false;\n }\n\n // Block opening only if programmatic focus right after selection\n if (justSelectedRef.current && !isNaturalFocus) {\n return;\n }\n\n // Open dropdown for natural focus\n if (isNaturalFocus) {\n setIsOpen(true);\n justSelectedRef.current = false;\n }\n };\n\n useEffect(() => {\n if (!inputRef || typeof inputRef === \"function\") return;\n const inputElement = inputRef.current;\n if (!inputElement) return;\n\n const handleMouseDown = () => {\n // Track that user clicked/interacted with input\n userInteractedRef.current = true;\n };\n\n inputElement.addEventListener(\"mousedown\", handleMouseDown);\n return () => {\n inputElement.removeEventListener(\"mousedown\", handleMouseDown);\n };\n }, [inputRef]);\n\n useOnUnmount(() => {\n if (blurTimeoutRef.current) {\n clearTimeout(blurTimeoutRef.current);\n }\n });\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setValidationError(undefined);\n justSelectedRef.current = false;\n setIsChanging(true);\n // Only open immediately for sync options; async options controlled by useEffect\n if (!asyncOptions) {\n setIsOpen(true);\n }\n clearHighlight();\n onChange?.(e);\n };\n\n const handleOptionSelect = (option: T) => {\n const val = getOptionValue(option);\n\n // Allow empty values to pass through\n if (!val && val !== \"\") return;\n\n if (\n typeof option === \"object\" &&\n \"callback\" in option &&\n option.callback &&\n typeof option.callback === \"function\"\n ) {\n justSelectedRef.current = true;\n setTimeout(() => {\n if (inputRef && typeof inputRef !== \"function\" && inputRef.current) {\n inputRef.current.focus();\n }\n }, 0);\n const callbackPromise = option.callback();\n updateFilteredOptions(callbackPromise);\n callbackPromise\n .then(() => {\n setIsOpen(true);\n setIsChanging(true);\n })\n .catch(() => {\n // error handled inside updateFilteredOptions via setError\n });\n return;\n }\n\n // Prevent re-fetching options after selecting an option\n skipNextDebounceRef.current = true;\n justSelectedRef.current = true;\n\n setIsChanging(false);\n setValidationError(undefined);\n setIsOpen(false);\n setInputValue(val);\n onSelected?.(option);\n };\n\n const getFirstOption = () => {\n if (!filteredOptions) return undefined;\n if (isOptionGroup(filteredOptions)) {\n return filteredOptions[0]?.options[0];\n }\n\n return filteredOptions[0];\n };\n\n const getHighlightedOption = () => {\n if (!filteredOptions) return undefined;\n if (highlightedIndex === -1) return undefined;\n\n if (isOptionGroup(filteredOptions)) {\n const group = filteredOptions[highlightedGroupIndex];\n return group?.options[highlightedIndex];\n }\n\n return filteredOptions[highlightedIndex];\n };\n\n const getHighlightedOptionId = () => {\n const option = getHighlightedOption();\n if (!option) return undefined;\n\n if (isOptionGroup(filteredOptions)) {\n return `${listboxId}-option-${highlightedGroupIndex}-${highlightedIndex}`;\n }\n\n return `${listboxId}-option-${highlightedIndex}`;\n };\n\n const handleBlur = (e: FocusEvent<Element, Element>) => {\n // Force selection if user has matched an entry by typing (not already selected)\n // Defer this to allow natural focus flow to complete first\n if (!justSelectedRef.current) {\n const typedText = inputValue.trim();\n const typedTextLower = typedText.toLowerCase();\n const highlightedOption = getHighlightedOption();\n const label = getOptionLabel(highlightedOption);\n\n if (typedTextLower === label?.toLowerCase()) {\n // Exact match with an option\n setTimeout(() => {\n handleOptionSelect(highlightedOption as T);\n }, 0);\n } else if (typedText === \"\") {\n // Allow empty values\n setTimeout(() => {\n handleOptionSelect(getEmptyValue());\n }, 0);\n } else {\n // Invalid value (not in options and not empty)\n setValidationError(\n errorMessage || \"Please select an option from the list\",\n );\n setTimeout(() => {\n setInputValue(\"\");\n }, 0);\n }\n }\n\n blurTimeoutRef.current = setTimeout(() => {\n onBlur?.(e);\n setIsOpen(false);\n setIsChanging(false);\n }, 150);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n justSelectedRef.current = false;\n setIsOpen(true);\n highlightNextOption();\n break;\n case \"ArrowUp\":\n e.preventDefault();\n justSelectedRef.current = false;\n setIsOpen(true);\n highlightPreviousOption();\n break;\n case \"Home\":\n e.preventDefault();\n justSelectedRef.current = false;\n setIsOpen(true);\n highlightFirstOption();\n break;\n case \"End\":\n e.preventDefault();\n justSelectedRef.current = false;\n setIsOpen(true);\n highlightLastOption();\n break;\n case \"Enter\":\n e.preventDefault();\n if (isOpen) {\n const selectedOption = getHighlightedOption() || getFirstOption();\n if (selectedOption) {\n handleOptionSelect(selectedOption);\n }\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setInputValue(\"\");\n setIsOpen(false);\n clearHighlight();\n break;\n default:\n // Do nothing\n }\n };\n\n useEffect(() => {\n if (value) {\n setInputValue(value);\n }\n }, [value]);\n\n // Open and close the combobox based on async filtered options\n useEffect(() => {\n if (asyncOptions && isChanging) {\n setIsOpen(!!filteredOptions && filteredOptions.length > 0);\n }\n }, [filteredOptions, asyncOptions, isChanging]);\n\n const classes = classNames(\n \"mobius mobius-combobox\",\n {\n \"mobius-combobox--is-expanded\": isOpen,\n \"mobius-combobox--is-loading\": isLoading,\n \"mobius-combobox--is-mobile\": isMobile,\n },\n className,\n );\n\n const getStatusMessage = () => {\n if (isLoading) return \"Loading options\";\n if (!filteredOptions || filteredOptions.length === 0) {\n return isChanging ? \"No options found\" : \"\";\n }\n const count = isOptionGroup(filteredOptions)\n ? filteredOptions.reduce((sum, group) => sum + group.options.length, 0)\n : filteredOptions.length;\n return isOpen && isChanging\n ? `${count} option${count === 1 ? \"\" : \"s\"} available`\n : \"\";\n };\n\n return (\n <div id={id} data-testid=\"mobius-combobox__wrapper\" className={classes}>\n <VisuallyHidden\n role=\"status\"\n aria-live=\"polite\"\n id={statusId}\n elementType=\"div\"\n className=\"mobius-combobox__status\"\n >\n {getStatusMessage()}\n </VisuallyHidden>\n <TextField\n {...otherProps}\n className=\"mobius-combobox__input\"\n role=\"combobox\"\n value={inputValue}\n placeholder={placeholder}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n onChange={handleInputChange}\n autoComplete=\"off\"\n aria-describedby={isLoading ? statusId : undefined}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls={isOpen ? listboxId : undefined}\n aria-expanded={isOpen}\n aria-activedescendant={\n highlightedIndex === -1 ? undefined : getHighlightedOptionId()\n }\n prefixInside={icon}\n ref={inputRef}\n errorMessage={errorMessage || validationError || error?.message}\n />\n <Listbox\n id={listboxId}\n isOpen={isOpen}\n isLoading={isLoading}\n options={filteredOptions}\n highlightedIndex={highlightedIndex}\n highlightedGroupIndex={highlightedGroupIndex}\n onOptionSelect={handleOptionSelect}\n optionComponent={optionComponent}\n optionTestIdPrefix={optionTestIdPrefix}\n />\n </div>\n );\n};\n\nexport const Combobox = ComboboxInner as <T extends ComboboxOption>(\n props: ComboboxProps<T> & { ref?: ComboboxRef },\n) => React.JSX.Element;\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,100 @@
1
+ import {
2
+ convertToDateFormat,
3
+ isValidDate
4
+ } from "./chunk-CI5GCPUG.js";
5
+ import {
6
+ TextField
7
+ } from "./chunk-UIIXVY6K.js";
8
+ import {
9
+ mergeRefs
10
+ } from "./chunk-QGGILW3D.js";
11
+
12
+ // src/components/DateField/DateField.tsx
13
+ import classNames from "classnames/dedupe";
14
+ import { useEffect, useRef, useState } from "react";
15
+ import { jsx } from "react/jsx-runtime";
16
+ var MIN_MAX_ERROR = '"min" value should not be greater than "max" value.';
17
+ var DateField = ({ ref, ...props }) => {
18
+ const {
19
+ min,
20
+ max,
21
+ format,
22
+ className,
23
+ errorMessage,
24
+ defaultValue,
25
+ value,
26
+ ...otherProps
27
+ } = props;
28
+ const [error, setError] = useState(errorMessage);
29
+ const [isInvalid, setIsInvalid] = useState(void 0);
30
+ const localRef = useRef(null);
31
+ const classes = classNames("mobius-date-field", className);
32
+ const formattedMin = min ? convertToDateFormat(min, format) : void 0;
33
+ const formattedMax = max ? convertToDateFormat(max, format) : void 0;
34
+ const formattedDefaultValue = defaultValue ? convertToDateFormat(defaultValue, format) : void 0;
35
+ const formattedValue = value ? convertToDateFormat(value, format) : void 0;
36
+ const setInvalidState = (error2) => {
37
+ setError(error2);
38
+ setIsInvalid(true);
39
+ };
40
+ const setValidState = () => {
41
+ setError(props.errorMessage);
42
+ setIsInvalid(false);
43
+ };
44
+ useEffect(() => {
45
+ if (!isValidDate(min, format)) {
46
+ setInvalidState(`Invalid min date: ${min}`);
47
+ return;
48
+ }
49
+ if (!isValidDate(max, format)) {
50
+ setInvalidState(`Invalid max date: ${max}`);
51
+ return;
52
+ }
53
+ if (min && max) {
54
+ const minDate = new Date(min);
55
+ const maxDate = new Date(max);
56
+ if (minDate > maxDate) {
57
+ setInvalidState(MIN_MAX_ERROR);
58
+ } else {
59
+ setValidState();
60
+ }
61
+ } else {
62
+ setValidState();
63
+ }
64
+ }, [min, max, format]);
65
+ const validate = () => {
66
+ const isValidInput = localRef.current?.checkValidity();
67
+ if (!isValidInput) {
68
+ setInvalidState("Invalid date input");
69
+ } else {
70
+ setValidState();
71
+ }
72
+ };
73
+ const handleBlur = (event) => {
74
+ validate();
75
+ otherProps.onBlur?.(event);
76
+ };
77
+ return /* @__PURE__ */ jsx(
78
+ TextField,
79
+ {
80
+ ref: mergeRefs([localRef, ref]),
81
+ className: classes,
82
+ type: "date",
83
+ min: formattedMin,
84
+ max: formattedMax,
85
+ errorMessage: errorMessage ?? error,
86
+ isInvalid,
87
+ defaultValue: formattedDefaultValue,
88
+ value: formattedValue,
89
+ onBlur: handleBlur,
90
+ ...otherProps
91
+ }
92
+ );
93
+ };
94
+ DateField.displayName = "DateField";
95
+
96
+ export {
97
+ MIN_MAX_ERROR,
98
+ DateField
99
+ };
100
+ //# sourceMappingURL=chunk-KQZ3MNK5.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/DateField/DateField.tsx"],
4
+ "sourcesContent": ["\"use client\";\n\nimport classNames from \"classnames/dedupe\";\nimport type { FocusEvent, RefAttributes } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { mergeRefs } from \"../../utils/mergeRefs\";\nimport {\n TextField,\n type TextFieldElementType,\n type TextFieldProps,\n} from \"../TextField\";\nimport { convertToDateFormat, isValidDate } from \"./validation\";\n\nexport interface DateFieldProps\n extends Omit<TextFieldProps, \"type\">, RefAttributes<TextFieldElementType> {\n /** The earliest date allowed for the input. */\n min?: string;\n /** The latest date allowed for the input. */\n max?: string;\n /** Date format to use. */\n format?: string;\n}\n\nexport const MIN_MAX_ERROR =\n '\"min\" value should not be greater than \"max\" value.';\n\nexport const DateField = ({ ref, ...props }: DateFieldProps) => {\n const {\n min,\n max,\n format,\n className,\n errorMessage,\n defaultValue,\n value,\n ...otherProps\n } = props;\n const [error, setError] = useState<string | undefined>(errorMessage);\n const [isInvalid, setIsInvalid] = useState<boolean | undefined>(undefined);\n const localRef = useRef<TextFieldElementType>(null);\n const classes = classNames(\"mobius-date-field\", className);\n\n // If a custom format is provided, convert the min, max,\n // and defaultValue dates to that format\n const formattedMin = min ? convertToDateFormat(min, format) : undefined;\n const formattedMax = max ? convertToDateFormat(max, format) : undefined;\n const formattedDefaultValue = defaultValue\n ? convertToDateFormat(defaultValue, format)\n : undefined;\n const formattedValue = value ? convertToDateFormat(value, format) : undefined;\n\n const setInvalidState = (error?: string) => {\n setError(error);\n setIsInvalid(true);\n };\n\n const setValidState = () => {\n setError(props.errorMessage);\n setIsInvalid(false);\n };\n\n // Validate min and max values\n useEffect(() => {\n if (!isValidDate(min, format)) {\n setInvalidState(`Invalid min date: ${min}`);\n return;\n }\n if (!isValidDate(max, format)) {\n setInvalidState(`Invalid max date: ${max}`);\n return;\n }\n\n if (min && max) {\n const minDate = new Date(min);\n const maxDate = new Date(max);\n if (minDate > maxDate) {\n setInvalidState(MIN_MAX_ERROR);\n } else {\n setValidState();\n }\n } else {\n setValidState();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [min, max, format]);\n\n const validate = () => {\n // If 'min' or 'max' values are provided, checkValidity() will\n // validate the date and return a boolean\n const isValidInput = localRef.current?.checkValidity();\n\n if (!isValidInput) {\n setInvalidState(\"Invalid date input\");\n } else {\n setValidState();\n }\n };\n\n // User has interacted with the component and navigated away\n const handleBlur = (event: FocusEvent<Element>) => {\n validate();\n otherProps.onBlur?.(event);\n };\n\n return (\n <TextField\n ref={mergeRefs([localRef, ref])}\n className={classes}\n type=\"date\"\n min={formattedMin}\n max={formattedMax}\n errorMessage={errorMessage ?? error}\n isInvalid={isInvalid}\n defaultValue={formattedDefaultValue}\n value={formattedValue}\n onBlur={handleBlur}\n {...otherProps}\n />\n );\n};\n\nDateField.displayName = \"DateField\";\n"],
5
+ "mappings": ";;;;;;;;;;;;AAEA,OAAO,gBAAgB;AAEvB,SAAS,WAAW,QAAQ,gBAAgB;AAqGxC;AAlFG,IAAM,gBACX;AAEK,IAAM,YAAY,CAAC,EAAE,KAAK,GAAG,MAAM,MAAsB;AAC9D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AACJ,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA6B,YAAY;AACnE,QAAM,CAAC,WAAW,YAAY,IAAI,SAA8B,MAAS;AACzE,QAAM,WAAW,OAA6B,IAAI;AAClD,QAAM,UAAU,WAAW,qBAAqB,SAAS;AAIzD,QAAM,eAAe,MAAM,oBAAoB,KAAK,MAAM,IAAI;AAC9D,QAAM,eAAe,MAAM,oBAAoB,KAAK,MAAM,IAAI;AAC9D,QAAM,wBAAwB,eAC1B,oBAAoB,cAAc,MAAM,IACxC;AACJ,QAAM,iBAAiB,QAAQ,oBAAoB,OAAO,MAAM,IAAI;AAEpE,QAAM,kBAAkB,CAACA,WAAmB;AAC1C,aAASA,MAAK;AACd,iBAAa,IAAI;AAAA,EACnB;AAEA,QAAM,gBAAgB,MAAM;AAC1B,aAAS,MAAM,YAAY;AAC3B,iBAAa,KAAK;AAAA,EACpB;AAGA,YAAU,MAAM;AACd,QAAI,CAAC,YAAY,KAAK,MAAM,GAAG;AAC7B,sBAAgB,qBAAqB,GAAG,EAAE;AAC1C;AAAA,IACF;AACA,QAAI,CAAC,YAAY,KAAK,MAAM,GAAG;AAC7B,sBAAgB,qBAAqB,GAAG,EAAE;AAC1C;AAAA,IACF;AAEA,QAAI,OAAO,KAAK;AACd,YAAM,UAAU,IAAI,KAAK,GAAG;AAC5B,YAAM,UAAU,IAAI,KAAK,GAAG;AAC5B,UAAI,UAAU,SAAS;AACrB,wBAAgB,aAAa;AAAA,MAC/B,OAAO;AACL,sBAAc;AAAA,MAChB;AAAA,IACF,OAAO;AACL,oBAAc;AAAA,IAChB;AAAA,EAEF,GAAG,CAAC,KAAK,KAAK,MAAM,CAAC;AAErB,QAAM,WAAW,MAAM;AAGrB,UAAM,eAAe,SAAS,SAAS,cAAc;AAErD,QAAI,CAAC,cAAc;AACjB,sBAAgB,oBAAoB;AAAA,IACtC,OAAO;AACL,oBAAc;AAAA,IAChB;AAAA,EACF;AAGA,QAAM,aAAa,CAAC,UAA+B;AACjD,aAAS;AACT,eAAW,SAAS,KAAK;AAAA,EAC3B;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,UAAU,CAAC,UAAU,GAAG,CAAC;AAAA,MAC9B,WAAW;AAAA,MACX,MAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,cAAc,gBAAgB;AAAA,MAC9B;AAAA,MACA,cAAc;AAAA,MACd,OAAO;AAAA,MACP,QAAQ;AAAA,MACP,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,UAAU,cAAc;",
6
+ "names": ["error"]
7
+ }
@@ -0,0 +1,106 @@
1
+ import {
2
+ ErrorMessage
3
+ } from "./chunk-UQVAEWY2.js";
4
+ import {
5
+ Stack
6
+ } from "./chunk-XH3OJQMW.js";
7
+ import {
8
+ Label
9
+ } from "./chunk-ZN7OWLZY.js";
10
+ import {
11
+ Icon
12
+ } from "./chunk-TKIP5Q5H.js";
13
+ import {
14
+ useLabel
15
+ } from "./chunk-YLEFK7S2.js";
16
+ import {
17
+ useValidationClasses
18
+ } from "./chunk-DYOFXXZD.js";
19
+ import {
20
+ spaceDelimitedList
21
+ } from "./chunk-DTWRSP5P.js";
22
+
23
+ // src/components/Select/Select.tsx
24
+ import { chevronDown } from "@simplybusiness/icons";
25
+ import classNames from "classnames/dedupe";
26
+ import { useId } from "react";
27
+ import "@simplybusiness/mobius/src/components/Select/Select.css";
28
+ import { jsx, jsxs } from "react/jsx-runtime";
29
+ var Select = ({ ref, ...props }) => {
30
+ const {
31
+ label,
32
+ onChange,
33
+ isInvalid,
34
+ errorMessage,
35
+ isDisabled = false,
36
+ isRequired,
37
+ ...otherProps
38
+ } = props;
39
+ const { labelProps, fieldProps } = useLabel({
40
+ label,
41
+ ...otherProps
42
+ });
43
+ const validationClasses = useValidationClasses({ isInvalid });
44
+ const stateClasses = {
45
+ "--is-disabled": isDisabled,
46
+ "--is-required": typeof isRequired === "boolean" && isRequired,
47
+ "--is-optional": typeof isRequired === "boolean" && !isRequired
48
+ };
49
+ const sharedClasses = classNames(validationClasses, stateClasses);
50
+ const wrapperClasses = classNames(
51
+ "mobius-select__wrapper",
52
+ sharedClasses,
53
+ otherProps.className
54
+ );
55
+ const selectClasses = classNames(
56
+ "mobius-select",
57
+ sharedClasses,
58
+ otherProps.className
59
+ );
60
+ const labelClasses = classNames(
61
+ "mobius-label",
62
+ sharedClasses,
63
+ otherProps.className
64
+ );
65
+ const iconClasses = classNames("mobius-select__icon", sharedClasses);
66
+ const errorMessageId = useId();
67
+ const shouldErrorMessageShow = errorMessage ? errorMessageId : void 0;
68
+ const describedBy = spaceDelimitedList([
69
+ shouldErrorMessageShow,
70
+ props["aria-describedby"]
71
+ ]);
72
+ const handleChange = (e) => {
73
+ if (onChange) {
74
+ onChange(e);
75
+ }
76
+ };
77
+ return /* @__PURE__ */ jsxs(Stack, { className: "mobius mobius-select__outer", gap: "xs", children: [
78
+ label && /* @__PURE__ */ jsx(Label, { ...labelProps, className: labelClasses, children: label }),
79
+ /* @__PURE__ */ jsxs("div", { className: wrapperClasses, children: [
80
+ /* @__PURE__ */ jsx(
81
+ "select",
82
+ {
83
+ ...otherProps,
84
+ ...fieldProps,
85
+ ref,
86
+ multiple: false,
87
+ className: selectClasses,
88
+ disabled: isDisabled,
89
+ "aria-invalid": !!errorMessage,
90
+ "aria-describedby": describedBy,
91
+ "aria-required": isRequired,
92
+ required: isRequired,
93
+ onChange: handleChange
94
+ }
95
+ ),
96
+ /* @__PURE__ */ jsx("span", { className: iconClasses, children: /* @__PURE__ */ jsx(Icon, { icon: chevronDown }) })
97
+ ] }),
98
+ errorMessage && /* @__PURE__ */ jsx(ErrorMessage, { id: errorMessageId, errorMessage })
99
+ ] });
100
+ };
101
+ Select.displayName = "Select";
102
+
103
+ export {
104
+ Select
105
+ };
106
+ //# sourceMappingURL=chunk-M2NDSQR5.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/Select/Select.tsx"],
4
+ "sourcesContent": ["\"use client\";\n\nimport { chevronDown } from \"@simplybusiness/icons\";\nimport classNames from \"classnames/dedupe\";\nimport type { ChangeEvent, ReactElement, RefAttributes } from \"react\";\nimport { useId } from \"react\";\nimport { useValidationClasses } from \"../../hooks\";\nimport type { UseLabelProps } from \"../../hooks/useLabel\";\nimport { useLabel } from \"../../hooks/useLabel\";\nimport type { DOMProps, Validation } from \"../../types\";\nimport { spaceDelimitedList } from \"../../utils/spaceDelimitedList\";\nimport { ErrorMessage } from \"../ErrorMessage\";\nimport { Icon } from \"../Icon\";\nimport { Label } from \"../Label\";\nimport type { OptionProps } from \"../Option\";\nimport { Stack } from \"../Stack\";\nimport \"./Select.css\";\n\nexport type SelectElementType = HTMLSelectElement;\nexport interface SelectProps\n extends\n UseLabelProps,\n Validation,\n DOMProps,\n RefAttributes<SelectElementType> {\n name?: string;\n onChange?: (e: ChangeEvent<HTMLSelectElement>) => void;\n value?: string;\n defaultValue?: string;\n className?: string;\n errorMessage?: string;\n children?: ReactElement<OptionProps>[] | ReactElement<OptionProps>;\n \"aria-describedby\"?: string;\n isDisabled?: boolean;\n}\n\nconst Select = ({ ref, ...props }: SelectProps) => {\n const {\n label,\n onChange,\n isInvalid,\n errorMessage,\n isDisabled = false,\n isRequired,\n ...otherProps\n } = props;\n\n const { labelProps, fieldProps } = useLabel({\n label,\n ...otherProps,\n });\n\n const validationClasses = useValidationClasses({ isInvalid });\n\n const stateClasses = {\n \"--is-disabled\": isDisabled,\n \"--is-required\": typeof isRequired === \"boolean\" && isRequired,\n \"--is-optional\": typeof isRequired === \"boolean\" && !isRequired,\n };\n\n const sharedClasses = classNames(validationClasses, stateClasses);\n\n const wrapperClasses = classNames(\n \"mobius-select__wrapper\",\n sharedClasses,\n otherProps.className,\n );\n const selectClasses = classNames(\n \"mobius-select\",\n sharedClasses,\n otherProps.className,\n );\n const labelClasses = classNames(\n \"mobius-label\",\n sharedClasses,\n otherProps.className,\n );\n const iconClasses = classNames(\"mobius-select__icon\", sharedClasses);\n const errorMessageId = useId();\n const shouldErrorMessageShow = errorMessage ? errorMessageId : undefined;\n const describedBy = spaceDelimitedList([\n shouldErrorMessageShow,\n props[\"aria-describedby\"],\n ]);\n\n const handleChange = (e: ChangeEvent<HTMLSelectElement>) => {\n if (onChange) {\n onChange(e);\n }\n };\n\n return (\n <Stack className=\"mobius mobius-select__outer\" gap=\"xs\">\n {label && (\n <Label {...labelProps} className={labelClasses}>\n {label}\n </Label>\n )}\n <div className={wrapperClasses}>\n <select\n {...otherProps}\n {...fieldProps}\n ref={ref}\n multiple={false}\n className={selectClasses}\n disabled={isDisabled}\n aria-invalid={!!errorMessage}\n aria-describedby={describedBy}\n aria-required={isRequired}\n required={isRequired}\n onChange={handleChange}\n />\n <span className={iconClasses}>\n <Icon icon={chevronDown} />\n </span>\n </div>\n {errorMessage && (\n <ErrorMessage id={errorMessageId} errorMessage={errorMessage} />\n )}\n </Stack>\n );\n};\n\nSelect.displayName = \"Select\";\nexport { Select };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,mBAAmB;AAC5B,OAAO,gBAAgB;AAEvB,SAAS,aAAa;AAWtB,OAAO;AA8EC,cAIF,YAJE;AA1DR,IAAM,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,MAAmB;AACjD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,EAAE,YAAY,WAAW,IAAI,SAAS;AAAA,IAC1C;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AAED,QAAM,oBAAoB,qBAAqB,EAAE,UAAU,CAAC;AAE5D,QAAM,eAAe;AAAA,IACnB,iBAAiB;AAAA,IACjB,iBAAiB,OAAO,eAAe,aAAa;AAAA,IACpD,iBAAiB,OAAO,eAAe,aAAa,CAAC;AAAA,EACvD;AAEA,QAAM,gBAAgB,WAAW,mBAAmB,YAAY;AAEhE,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AACA,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AACA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AACA,QAAM,cAAc,WAAW,uBAAuB,aAAa;AACnE,QAAM,iBAAiB,MAAM;AAC7B,QAAM,yBAAyB,eAAe,iBAAiB;AAC/D,QAAM,cAAc,mBAAmB;AAAA,IACrC;AAAA,IACA,MAAM,kBAAkB;AAAA,EAC1B,CAAC;AAED,QAAM,eAAe,CAAC,MAAsC;AAC1D,QAAI,UAAU;AACZ,eAAS,CAAC;AAAA,IACZ;AAAA,EACF;AAEA,SACE,qBAAC,SAAM,WAAU,+BAA8B,KAAI,MAChD;AAAA,aACC,oBAAC,SAAO,GAAG,YAAY,WAAW,cAC/B,iBACH;AAAA,IAEF,qBAAC,SAAI,WAAW,gBACd;AAAA;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACH,GAAG;AAAA,UACJ;AAAA,UACA,UAAU;AAAA,UACV,WAAW;AAAA,UACX,UAAU;AAAA,UACV,gBAAc,CAAC,CAAC;AAAA,UAChB,oBAAkB;AAAA,UAClB,iBAAe;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA;AAAA,MACZ;AAAA,MACA,oBAAC,UAAK,WAAW,aACf,8BAAC,QAAK,MAAM,aAAa,GAC3B;AAAA,OACF;AAAA,IACC,gBACC,oBAAC,gBAAa,IAAI,gBAAgB,cAA4B;AAAA,KAElE;AAEJ;AAEA,OAAO,cAAc;",
6
+ "names": []
7
+ }