@axenstudio/axen-form 0.1.1

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 (210) hide show
  1. package/README.md +665 -0
  2. package/dist/adapters/yupAdapter.cjs +61 -0
  3. package/dist/adapters/yupAdapter.d.ts +21 -0
  4. package/dist/adapters/yupAdapter.d.ts.map +1 -0
  5. package/dist/adapters/yupAdapter.js +61 -0
  6. package/dist/adapters/zodAdapter.cjs +59 -0
  7. package/dist/adapters/zodAdapter.d.ts +22 -0
  8. package/dist/adapters/zodAdapter.d.ts.map +1 -0
  9. package/dist/adapters/zodAdapter.js +59 -0
  10. package/dist/core/dateUtils.cjs +69 -0
  11. package/dist/core/dateUtils.d.ts +28 -0
  12. package/dist/core/dateUtils.d.ts.map +1 -0
  13. package/dist/core/dateUtils.js +69 -0
  14. package/dist/core/formStore.cjs +184 -0
  15. package/dist/core/formStore.d.ts +39 -0
  16. package/dist/core/formStore.d.ts.map +1 -0
  17. package/dist/core/formStore.js +184 -0
  18. package/dist/core/numberUtils.cjs +59 -0
  19. package/dist/core/numberUtils.d.ts +26 -0
  20. package/dist/core/numberUtils.d.ts.map +1 -0
  21. package/dist/core/numberUtils.js +59 -0
  22. package/dist/core/pathUtils.cjs +44 -0
  23. package/dist/core/pathUtils.d.ts +15 -0
  24. package/dist/core/pathUtils.d.ts.map +1 -0
  25. package/dist/core/pathUtils.js +44 -0
  26. package/dist/core/payloadUtils.cjs +26 -0
  27. package/dist/core/payloadUtils.d.ts +22 -0
  28. package/dist/core/payloadUtils.d.ts.map +1 -0
  29. package/dist/core/payloadUtils.js +26 -0
  30. package/dist/core/validation.cjs +41 -0
  31. package/dist/core/validation.d.ts +7 -0
  32. package/dist/core/validation.d.ts.map +1 -0
  33. package/dist/core/validation.js +41 -0
  34. package/dist/fields/AutocompleteField/AutocompleteField.cjs +242 -0
  35. package/dist/fields/AutocompleteField/AutocompleteField.d.ts +6 -0
  36. package/dist/fields/AutocompleteField/AutocompleteField.d.ts.map +1 -0
  37. package/dist/fields/AutocompleteField/AutocompleteField.js +242 -0
  38. package/dist/fields/AutocompleteField/AutocompleteField.module.css +168 -0
  39. package/dist/fields/AutocompleteField/AutocompleteField.module.css.cjs +44 -0
  40. package/dist/fields/AutocompleteField/AutocompleteField.module.css.js +44 -0
  41. package/dist/fields/AutocompleteMultiField/AutocompleteMultiField.cjs +286 -0
  42. package/dist/fields/AutocompleteMultiField/AutocompleteMultiField.d.ts +6 -0
  43. package/dist/fields/AutocompleteMultiField/AutocompleteMultiField.d.ts.map +1 -0
  44. package/dist/fields/AutocompleteMultiField/AutocompleteMultiField.js +286 -0
  45. package/dist/fields/AutocompletePredictField/AutocompletePredictField.cjs +289 -0
  46. package/dist/fields/AutocompletePredictField/AutocompletePredictField.d.ts +10 -0
  47. package/dist/fields/AutocompletePredictField/AutocompletePredictField.d.ts.map +1 -0
  48. package/dist/fields/AutocompletePredictField/AutocompletePredictField.js +289 -0
  49. package/dist/fields/CheckboxField/CheckboxField.cjs +60 -0
  50. package/dist/fields/CheckboxField/CheckboxField.d.ts +3 -0
  51. package/dist/fields/CheckboxField/CheckboxField.d.ts.map +1 -0
  52. package/dist/fields/CheckboxField/CheckboxField.js +60 -0
  53. package/dist/fields/CheckboxField/CheckboxField.module.css +29 -0
  54. package/dist/fields/CheckboxField/CheckboxField.module.css.cjs +11 -0
  55. package/dist/fields/CheckboxField/CheckboxField.module.css.js +11 -0
  56. package/dist/fields/ColorField/ColorField.cjs +69 -0
  57. package/dist/fields/ColorField/ColorField.d.ts +3 -0
  58. package/dist/fields/ColorField/ColorField.d.ts.map +1 -0
  59. package/dist/fields/ColorField/ColorField.js +69 -0
  60. package/dist/fields/ColorField/ColorField.module.css +33 -0
  61. package/dist/fields/ColorField/ColorField.module.css.cjs +14 -0
  62. package/dist/fields/ColorField/ColorField.module.css.js +14 -0
  63. package/dist/fields/CurrencyField/CurrencyField.cjs +120 -0
  64. package/dist/fields/CurrencyField/CurrencyField.d.ts +10 -0
  65. package/dist/fields/CurrencyField/CurrencyField.d.ts.map +1 -0
  66. package/dist/fields/CurrencyField/CurrencyField.js +120 -0
  67. package/dist/fields/DateField/DateField.cjs +70 -0
  68. package/dist/fields/DateField/DateField.d.ts +7 -0
  69. package/dist/fields/DateField/DateField.d.ts.map +1 -0
  70. package/dist/fields/DateField/DateField.js +70 -0
  71. package/dist/fields/DateTimeField/DateTimeField.cjs +71 -0
  72. package/dist/fields/DateTimeField/DateTimeField.d.ts +8 -0
  73. package/dist/fields/DateTimeField/DateTimeField.d.ts.map +1 -0
  74. package/dist/fields/DateTimeField/DateTimeField.js +71 -0
  75. package/dist/fields/EmailField/EmailField.cjs +57 -0
  76. package/dist/fields/EmailField/EmailField.d.ts +3 -0
  77. package/dist/fields/EmailField/EmailField.d.ts.map +1 -0
  78. package/dist/fields/EmailField/EmailField.js +57 -0
  79. package/dist/fields/NumberField/NumberField.cjs +110 -0
  80. package/dist/fields/NumberField/NumberField.d.ts +10 -0
  81. package/dist/fields/NumberField/NumberField.d.ts.map +1 -0
  82. package/dist/fields/NumberField/NumberField.js +110 -0
  83. package/dist/fields/PasswordField/PasswordField.cjs +77 -0
  84. package/dist/fields/PasswordField/PasswordField.d.ts +3 -0
  85. package/dist/fields/PasswordField/PasswordField.d.ts.map +1 -0
  86. package/dist/fields/PasswordField/PasswordField.js +77 -0
  87. package/dist/fields/PasswordField/PasswordField.module.css +41 -0
  88. package/dist/fields/PasswordField/PasswordField.module.css.cjs +14 -0
  89. package/dist/fields/PasswordField/PasswordField.module.css.js +14 -0
  90. package/dist/fields/PhoneField/PhoneField.cjs +58 -0
  91. package/dist/fields/PhoneField/PhoneField.d.ts +3 -0
  92. package/dist/fields/PhoneField/PhoneField.d.ts.map +1 -0
  93. package/dist/fields/PhoneField/PhoneField.js +58 -0
  94. package/dist/fields/RadioField/RadioField.cjs +66 -0
  95. package/dist/fields/RadioField/RadioField.d.ts +3 -0
  96. package/dist/fields/RadioField/RadioField.d.ts.map +1 -0
  97. package/dist/fields/RadioField/RadioField.js +66 -0
  98. package/dist/fields/RadioField/RadioField.module.css +34 -0
  99. package/dist/fields/RadioField/RadioField.module.css.cjs +14 -0
  100. package/dist/fields/RadioField/RadioField.module.css.js +14 -0
  101. package/dist/fields/SelectField/SelectField.cjs +58 -0
  102. package/dist/fields/SelectField/SelectField.d.ts +3 -0
  103. package/dist/fields/SelectField/SelectField.d.ts.map +1 -0
  104. package/dist/fields/SelectField/SelectField.js +58 -0
  105. package/dist/fields/SliderField/SliderField.cjs +79 -0
  106. package/dist/fields/SliderField/SliderField.d.ts +7 -0
  107. package/dist/fields/SliderField/SliderField.d.ts.map +1 -0
  108. package/dist/fields/SliderField/SliderField.js +79 -0
  109. package/dist/fields/SliderField/SliderField.module.css +76 -0
  110. package/dist/fields/SliderField/SliderField.module.css.cjs +14 -0
  111. package/dist/fields/SliderField/SliderField.module.css.js +14 -0
  112. package/dist/fields/SwitchField/SwitchField.cjs +65 -0
  113. package/dist/fields/SwitchField/SwitchField.d.ts +3 -0
  114. package/dist/fields/SwitchField/SwitchField.d.ts.map +1 -0
  115. package/dist/fields/SwitchField/SwitchField.js +65 -0
  116. package/dist/fields/SwitchField/SwitchField.module.css +79 -0
  117. package/dist/fields/SwitchField/SwitchField.module.css.cjs +17 -0
  118. package/dist/fields/SwitchField/SwitchField.module.css.js +17 -0
  119. package/dist/fields/TextField/TextField.cjs +56 -0
  120. package/dist/fields/TextField/TextField.d.ts +3 -0
  121. package/dist/fields/TextField/TextField.d.ts.map +1 -0
  122. package/dist/fields/TextField/TextField.js +56 -0
  123. package/dist/fields/TextareaField/TextareaField.cjs +57 -0
  124. package/dist/fields/TextareaField/TextareaField.d.ts +5 -0
  125. package/dist/fields/TextareaField/TextareaField.d.ts.map +1 -0
  126. package/dist/fields/TextareaField/TextareaField.js +57 -0
  127. package/dist/fields/TimeField/TimeField.cjs +67 -0
  128. package/dist/fields/TimeField/TimeField.d.ts +6 -0
  129. package/dist/fields/TimeField/TimeField.d.ts.map +1 -0
  130. package/dist/fields/TimeField/TimeField.js +67 -0
  131. package/dist/fields/defaultComponentMap.cjs +43 -0
  132. package/dist/fields/defaultComponentMap.d.ts +7 -0
  133. package/dist/fields/defaultComponentMap.d.ts.map +1 -0
  134. package/dist/fields/defaultComponentMap.js +43 -0
  135. package/dist/fields/fieldBase.module.css +201 -0
  136. package/dist/fields/fieldBase.module.css.cjs +50 -0
  137. package/dist/fields/fieldBase.module.css.js +50 -0
  138. package/dist/fields/fieldUtils.cjs +26 -0
  139. package/dist/fields/fieldUtils.d.ts +24 -0
  140. package/dist/fields/fieldUtils.d.ts.map +1 -0
  141. package/dist/fields/fieldUtils.js +26 -0
  142. package/dist/index.cjs +99 -0
  143. package/dist/index.d.ts +42 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +99 -0
  146. package/dist/layout/Box/Box.cjs +70 -0
  147. package/dist/layout/Box/Box.d.ts +6 -0
  148. package/dist/layout/Box/Box.d.ts.map +1 -0
  149. package/dist/layout/Box/Box.js +70 -0
  150. package/dist/layout/Box/Box.module.css +3 -0
  151. package/dist/layout/Box/Box.module.css.cjs +8 -0
  152. package/dist/layout/Box/Box.module.css.js +8 -0
  153. package/dist/layout/Divider/Divider.cjs +20 -0
  154. package/dist/layout/Divider/Divider.d.ts +6 -0
  155. package/dist/layout/Divider/Divider.d.ts.map +1 -0
  156. package/dist/layout/Divider/Divider.js +20 -0
  157. package/dist/layout/Divider/Divider.module.css +25 -0
  158. package/dist/layout/Divider/Divider.module.css.cjs +14 -0
  159. package/dist/layout/Divider/Divider.module.css.js +14 -0
  160. package/dist/layout/Grid/Grid.cjs +106 -0
  161. package/dist/layout/Grid/Grid.d.ts +7 -0
  162. package/dist/layout/Grid/Grid.d.ts.map +1 -0
  163. package/dist/layout/Grid/Grid.js +106 -0
  164. package/dist/layout/Grid/Grid.module.css +43 -0
  165. package/dist/layout/Grid/Grid.module.css.cjs +23 -0
  166. package/dist/layout/Grid/Grid.module.css.js +23 -0
  167. package/dist/layout/Spacer/Spacer.cjs +30 -0
  168. package/dist/layout/Spacer/Spacer.d.ts +21 -0
  169. package/dist/layout/Spacer/Spacer.d.ts.map +1 -0
  170. package/dist/layout/Spacer/Spacer.js +30 -0
  171. package/dist/layout/Stack/Stack.cjs +52 -0
  172. package/dist/layout/Stack/Stack.d.ts +7 -0
  173. package/dist/layout/Stack/Stack.d.ts.map +1 -0
  174. package/dist/layout/Stack/Stack.js +52 -0
  175. package/dist/layout/Stack/Stack.module.css +3 -0
  176. package/dist/layout/Stack/Stack.module.css.cjs +8 -0
  177. package/dist/layout/Stack/Stack.module.css.js +8 -0
  178. package/dist/layout/index.d.ts +6 -0
  179. package/dist/layout/index.d.ts.map +1 -0
  180. package/dist/react/AxenArrayField.cjs +80 -0
  181. package/dist/react/AxenArrayField.d.ts +15 -0
  182. package/dist/react/AxenArrayField.d.ts.map +1 -0
  183. package/dist/react/AxenArrayField.js +80 -0
  184. package/dist/react/AxenField.cjs +62 -0
  185. package/dist/react/AxenField.d.ts +13 -0
  186. package/dist/react/AxenField.d.ts.map +1 -0
  187. package/dist/react/AxenField.js +62 -0
  188. package/dist/react/AxenForm.cjs +134 -0
  189. package/dist/react/AxenForm.d.ts +7 -0
  190. package/dist/react/AxenForm.d.ts.map +1 -0
  191. package/dist/react/AxenForm.js +134 -0
  192. package/dist/react/FormContext.cjs +13 -0
  193. package/dist/react/FormContext.d.ts +11 -0
  194. package/dist/react/FormContext.d.ts.map +1 -0
  195. package/dist/react/FormContext.js +13 -0
  196. package/dist/react/useAxenForm.cjs +88 -0
  197. package/dist/react/useAxenForm.d.ts +8 -0
  198. package/dist/react/useAxenForm.d.ts.map +1 -0
  199. package/dist/react/useAxenForm.js +88 -0
  200. package/dist/react/useField.cjs +41 -0
  201. package/dist/react/useField.d.ts +13 -0
  202. package/dist/react/useField.d.ts.map +1 -0
  203. package/dist/react/useField.js +41 -0
  204. package/dist/react/useFieldArray.cjs +74 -0
  205. package/dist/react/useFieldArray.d.ts +5 -0
  206. package/dist/react/useFieldArray.d.ts.map +1 -0
  207. package/dist/react/useFieldArray.js +74 -0
  208. package/dist/types.d.ts +226 -0
  209. package/dist/types.d.ts.map +1 -0
  210. package/package.json +87 -0
@@ -0,0 +1,44 @@
1
+ const inputWrap = "_inputWrap_1hzxx_1";
2
+ const spinner = "_spinner_1hzxx_7";
3
+ const dropdown = "_dropdown_1hzxx_32";
4
+ const option = "_option_1hzxx_48";
5
+ const optionActive = "_optionActive_1hzxx_63";
6
+ const optionDisabled = "_optionDisabled_1hzxx_67";
7
+ const noResults = "_noResults_1hzxx_72";
8
+ const chipWrap = "_chipWrap_1hzxx_83";
9
+ const chip = "_chip_1hzxx_83";
10
+ const chipRemove = "_chipRemove_1hzxx_105";
11
+ const predictWrap = "_predictWrap_1hzxx_131";
12
+ const ghostText = "_ghostText_1hzxx_137";
13
+ const ghostHidden = "_ghostHidden_1hzxx_150";
14
+ const localStyles = {
15
+ inputWrap,
16
+ spinner,
17
+ dropdown,
18
+ option,
19
+ optionActive,
20
+ optionDisabled,
21
+ noResults,
22
+ chipWrap,
23
+ chip,
24
+ chipRemove,
25
+ predictWrap,
26
+ ghostText,
27
+ ghostHidden
28
+ };
29
+ export {
30
+ chip,
31
+ chipRemove,
32
+ chipWrap,
33
+ localStyles as default,
34
+ dropdown,
35
+ ghostHidden,
36
+ ghostText,
37
+ inputWrap,
38
+ noResults,
39
+ option,
40
+ optionActive,
41
+ optionDisabled,
42
+ predictWrap,
43
+ spinner
44
+ };
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const AutocompleteField_module = require("../AutocompleteField/AutocompleteField.module.css.cjs");
6
+ const fieldBase_module = require("../fieldBase.module.css.cjs");
7
+ const fieldUtils = require("../fieldUtils.cjs");
8
+ const DEBOUNCE_MS = 400;
9
+ function AutocompleteMultiField({
10
+ name,
11
+ value,
12
+ onChange: _onChange,
13
+ onBlur,
14
+ error,
15
+ helperText,
16
+ label,
17
+ placeholder,
18
+ disabled,
19
+ readOnly,
20
+ required,
21
+ options: staticOptions,
22
+ fetchOptions,
23
+ optionLabel,
24
+ form
25
+ }) {
26
+ const [inputText, setInputText] = react.useState("");
27
+ const [filteredOptions, setFilteredOptions] = react.useState([]);
28
+ const [isOpen, setIsOpen] = react.useState(false);
29
+ const [activeIndex, setActiveIndex] = react.useState(-1);
30
+ const [loading, setLoading] = react.useState(false);
31
+ const abortRef = react.useRef(null);
32
+ const debounceRef = react.useRef(void 0);
33
+ const knownPoolRef = react.useRef(staticOptions ?? []);
34
+ const wrapperRef = react.useRef(null);
35
+ const selectedValues = Array.isArray(value) ? value : [];
36
+ const getOptionLabel = react.useCallback(
37
+ (opt) => {
38
+ if (optionLabel) {
39
+ const val = opt[optionLabel];
40
+ return typeof val === "string" || typeof val === "number" ? String(val) : opt.label;
41
+ }
42
+ return opt.label;
43
+ },
44
+ [optionLabel]
45
+ );
46
+ const doSearch = react.useCallback(
47
+ (query) => {
48
+ var _a;
49
+ if (fetchOptions) {
50
+ (_a = abortRef.current) == null ? void 0 : _a.abort();
51
+ const controller = new AbortController();
52
+ abortRef.current = controller;
53
+ setLoading(true);
54
+ fetchOptions(query, controller.signal).then((results) => {
55
+ if (!controller.signal.aborted) {
56
+ for (const r of results) {
57
+ if (!knownPoolRef.current.some((k) => k.value === r.value)) {
58
+ knownPoolRef.current.push(r);
59
+ }
60
+ }
61
+ setFilteredOptions(results.filter((o) => !selectedValues.includes(o.value)));
62
+ setLoading(false);
63
+ }
64
+ }).catch((err) => {
65
+ if (!controller.signal.aborted && err.name !== "AbortError") {
66
+ setFilteredOptions([]);
67
+ setLoading(false);
68
+ }
69
+ });
70
+ } else {
71
+ const q = query.toLowerCase();
72
+ const opts = (staticOptions ?? []).filter(
73
+ (opt) => getOptionLabel(opt).toLowerCase().includes(q) && !selectedValues.includes(opt.value)
74
+ );
75
+ setFilteredOptions(opts);
76
+ }
77
+ },
78
+ [fetchOptions, staticOptions, selectedValues, getOptionLabel]
79
+ );
80
+ const handleInputChange = react.useCallback(
81
+ (e) => {
82
+ const query = e.target.value;
83
+ setInputText(query);
84
+ setIsOpen(true);
85
+ setActiveIndex(-1);
86
+ clearTimeout(debounceRef.current);
87
+ debounceRef.current = setTimeout(() => doSearch(query), DEBOUNCE_MS);
88
+ },
89
+ [doSearch]
90
+ );
91
+ const selectOption = react.useCallback(
92
+ (opt) => {
93
+ form.setFieldValue(name, [...selectedValues, opt.value]);
94
+ setInputText("");
95
+ setIsOpen(false);
96
+ setActiveIndex(-1);
97
+ },
98
+ [form, name, selectedValues]
99
+ );
100
+ const removeValue = react.useCallback(
101
+ (val) => {
102
+ form.setFieldValue(
103
+ name,
104
+ selectedValues.filter((v) => v !== val)
105
+ );
106
+ },
107
+ [form, name, selectedValues]
108
+ );
109
+ const handleKeyDown = react.useCallback(
110
+ (e) => {
111
+ if (e.key === "Backspace" && inputText === "" && selectedValues.length > 0) {
112
+ removeValue(selectedValues.at(-1));
113
+ return;
114
+ }
115
+ if (!isOpen) {
116
+ if (e.key === "ArrowDown") {
117
+ setIsOpen(true);
118
+ doSearch(inputText);
119
+ }
120
+ return;
121
+ }
122
+ switch (e.key) {
123
+ case "ArrowDown":
124
+ e.preventDefault();
125
+ setActiveIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));
126
+ break;
127
+ case "ArrowUp":
128
+ e.preventDefault();
129
+ setActiveIndex((prev) => Math.max(prev - 1, 0));
130
+ break;
131
+ case "Enter":
132
+ e.preventDefault();
133
+ if (activeIndex >= 0 && filteredOptions[activeIndex]) {
134
+ selectOption(filteredOptions[activeIndex]);
135
+ }
136
+ break;
137
+ case "Escape":
138
+ setIsOpen(false);
139
+ setActiveIndex(-1);
140
+ break;
141
+ }
142
+ },
143
+ [
144
+ isOpen,
145
+ activeIndex,
146
+ filteredOptions,
147
+ inputText,
148
+ selectedValues,
149
+ selectOption,
150
+ removeValue,
151
+ doSearch
152
+ ]
153
+ );
154
+ const handleBlur = react.useCallback(
155
+ (e) => {
156
+ setTimeout(() => {
157
+ var _a;
158
+ if (!((_a = wrapperRef.current) == null ? void 0 : _a.contains(document.activeElement))) {
159
+ setIsOpen(false);
160
+ onBlur(e);
161
+ }
162
+ }, 150);
163
+ },
164
+ [onBlur]
165
+ );
166
+ react.useEffect(() => {
167
+ return () => {
168
+ var _a;
169
+ (_a = abortRef.current) == null ? void 0 : _a.abort();
170
+ clearTimeout(debounceRef.current);
171
+ };
172
+ }, []);
173
+ const aria = fieldUtils.ariaProps(name, { error, helperText, required, label });
174
+ const listboxId = `${name}-listbox`;
175
+ const allPool = staticOptions ?? knownPoolRef.current;
176
+ const resolveLabel = (val) => {
177
+ const opt = allPool.find((o) => o.value === val);
178
+ return opt ? getOptionLabel(opt) : String(val);
179
+ };
180
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: fieldBase_module.default.wrapper, ref: wrapperRef, children: [
181
+ label && /* @__PURE__ */ jsxRuntime.jsx(
182
+ "label",
183
+ {
184
+ id: fieldUtils.labelId(name),
185
+ htmlFor: name,
186
+ className: fieldUtils.cx(fieldBase_module.default.label, required && fieldBase_module.default.labelRequired),
187
+ children: label
188
+ }
189
+ ),
190
+ /* @__PURE__ */ jsxRuntime.jsx(
191
+ "div",
192
+ {
193
+ className: fieldUtils.cx(fieldBase_module.default.input, error && fieldBase_module.default.inputError),
194
+ style: { height: "auto", padding: 0 },
195
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: AutocompleteField_module.default.chipWrap, children: [
196
+ selectedValues.map((val) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: AutocompleteField_module.default.chip, children: [
197
+ resolveLabel(val),
198
+ !disabled && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
199
+ "button",
200
+ {
201
+ type: "button",
202
+ className: AutocompleteField_module.default.chipRemove,
203
+ onClick: () => removeValue(val),
204
+ "aria-label": `Remove ${resolveLabel(val)}`,
205
+ children: "×"
206
+ }
207
+ )
208
+ ] }, val)),
209
+ /* @__PURE__ */ jsxRuntime.jsx(
210
+ "input",
211
+ {
212
+ ...aria,
213
+ type: "text",
214
+ value: inputText,
215
+ onChange: handleInputChange,
216
+ onKeyDown: handleKeyDown,
217
+ onBlur: handleBlur,
218
+ onFocus: () => {
219
+ doSearch(inputText);
220
+ setIsOpen(true);
221
+ },
222
+ placeholder: selectedValues.length === 0 ? placeholder : "",
223
+ disabled,
224
+ readOnly,
225
+ role: "combobox",
226
+ "aria-expanded": isOpen,
227
+ "aria-controls": listboxId,
228
+ "aria-activedescendant": activeIndex >= 0 ? `${name}-opt-${activeIndex}` : void 0,
229
+ "aria-autocomplete": "list",
230
+ autoComplete: "off",
231
+ style: {
232
+ border: "none",
233
+ outline: "none",
234
+ flex: 1,
235
+ minWidth: "60px",
236
+ padding: "var(--axen-space-xs)",
237
+ background: "transparent"
238
+ }
239
+ }
240
+ ),
241
+ loading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: AutocompleteField_module.default.spinner, "aria-hidden": "true" })
242
+ ] })
243
+ }
244
+ ),
245
+ isOpen && filteredOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
246
+ "div",
247
+ {
248
+ id: listboxId,
249
+ role: "listbox",
250
+ className: AutocompleteField_module.default.dropdown,
251
+ "aria-multiselectable": "true",
252
+ children: filteredOptions.map((opt, i) => /* @__PURE__ */ jsxRuntime.jsx(
253
+ "div",
254
+ {
255
+ id: `${name}-opt-${i}`,
256
+ role: "option",
257
+ tabIndex: -1,
258
+ "aria-selected": i === activeIndex,
259
+ "aria-disabled": opt.disabled,
260
+ className: fieldUtils.cx(
261
+ AutocompleteField_module.default.option,
262
+ i === activeIndex && AutocompleteField_module.default.optionActive,
263
+ opt.disabled && AutocompleteField_module.default.optionDisabled
264
+ ),
265
+ onMouseDown: (e) => {
266
+ e.preventDefault();
267
+ if (!opt.disabled) selectOption(opt);
268
+ },
269
+ children: getOptionLabel(opt)
270
+ },
271
+ opt.value
272
+ ))
273
+ }
274
+ ),
275
+ helperText && /* @__PURE__ */ jsxRuntime.jsx(
276
+ "span",
277
+ {
278
+ id: fieldUtils.helperId(name),
279
+ className: fieldUtils.cx(fieldBase_module.default.helperText, error && fieldBase_module.default.helperTextError),
280
+ role: error ? "alert" : void 0,
281
+ children: helperText
282
+ }
283
+ )
284
+ ] });
285
+ }
286
+ exports.AutocompleteMultiField = AutocompleteMultiField;
@@ -0,0 +1,6 @@
1
+ import { AutocompleteOption, FieldComponentProps } from '../../types';
2
+ export declare function AutocompleteMultiField({ name, value, onChange: _onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, options: staticOptions, fetchOptions, optionLabel, form, }: FieldComponentProps & {
3
+ fetchOptions?: (query: string, signal?: AbortSignal) => Promise<AutocompleteOption[]>;
4
+ optionLabel?: string;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=AutocompleteMultiField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutocompleteMultiField.d.ts","sourceRoot":"","sources":["../../../src/fields/AutocompleteMultiField/AutocompleteMultiField.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAO3E,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,KAAK,EACL,QAAQ,EAAE,SAAS,EACnB,MAAM,EACN,KAAK,EACL,UAAU,EACV,KAAK,EACL,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,OAAO,EAAE,aAAa,EACtB,YAAY,EACZ,WAAW,EACX,IAAI,GACL,EAAE,mBAAmB,GAAG;IACvB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,2CAsRA"}
@@ -0,0 +1,286 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useCallback, useEffect } from "react";
3
+ import localStyles from "../AutocompleteField/AutocompleteField.module.css.js";
4
+ import styles from "../fieldBase.module.css.js";
5
+ import { ariaProps, cx, labelId, helperId } from "../fieldUtils.js";
6
+ const DEBOUNCE_MS = 400;
7
+ function AutocompleteMultiField({
8
+ name,
9
+ value,
10
+ onChange: _onChange,
11
+ onBlur,
12
+ error,
13
+ helperText,
14
+ label,
15
+ placeholder,
16
+ disabled,
17
+ readOnly,
18
+ required,
19
+ options: staticOptions,
20
+ fetchOptions,
21
+ optionLabel,
22
+ form
23
+ }) {
24
+ const [inputText, setInputText] = useState("");
25
+ const [filteredOptions, setFilteredOptions] = useState([]);
26
+ const [isOpen, setIsOpen] = useState(false);
27
+ const [activeIndex, setActiveIndex] = useState(-1);
28
+ const [loading, setLoading] = useState(false);
29
+ const abortRef = useRef(null);
30
+ const debounceRef = useRef(void 0);
31
+ const knownPoolRef = useRef(staticOptions ?? []);
32
+ const wrapperRef = useRef(null);
33
+ const selectedValues = Array.isArray(value) ? value : [];
34
+ const getOptionLabel = useCallback(
35
+ (opt) => {
36
+ if (optionLabel) {
37
+ const val = opt[optionLabel];
38
+ return typeof val === "string" || typeof val === "number" ? String(val) : opt.label;
39
+ }
40
+ return opt.label;
41
+ },
42
+ [optionLabel]
43
+ );
44
+ const doSearch = useCallback(
45
+ (query) => {
46
+ var _a;
47
+ if (fetchOptions) {
48
+ (_a = abortRef.current) == null ? void 0 : _a.abort();
49
+ const controller = new AbortController();
50
+ abortRef.current = controller;
51
+ setLoading(true);
52
+ fetchOptions(query, controller.signal).then((results) => {
53
+ if (!controller.signal.aborted) {
54
+ for (const r of results) {
55
+ if (!knownPoolRef.current.some((k) => k.value === r.value)) {
56
+ knownPoolRef.current.push(r);
57
+ }
58
+ }
59
+ setFilteredOptions(results.filter((o) => !selectedValues.includes(o.value)));
60
+ setLoading(false);
61
+ }
62
+ }).catch((err) => {
63
+ if (!controller.signal.aborted && err.name !== "AbortError") {
64
+ setFilteredOptions([]);
65
+ setLoading(false);
66
+ }
67
+ });
68
+ } else {
69
+ const q = query.toLowerCase();
70
+ const opts = (staticOptions ?? []).filter(
71
+ (opt) => getOptionLabel(opt).toLowerCase().includes(q) && !selectedValues.includes(opt.value)
72
+ );
73
+ setFilteredOptions(opts);
74
+ }
75
+ },
76
+ [fetchOptions, staticOptions, selectedValues, getOptionLabel]
77
+ );
78
+ const handleInputChange = useCallback(
79
+ (e) => {
80
+ const query = e.target.value;
81
+ setInputText(query);
82
+ setIsOpen(true);
83
+ setActiveIndex(-1);
84
+ clearTimeout(debounceRef.current);
85
+ debounceRef.current = setTimeout(() => doSearch(query), DEBOUNCE_MS);
86
+ },
87
+ [doSearch]
88
+ );
89
+ const selectOption = useCallback(
90
+ (opt) => {
91
+ form.setFieldValue(name, [...selectedValues, opt.value]);
92
+ setInputText("");
93
+ setIsOpen(false);
94
+ setActiveIndex(-1);
95
+ },
96
+ [form, name, selectedValues]
97
+ );
98
+ const removeValue = useCallback(
99
+ (val) => {
100
+ form.setFieldValue(
101
+ name,
102
+ selectedValues.filter((v) => v !== val)
103
+ );
104
+ },
105
+ [form, name, selectedValues]
106
+ );
107
+ const handleKeyDown = useCallback(
108
+ (e) => {
109
+ if (e.key === "Backspace" && inputText === "" && selectedValues.length > 0) {
110
+ removeValue(selectedValues.at(-1));
111
+ return;
112
+ }
113
+ if (!isOpen) {
114
+ if (e.key === "ArrowDown") {
115
+ setIsOpen(true);
116
+ doSearch(inputText);
117
+ }
118
+ return;
119
+ }
120
+ switch (e.key) {
121
+ case "ArrowDown":
122
+ e.preventDefault();
123
+ setActiveIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));
124
+ break;
125
+ case "ArrowUp":
126
+ e.preventDefault();
127
+ setActiveIndex((prev) => Math.max(prev - 1, 0));
128
+ break;
129
+ case "Enter":
130
+ e.preventDefault();
131
+ if (activeIndex >= 0 && filteredOptions[activeIndex]) {
132
+ selectOption(filteredOptions[activeIndex]);
133
+ }
134
+ break;
135
+ case "Escape":
136
+ setIsOpen(false);
137
+ setActiveIndex(-1);
138
+ break;
139
+ }
140
+ },
141
+ [
142
+ isOpen,
143
+ activeIndex,
144
+ filteredOptions,
145
+ inputText,
146
+ selectedValues,
147
+ selectOption,
148
+ removeValue,
149
+ doSearch
150
+ ]
151
+ );
152
+ const handleBlur = useCallback(
153
+ (e) => {
154
+ setTimeout(() => {
155
+ var _a;
156
+ if (!((_a = wrapperRef.current) == null ? void 0 : _a.contains(document.activeElement))) {
157
+ setIsOpen(false);
158
+ onBlur(e);
159
+ }
160
+ }, 150);
161
+ },
162
+ [onBlur]
163
+ );
164
+ useEffect(() => {
165
+ return () => {
166
+ var _a;
167
+ (_a = abortRef.current) == null ? void 0 : _a.abort();
168
+ clearTimeout(debounceRef.current);
169
+ };
170
+ }, []);
171
+ const aria = ariaProps(name, { error, helperText, required, label });
172
+ const listboxId = `${name}-listbox`;
173
+ const allPool = staticOptions ?? knownPoolRef.current;
174
+ const resolveLabel = (val) => {
175
+ const opt = allPool.find((o) => o.value === val);
176
+ return opt ? getOptionLabel(opt) : String(val);
177
+ };
178
+ return /* @__PURE__ */ jsxs("div", { className: styles.wrapper, ref: wrapperRef, children: [
179
+ label && /* @__PURE__ */ jsx(
180
+ "label",
181
+ {
182
+ id: labelId(name),
183
+ htmlFor: name,
184
+ className: cx(styles.label, required && styles.labelRequired),
185
+ children: label
186
+ }
187
+ ),
188
+ /* @__PURE__ */ jsx(
189
+ "div",
190
+ {
191
+ className: cx(styles.input, error && styles.inputError),
192
+ style: { height: "auto", padding: 0 },
193
+ children: /* @__PURE__ */ jsxs("div", { className: localStyles.chipWrap, children: [
194
+ selectedValues.map((val) => /* @__PURE__ */ jsxs("span", { className: localStyles.chip, children: [
195
+ resolveLabel(val),
196
+ !disabled && !readOnly && /* @__PURE__ */ jsx(
197
+ "button",
198
+ {
199
+ type: "button",
200
+ className: localStyles.chipRemove,
201
+ onClick: () => removeValue(val),
202
+ "aria-label": `Remove ${resolveLabel(val)}`,
203
+ children: "×"
204
+ }
205
+ )
206
+ ] }, val)),
207
+ /* @__PURE__ */ jsx(
208
+ "input",
209
+ {
210
+ ...aria,
211
+ type: "text",
212
+ value: inputText,
213
+ onChange: handleInputChange,
214
+ onKeyDown: handleKeyDown,
215
+ onBlur: handleBlur,
216
+ onFocus: () => {
217
+ doSearch(inputText);
218
+ setIsOpen(true);
219
+ },
220
+ placeholder: selectedValues.length === 0 ? placeholder : "",
221
+ disabled,
222
+ readOnly,
223
+ role: "combobox",
224
+ "aria-expanded": isOpen,
225
+ "aria-controls": listboxId,
226
+ "aria-activedescendant": activeIndex >= 0 ? `${name}-opt-${activeIndex}` : void 0,
227
+ "aria-autocomplete": "list",
228
+ autoComplete: "off",
229
+ style: {
230
+ border: "none",
231
+ outline: "none",
232
+ flex: 1,
233
+ minWidth: "60px",
234
+ padding: "var(--axen-space-xs)",
235
+ background: "transparent"
236
+ }
237
+ }
238
+ ),
239
+ loading && /* @__PURE__ */ jsx("span", { className: localStyles.spinner, "aria-hidden": "true" })
240
+ ] })
241
+ }
242
+ ),
243
+ isOpen && filteredOptions.length > 0 && /* @__PURE__ */ jsx(
244
+ "div",
245
+ {
246
+ id: listboxId,
247
+ role: "listbox",
248
+ className: localStyles.dropdown,
249
+ "aria-multiselectable": "true",
250
+ children: filteredOptions.map((opt, i) => /* @__PURE__ */ jsx(
251
+ "div",
252
+ {
253
+ id: `${name}-opt-${i}`,
254
+ role: "option",
255
+ tabIndex: -1,
256
+ "aria-selected": i === activeIndex,
257
+ "aria-disabled": opt.disabled,
258
+ className: cx(
259
+ localStyles.option,
260
+ i === activeIndex && localStyles.optionActive,
261
+ opt.disabled && localStyles.optionDisabled
262
+ ),
263
+ onMouseDown: (e) => {
264
+ e.preventDefault();
265
+ if (!opt.disabled) selectOption(opt);
266
+ },
267
+ children: getOptionLabel(opt)
268
+ },
269
+ opt.value
270
+ ))
271
+ }
272
+ ),
273
+ helperText && /* @__PURE__ */ jsx(
274
+ "span",
275
+ {
276
+ id: helperId(name),
277
+ className: cx(styles.helperText, error && styles.helperTextError),
278
+ role: error ? "alert" : void 0,
279
+ children: helperText
280
+ }
281
+ )
282
+ ] });
283
+ }
284
+ export {
285
+ AutocompleteMultiField
286
+ };