@simplybusiness/mobius 10.3.2 → 10.3.3
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.
- package/CHANGELOG.md +7 -0
- package/dist/cjs/components/AddressLookup/AddressLookup.js +888 -5314
- package/dist/cjs/components/AddressLookup/AddressLookup.js.map +4 -4
- package/dist/cjs/components/AddressLookup/index.js +952 -5381
- package/dist/cjs/components/AddressLookup/index.js.map +4 -4
- package/dist/cjs/components/Checkbox/Checkbox.js +245 -5625
- package/dist/cjs/components/Checkbox/Checkbox.js.map +4 -4
- package/dist/cjs/components/Checkbox/CheckboxGroup.js +371 -5614
- package/dist/cjs/components/Checkbox/CheckboxGroup.js.map +4 -4
- package/dist/cjs/components/Checkbox/index.js +377 -5619
- package/dist/cjs/components/Checkbox/index.js.map +4 -4
- package/dist/cjs/components/Combobox/Combobox.js +829 -5344
- package/dist/cjs/components/Combobox/Combobox.js.map +4 -4
- package/dist/cjs/components/Combobox/index.js +813 -5327
- package/dist/cjs/components/Combobox/index.js.map +4 -4
- package/dist/cjs/components/DateField/DateField.js +379 -5505
- package/dist/cjs/components/DateField/DateField.js.map +4 -4
- package/dist/cjs/components/DateField/index.js +383 -5508
- package/dist/cjs/components/DateField/index.js.map +4 -4
- package/dist/cjs/components/ErrorMessage/ErrorMessage.js +120 -5643
- package/dist/cjs/components/ErrorMessage/ErrorMessage.js.map +4 -4
- package/dist/cjs/components/ErrorMessage/index.js +121 -5642
- package/dist/cjs/components/ErrorMessage/index.js.map +4 -4
- package/dist/cjs/components/ExpandableText/ExpandableText.js +511 -5604
- package/dist/cjs/components/ExpandableText/ExpandableText.js.map +4 -4
- package/dist/cjs/components/ExpandableText/index.js +512 -5604
- package/dist/cjs/components/ExpandableText/index.js.map +4 -4
- package/dist/cjs/components/MaskedField/MaskedField.js +394 -5511
- package/dist/cjs/components/MaskedField/MaskedField.js.map +4 -4
- package/dist/cjs/components/MaskedField/index.js +293 -5118
- package/dist/cjs/components/MaskedField/index.js.map +4 -4
- package/dist/cjs/components/NumberField/NumberField.js +357 -5523
- package/dist/cjs/components/NumberField/NumberField.js.map +4 -4
- package/dist/cjs/components/NumberField/index.js +358 -5523
- package/dist/cjs/components/NumberField/index.js.map +4 -4
- package/dist/cjs/components/PasswordField/PasswordField.js +330 -5511
- package/dist/cjs/components/PasswordField/PasswordField.js.map +4 -4
- package/dist/cjs/components/PasswordField/ShowHideButton.js +32 -5655
- package/dist/cjs/components/PasswordField/ShowHideButton.js.map +4 -4
- package/dist/cjs/components/PasswordField/index.js +332 -5512
- package/dist/cjs/components/PasswordField/index.js.map +4 -4
- package/dist/cjs/components/Radio/Radio.js +242 -5632
- package/dist/cjs/components/Radio/Radio.js.map +4 -4
- package/dist/cjs/components/Radio/RadioGroup.js +274 -5619
- package/dist/cjs/components/Radio/RadioGroup.js.map +4 -4
- package/dist/cjs/components/Radio/index.js +404 -5628
- package/dist/cjs/components/Radio/index.js.map +4 -4
- package/dist/cjs/components/Select/Select.js +233 -5588
- package/dist/cjs/components/Select/Select.js.map +4 -4
- package/dist/cjs/components/Select/index.js +234 -5588
- package/dist/cjs/components/Select/index.js.map +4 -4
- package/dist/cjs/components/TextArea/TextArea.js +229 -5531
- package/dist/cjs/components/TextArea/TextArea.js.map +4 -4
- package/dist/cjs/components/TextArea/index.js +230 -5531
- package/dist/cjs/components/TextArea/index.js.map +4 -4
- package/dist/cjs/components/TextField/TextField.js +265 -5522
- package/dist/cjs/components/TextField/TextField.js.map +4 -4
- package/dist/cjs/components/TextField/index.js +266 -5522
- package/dist/cjs/components/TextField/index.js.map +4 -4
- package/dist/cjs/components/index.js +4273 -5291
- package/dist/cjs/components/index.js.map +4 -4
- package/dist/cjs/index.js +4304 -5334
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs/meta.json +5734 -51529
- package/dist/esm/chunk-3O5DIIGS.js +1 -0
- package/dist/esm/chunk-3O5DIIGS.js.map +7 -0
- package/dist/esm/chunk-3PRSHEVX.js +1 -0
- package/dist/esm/chunk-3PRSHEVX.js.map +7 -0
- package/dist/esm/chunk-4NBLO5WK.js +54 -0
- package/dist/esm/chunk-4NBLO5WK.js.map +7 -0
- package/dist/esm/chunk-4WVJNNBK.js +157 -0
- package/dist/esm/chunk-4WVJNNBK.js.map +7 -0
- package/dist/esm/chunk-5L4G4VLM.js +1 -0
- package/dist/esm/chunk-5L4G4VLM.js.map +7 -0
- package/dist/esm/chunk-5OFXPT4J.js +135 -0
- package/dist/esm/chunk-5OFXPT4J.js.map +7 -0
- package/dist/esm/chunk-6O77SOOB.js +1 -0
- package/dist/esm/chunk-6O77SOOB.js.map +7 -0
- package/dist/esm/chunk-AFU7BFCD.js +151 -0
- package/dist/esm/chunk-AFU7BFCD.js.map +7 -0
- package/dist/esm/chunk-BGR2OTTR.js +1 -0
- package/dist/esm/chunk-BGR2OTTR.js.map +7 -0
- package/dist/esm/chunk-BIGO5EVC.js +1 -0
- package/dist/esm/chunk-BIGO5EVC.js.map +7 -0
- package/dist/esm/chunk-CUOVI2HT.js +1 -0
- package/dist/esm/chunk-CUOVI2HT.js.map +7 -0
- package/dist/esm/chunk-F4RQKLF7.js +1 -0
- package/dist/esm/chunk-F4RQKLF7.js.map +7 -0
- package/dist/esm/chunk-FKTDL7KO.js +355 -0
- package/dist/esm/chunk-FKTDL7KO.js.map +7 -0
- package/dist/esm/chunk-KQZ3MNK5.js +100 -0
- package/dist/esm/chunk-KQZ3MNK5.js.map +7 -0
- package/dist/esm/chunk-M2NDSQR5.js +106 -0
- package/dist/esm/chunk-M2NDSQR5.js.map +7 -0
- package/dist/esm/chunk-N4WQ6522.js +125 -0
- package/dist/esm/chunk-N4WQ6522.js.map +7 -0
- package/dist/esm/{chunk-CNOF66SV.js → chunk-NGNVAFBJ.js} +4 -4
- package/dist/esm/chunk-NOQ27VLY.js +1 -0
- package/dist/esm/chunk-NOQ27VLY.js.map +7 -0
- package/dist/esm/chunk-ONDOONBM.js +101 -0
- package/dist/esm/chunk-ONDOONBM.js.map +7 -0
- package/dist/esm/chunk-P34DI6BE.js +1 -0
- package/dist/esm/chunk-P34DI6BE.js.map +7 -0
- package/dist/esm/chunk-P5VEI574.js +97 -0
- package/dist/esm/chunk-P5VEI574.js.map +7 -0
- package/dist/esm/chunk-QPIA6BGW.js +64 -0
- package/dist/esm/chunk-QPIA6BGW.js.map +7 -0
- package/dist/esm/chunk-SZEFLEDA.js +1 -0
- package/dist/esm/chunk-SZEFLEDA.js.map +7 -0
- package/dist/esm/chunk-TXB4BOHB.js +1 -0
- package/dist/esm/chunk-TXB4BOHB.js.map +7 -0
- package/dist/esm/chunk-UIIXVY6K.js +123 -0
- package/dist/esm/chunk-UIIXVY6K.js.map +7 -0
- package/dist/esm/chunk-UQVAEWY2.js +44 -0
- package/dist/esm/chunk-UQVAEWY2.js.map +7 -0
- package/dist/esm/chunk-WC3D5GNN.js +29 -0
- package/dist/esm/chunk-WC3D5GNN.js.map +7 -0
- package/dist/esm/chunk-WNRO77YH.js +1 -0
- package/dist/esm/chunk-WNRO77YH.js.map +7 -0
- package/dist/esm/chunk-X6EPYQKX.js +96 -0
- package/dist/esm/chunk-X6EPYQKX.js.map +7 -0
- package/dist/esm/chunk-ZN5TRIVZ.js +41 -0
- package/dist/esm/chunk-ZN5TRIVZ.js.map +7 -0
- package/dist/esm/components/AddressLookup/AddressLookup.js +9 -106
- package/dist/esm/components/AddressLookup/index.js +10 -103
- package/dist/esm/components/Checkbox/Checkbox.js +3 -116
- package/dist/esm/components/Checkbox/CheckboxGroup.js +4 -114
- package/dist/esm/components/Checkbox/index.js +7 -114
- package/dist/esm/components/Combobox/Combobox.js +6 -107
- package/dist/esm/components/Combobox/index.js +8 -107
- package/dist/esm/components/DateField/DateField.js +6 -113
- package/dist/esm/components/DateField/index.js +7 -113
- package/dist/esm/components/ErrorMessage/ErrorMessage.js +1 -146
- package/dist/esm/components/ErrorMessage/index.js +2 -146
- package/dist/esm/components/ExpandableText/ExpandableText.js +1 -108
- package/dist/esm/components/ExpandableText/index.js +2 -108
- package/dist/esm/components/MaskedField/MaskedField.js +5 -114
- package/dist/esm/components/MaskedField/MaskedField.js.map +1 -1
- package/dist/esm/components/MaskedField/index.js +6 -114
- package/dist/esm/components/NumberField/NumberField.js +6 -114
- package/dist/esm/components/NumberField/index.js +7 -114
- package/dist/esm/components/PasswordField/PasswordField.js +7 -114
- package/dist/esm/components/PasswordField/ShowHideButton.js +1 -149
- package/dist/esm/components/PasswordField/index.js +8 -114
- package/dist/esm/components/Radio/Radio.js +3 -144
- package/dist/esm/components/Radio/RadioGroup.js +3 -114
- package/dist/esm/components/Radio/index.js +7 -115
- package/dist/esm/components/Select/Select.js +3 -114
- package/dist/esm/components/Select/index.js +4 -114
- package/dist/esm/components/Slider/Slider.js +2 -2
- package/dist/esm/components/Slider/index.js +2 -2
- package/dist/esm/components/TextArea/TextArea.js +3 -112
- package/dist/esm/components/TextArea/index.js +4 -112
- package/dist/esm/components/TextField/TextField.js +4 -114
- package/dist/esm/components/TextField/index.js +5 -114
- package/dist/esm/components/index.js +81 -44
- package/dist/esm/index.js +81 -39
- package/dist/esm/meta.json +6950 -19169
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/components/ErrorMessage/ErrorMessage.tsx +1 -1
- package/src/components/ExpandableText/ExpandableText.tsx +3 -1
- package/src/components/PasswordField/ShowHideButton.tsx +1 -1
- package/dist/esm/chunk-W2RQH4WS.js +0 -1606
- package/dist/esm/chunk-W2RQH4WS.js.map +0 -7
- /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 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-F4RQKLF7.js.map
|
|
@@ -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
|
+
}
|