@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,242 @@
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 fieldBase_module = require("../fieldBase.module.css.cjs");
6
+ const fieldUtils = require("../fieldUtils.cjs");
7
+ const AutocompleteField_module = require("./AutocompleteField.module.css.cjs");
8
+ const DEBOUNCE_MS = 400;
9
+ function AutocompleteField({
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
+ staticOptions ?? []
29
+ );
30
+ const [isOpen, setIsOpen] = react.useState(false);
31
+ const [activeIndex, setActiveIndex] = react.useState(-1);
32
+ const [loading, setLoading] = react.useState(false);
33
+ const abortRef = react.useRef(null);
34
+ const debounceRef = react.useRef(void 0);
35
+ const listRef = react.useRef(null);
36
+ const wrapperRef = react.useRef(null);
37
+ const getOptionLabel = react.useCallback(
38
+ (opt) => {
39
+ if (optionLabel) {
40
+ const val = opt[optionLabel];
41
+ return typeof val === "string" || typeof val === "number" ? String(val) : opt.label;
42
+ }
43
+ return opt.label;
44
+ },
45
+ [optionLabel]
46
+ );
47
+ react.useEffect(() => {
48
+ if (value != null && value !== "") {
49
+ const allOpts = staticOptions ?? filteredOptions;
50
+ const match = allOpts.find((o) => o.value === value);
51
+ if (match) setInputText(getOptionLabel(match));
52
+ } else {
53
+ setInputText("");
54
+ }
55
+ }, [value]);
56
+ const doSearch = react.useCallback(
57
+ (query) => {
58
+ var _a;
59
+ if (fetchOptions) {
60
+ (_a = abortRef.current) == null ? void 0 : _a.abort();
61
+ const controller = new AbortController();
62
+ abortRef.current = controller;
63
+ setLoading(true);
64
+ fetchOptions(query, controller.signal).then((results) => {
65
+ if (!controller.signal.aborted) {
66
+ setFilteredOptions(results);
67
+ setLoading(false);
68
+ }
69
+ }).catch((err) => {
70
+ if (!controller.signal.aborted && err.name !== "AbortError") {
71
+ setFilteredOptions([]);
72
+ setLoading(false);
73
+ }
74
+ });
75
+ } else {
76
+ const q = query.toLowerCase();
77
+ const filtered = (staticOptions ?? []).filter(
78
+ (opt) => getOptionLabel(opt).toLowerCase().includes(q)
79
+ );
80
+ setFilteredOptions(filtered);
81
+ }
82
+ },
83
+ [fetchOptions, staticOptions, getOptionLabel]
84
+ );
85
+ const handleInputChange = react.useCallback(
86
+ (e) => {
87
+ const query = e.target.value;
88
+ setInputText(query);
89
+ setIsOpen(true);
90
+ setActiveIndex(-1);
91
+ form.setFieldValue(name, "");
92
+ clearTimeout(debounceRef.current);
93
+ debounceRef.current = setTimeout(() => doSearch(query), DEBOUNCE_MS);
94
+ },
95
+ [form, name, doSearch]
96
+ );
97
+ const selectOption = react.useCallback(
98
+ (opt) => {
99
+ form.setFieldValue(name, opt.value);
100
+ setInputText(getOptionLabel(opt));
101
+ setIsOpen(false);
102
+ setActiveIndex(-1);
103
+ },
104
+ [form, name, getOptionLabel]
105
+ );
106
+ const handleKeyDown = react.useCallback(
107
+ (e) => {
108
+ if (!isOpen) {
109
+ if (e.key === "ArrowDown") {
110
+ setIsOpen(true);
111
+ doSearch(inputText);
112
+ }
113
+ return;
114
+ }
115
+ switch (e.key) {
116
+ case "ArrowDown":
117
+ e.preventDefault();
118
+ setActiveIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));
119
+ break;
120
+ case "ArrowUp":
121
+ e.preventDefault();
122
+ setActiveIndex((prev) => Math.max(prev - 1, 0));
123
+ break;
124
+ case "Enter":
125
+ e.preventDefault();
126
+ if (activeIndex >= 0 && filteredOptions[activeIndex]) {
127
+ selectOption(filteredOptions[activeIndex]);
128
+ }
129
+ break;
130
+ case "Escape":
131
+ setIsOpen(false);
132
+ setActiveIndex(-1);
133
+ break;
134
+ }
135
+ },
136
+ [isOpen, activeIndex, filteredOptions, inputText, selectOption, doSearch]
137
+ );
138
+ const handleBlur = react.useCallback(
139
+ (e) => {
140
+ setTimeout(() => {
141
+ var _a;
142
+ if (!((_a = wrapperRef.current) == null ? void 0 : _a.contains(document.activeElement))) {
143
+ setIsOpen(false);
144
+ onBlur(e);
145
+ }
146
+ }, 150);
147
+ },
148
+ [onBlur]
149
+ );
150
+ react.useEffect(() => {
151
+ return () => {
152
+ var _a;
153
+ (_a = abortRef.current) == null ? void 0 : _a.abort();
154
+ clearTimeout(debounceRef.current);
155
+ };
156
+ }, []);
157
+ const aria = fieldUtils.ariaProps(name, { error, helperText, required, label });
158
+ const listboxId = `${name}-listbox`;
159
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: fieldBase_module.default.wrapper, ref: wrapperRef, children: [
160
+ label && /* @__PURE__ */ jsxRuntime.jsx(
161
+ "label",
162
+ {
163
+ id: fieldUtils.labelId(name),
164
+ htmlFor: name,
165
+ className: fieldUtils.cx(fieldBase_module.default.label, required && fieldBase_module.default.labelRequired),
166
+ children: label
167
+ }
168
+ ),
169
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: AutocompleteField_module.default.inputWrap, children: [
170
+ /* @__PURE__ */ jsxRuntime.jsx(
171
+ "input",
172
+ {
173
+ ...aria,
174
+ type: "text",
175
+ name,
176
+ value: inputText,
177
+ onChange: handleInputChange,
178
+ onKeyDown: handleKeyDown,
179
+ onBlur: handleBlur,
180
+ onFocus: () => {
181
+ if (inputText) {
182
+ doSearch(inputText);
183
+ }
184
+ setIsOpen(true);
185
+ },
186
+ placeholder,
187
+ disabled,
188
+ readOnly,
189
+ role: "combobox",
190
+ "aria-expanded": isOpen,
191
+ "aria-controls": listboxId,
192
+ "aria-activedescendant": activeIndex >= 0 ? `${name}-opt-${activeIndex}` : void 0,
193
+ "aria-autocomplete": "list",
194
+ autoComplete: "off",
195
+ className: fieldUtils.cx(fieldBase_module.default.input, error && fieldBase_module.default.inputError)
196
+ }
197
+ ),
198
+ loading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: AutocompleteField_module.default.spinner, "aria-hidden": "true" })
199
+ ] }),
200
+ isOpen && filteredOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
201
+ "div",
202
+ {
203
+ id: listboxId,
204
+ ref: listRef,
205
+ role: "listbox",
206
+ className: AutocompleteField_module.default.dropdown,
207
+ children: filteredOptions.map((opt, i) => /* @__PURE__ */ jsxRuntime.jsx(
208
+ "div",
209
+ {
210
+ id: `${name}-opt-${i}`,
211
+ role: "option",
212
+ tabIndex: -1,
213
+ "aria-selected": i === activeIndex,
214
+ "aria-disabled": opt.disabled,
215
+ className: fieldUtils.cx(
216
+ AutocompleteField_module.default.option,
217
+ i === activeIndex && AutocompleteField_module.default.optionActive,
218
+ opt.disabled && AutocompleteField_module.default.optionDisabled
219
+ ),
220
+ onMouseDown: (e) => {
221
+ e.preventDefault();
222
+ if (!opt.disabled) selectOption(opt);
223
+ },
224
+ children: getOptionLabel(opt)
225
+ },
226
+ opt.value
227
+ ))
228
+ }
229
+ ),
230
+ isOpen && filteredOptions.length === 0 && inputText && !loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: AutocompleteField_module.default.noResults, children: "No results found" }),
231
+ helperText && /* @__PURE__ */ jsxRuntime.jsx(
232
+ "span",
233
+ {
234
+ id: fieldUtils.helperId(name),
235
+ className: fieldUtils.cx(fieldBase_module.default.helperText, error && fieldBase_module.default.helperTextError),
236
+ role: error ? "alert" : void 0,
237
+ children: helperText
238
+ }
239
+ )
240
+ ] });
241
+ }
242
+ exports.AutocompleteField = AutocompleteField;
@@ -0,0 +1,6 @@
1
+ import { AutocompleteOption, FieldComponentProps } from '../../types';
2
+ export declare function AutocompleteField({ 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=AutocompleteField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AutocompleteField.d.ts","sourceRoot":"","sources":["../../../src/fields/AutocompleteField/AutocompleteField.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAO3E,wBAAgB,iBAAiB,CAAC,EAChC,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,2CAgPA"}
@@ -0,0 +1,242 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useCallback, useEffect } from "react";
3
+ import styles from "../fieldBase.module.css.js";
4
+ import { ariaProps, cx, labelId, helperId } from "../fieldUtils.js";
5
+ import localStyles from "./AutocompleteField.module.css.js";
6
+ const DEBOUNCE_MS = 400;
7
+ function AutocompleteField({
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
+ staticOptions ?? []
27
+ );
28
+ const [isOpen, setIsOpen] = useState(false);
29
+ const [activeIndex, setActiveIndex] = useState(-1);
30
+ const [loading, setLoading] = useState(false);
31
+ const abortRef = useRef(null);
32
+ const debounceRef = useRef(void 0);
33
+ const listRef = useRef(null);
34
+ const wrapperRef = useRef(null);
35
+ const getOptionLabel = useCallback(
36
+ (opt) => {
37
+ if (optionLabel) {
38
+ const val = opt[optionLabel];
39
+ return typeof val === "string" || typeof val === "number" ? String(val) : opt.label;
40
+ }
41
+ return opt.label;
42
+ },
43
+ [optionLabel]
44
+ );
45
+ useEffect(() => {
46
+ if (value != null && value !== "") {
47
+ const allOpts = staticOptions ?? filteredOptions;
48
+ const match = allOpts.find((o) => o.value === value);
49
+ if (match) setInputText(getOptionLabel(match));
50
+ } else {
51
+ setInputText("");
52
+ }
53
+ }, [value]);
54
+ const doSearch = useCallback(
55
+ (query) => {
56
+ var _a;
57
+ if (fetchOptions) {
58
+ (_a = abortRef.current) == null ? void 0 : _a.abort();
59
+ const controller = new AbortController();
60
+ abortRef.current = controller;
61
+ setLoading(true);
62
+ fetchOptions(query, controller.signal).then((results) => {
63
+ if (!controller.signal.aborted) {
64
+ setFilteredOptions(results);
65
+ setLoading(false);
66
+ }
67
+ }).catch((err) => {
68
+ if (!controller.signal.aborted && err.name !== "AbortError") {
69
+ setFilteredOptions([]);
70
+ setLoading(false);
71
+ }
72
+ });
73
+ } else {
74
+ const q = query.toLowerCase();
75
+ const filtered = (staticOptions ?? []).filter(
76
+ (opt) => getOptionLabel(opt).toLowerCase().includes(q)
77
+ );
78
+ setFilteredOptions(filtered);
79
+ }
80
+ },
81
+ [fetchOptions, staticOptions, getOptionLabel]
82
+ );
83
+ const handleInputChange = useCallback(
84
+ (e) => {
85
+ const query = e.target.value;
86
+ setInputText(query);
87
+ setIsOpen(true);
88
+ setActiveIndex(-1);
89
+ form.setFieldValue(name, "");
90
+ clearTimeout(debounceRef.current);
91
+ debounceRef.current = setTimeout(() => doSearch(query), DEBOUNCE_MS);
92
+ },
93
+ [form, name, doSearch]
94
+ );
95
+ const selectOption = useCallback(
96
+ (opt) => {
97
+ form.setFieldValue(name, opt.value);
98
+ setInputText(getOptionLabel(opt));
99
+ setIsOpen(false);
100
+ setActiveIndex(-1);
101
+ },
102
+ [form, name, getOptionLabel]
103
+ );
104
+ const handleKeyDown = useCallback(
105
+ (e) => {
106
+ if (!isOpen) {
107
+ if (e.key === "ArrowDown") {
108
+ setIsOpen(true);
109
+ doSearch(inputText);
110
+ }
111
+ return;
112
+ }
113
+ switch (e.key) {
114
+ case "ArrowDown":
115
+ e.preventDefault();
116
+ setActiveIndex((prev) => Math.min(prev + 1, filteredOptions.length - 1));
117
+ break;
118
+ case "ArrowUp":
119
+ e.preventDefault();
120
+ setActiveIndex((prev) => Math.max(prev - 1, 0));
121
+ break;
122
+ case "Enter":
123
+ e.preventDefault();
124
+ if (activeIndex >= 0 && filteredOptions[activeIndex]) {
125
+ selectOption(filteredOptions[activeIndex]);
126
+ }
127
+ break;
128
+ case "Escape":
129
+ setIsOpen(false);
130
+ setActiveIndex(-1);
131
+ break;
132
+ }
133
+ },
134
+ [isOpen, activeIndex, filteredOptions, inputText, selectOption, doSearch]
135
+ );
136
+ const handleBlur = useCallback(
137
+ (e) => {
138
+ setTimeout(() => {
139
+ var _a;
140
+ if (!((_a = wrapperRef.current) == null ? void 0 : _a.contains(document.activeElement))) {
141
+ setIsOpen(false);
142
+ onBlur(e);
143
+ }
144
+ }, 150);
145
+ },
146
+ [onBlur]
147
+ );
148
+ useEffect(() => {
149
+ return () => {
150
+ var _a;
151
+ (_a = abortRef.current) == null ? void 0 : _a.abort();
152
+ clearTimeout(debounceRef.current);
153
+ };
154
+ }, []);
155
+ const aria = ariaProps(name, { error, helperText, required, label });
156
+ const listboxId = `${name}-listbox`;
157
+ return /* @__PURE__ */ jsxs("div", { className: styles.wrapper, ref: wrapperRef, children: [
158
+ label && /* @__PURE__ */ jsx(
159
+ "label",
160
+ {
161
+ id: labelId(name),
162
+ htmlFor: name,
163
+ className: cx(styles.label, required && styles.labelRequired),
164
+ children: label
165
+ }
166
+ ),
167
+ /* @__PURE__ */ jsxs("div", { className: localStyles.inputWrap, children: [
168
+ /* @__PURE__ */ jsx(
169
+ "input",
170
+ {
171
+ ...aria,
172
+ type: "text",
173
+ name,
174
+ value: inputText,
175
+ onChange: handleInputChange,
176
+ onKeyDown: handleKeyDown,
177
+ onBlur: handleBlur,
178
+ onFocus: () => {
179
+ if (inputText) {
180
+ doSearch(inputText);
181
+ }
182
+ setIsOpen(true);
183
+ },
184
+ placeholder,
185
+ disabled,
186
+ readOnly,
187
+ role: "combobox",
188
+ "aria-expanded": isOpen,
189
+ "aria-controls": listboxId,
190
+ "aria-activedescendant": activeIndex >= 0 ? `${name}-opt-${activeIndex}` : void 0,
191
+ "aria-autocomplete": "list",
192
+ autoComplete: "off",
193
+ className: cx(styles.input, error && styles.inputError)
194
+ }
195
+ ),
196
+ loading && /* @__PURE__ */ jsx("span", { className: localStyles.spinner, "aria-hidden": "true" })
197
+ ] }),
198
+ isOpen && filteredOptions.length > 0 && /* @__PURE__ */ jsx(
199
+ "div",
200
+ {
201
+ id: listboxId,
202
+ ref: listRef,
203
+ role: "listbox",
204
+ className: localStyles.dropdown,
205
+ children: filteredOptions.map((opt, i) => /* @__PURE__ */ jsx(
206
+ "div",
207
+ {
208
+ id: `${name}-opt-${i}`,
209
+ role: "option",
210
+ tabIndex: -1,
211
+ "aria-selected": i === activeIndex,
212
+ "aria-disabled": opt.disabled,
213
+ className: cx(
214
+ localStyles.option,
215
+ i === activeIndex && localStyles.optionActive,
216
+ opt.disabled && localStyles.optionDisabled
217
+ ),
218
+ onMouseDown: (e) => {
219
+ e.preventDefault();
220
+ if (!opt.disabled) selectOption(opt);
221
+ },
222
+ children: getOptionLabel(opt)
223
+ },
224
+ opt.value
225
+ ))
226
+ }
227
+ ),
228
+ isOpen && filteredOptions.length === 0 && inputText && !loading && /* @__PURE__ */ jsx("div", { className: localStyles.noResults, children: "No results found" }),
229
+ helperText && /* @__PURE__ */ jsx(
230
+ "span",
231
+ {
232
+ id: helperId(name),
233
+ className: cx(styles.helperText, error && styles.helperTextError),
234
+ role: error ? "alert" : void 0,
235
+ children: helperText
236
+ }
237
+ )
238
+ ] });
239
+ }
240
+ export {
241
+ AutocompleteField
242
+ };
@@ -0,0 +1,168 @@
1
+ ._inputWrap_1hzxx_1 {
2
+ position: relative;
3
+ display: flex;
4
+ align-items: center;
5
+ }
6
+
7
+ ._spinner_1hzxx_7 {
8
+ position: absolute;
9
+ right: 0.75rem;
10
+ width: 16px;
11
+ height: 16px;
12
+ border: 2px solid var(--axen-color-border);
13
+ border-top-color: var(--axen-color-primary);
14
+ border-radius: 50%;
15
+ animation: _spin_1hzxx_7 0.6s linear infinite;
16
+ }
17
+
18
+ @keyframes _spin_1hzxx_7 {
19
+ to {
20
+ transform: rotate(360deg);
21
+ }
22
+ }
23
+
24
+ @media (prefers-reduced-motion: reduce) {
25
+ ._spinner_1hzxx_7 {
26
+ animation: none;
27
+ opacity: 0.6;
28
+ }
29
+ }
30
+
31
+ /* ── Dropdown ────────────────────────────────── */
32
+ ._dropdown_1hzxx_32 {
33
+ position: absolute;
34
+ z-index: var(--axen-z-dropdown);
35
+ width: 100%;
36
+ max-height: 240px;
37
+ margin: 0;
38
+ padding: var(--axen-space-xs) 0;
39
+ list-style: none;
40
+ overflow-y: auto;
41
+ background: var(--axen-color-bg);
42
+ border: var(--axen-border-width) solid var(--axen-color-border);
43
+ border-top: none;
44
+ border-radius: 0 0 var(--axen-border-radius) var(--axen-border-radius);
45
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
46
+ }
47
+
48
+ ._option_1hzxx_48 {
49
+ display: flex;
50
+ align-items: center;
51
+ padding: var(--axen-space-sm) var(--axen-field-padding-x);
52
+ font-size: var(--axen-font-size-md);
53
+ color: var(--axen-color-text);
54
+ cursor: pointer;
55
+ min-height: var(--axen-field-min-height);
56
+ transition: background-color var(--axen-transition-fast);
57
+ }
58
+
59
+ ._option_1hzxx_48:hover {
60
+ background-color: var(--axen-color-bg-hover);
61
+ }
62
+
63
+ ._optionActive_1hzxx_63 {
64
+ background-color: var(--axen-color-primary-light);
65
+ }
66
+
67
+ ._optionDisabled_1hzxx_67 {
68
+ color: var(--axen-color-text-disabled);
69
+ cursor: not-allowed;
70
+ }
71
+
72
+ ._noResults_1hzxx_72 {
73
+ padding: var(--axen-space-sm) var(--axen-field-padding-x);
74
+ font-size: var(--axen-font-size-sm);
75
+ color: var(--axen-color-text-secondary);
76
+ border: var(--axen-border-width) solid var(--axen-color-border);
77
+ border-top: none;
78
+ border-radius: 0 0 var(--axen-border-radius) var(--axen-border-radius);
79
+ background: var(--axen-color-bg);
80
+ }
81
+
82
+ /* ── Chip (used by multi) ────────────────────── */
83
+ ._chipWrap_1hzxx_83 {
84
+ display: flex;
85
+ flex-wrap: wrap;
86
+ gap: var(--axen-space-xs);
87
+ padding: var(--axen-space-xs);
88
+ }
89
+
90
+ ._chip_1hzxx_83 {
91
+ display: inline-flex;
92
+ align-items: center;
93
+ gap: var(--axen-space-xs);
94
+ padding: 2px 8px;
95
+ font-size: var(--axen-font-size-xs);
96
+ color: var(--axen-color-text);
97
+ background-color: var(--axen-color-primary-light);
98
+ border-radius: var(--axen-border-radius-pill);
99
+ max-width: 100%;
100
+ white-space: nowrap;
101
+ overflow: hidden;
102
+ text-overflow: ellipsis;
103
+ }
104
+
105
+ ._chipRemove_1hzxx_105 {
106
+ display: inline-flex;
107
+ align-items: center;
108
+ justify-content: center;
109
+ width: 16px;
110
+ height: 16px;
111
+ padding: 0;
112
+ border: none;
113
+ background: transparent;
114
+ cursor: pointer;
115
+ font-size: 12px;
116
+ color: var(--axen-color-text-secondary);
117
+ border-radius: 50%;
118
+ flex-shrink: 0;
119
+ }
120
+
121
+ ._chipRemove_1hzxx_105:hover {
122
+ background: rgba(0, 0, 0, 0.08);
123
+ color: var(--axen-color-text);
124
+ }
125
+
126
+ ._chipRemove_1hzxx_105:focus-visible {
127
+ outline: var(--axen-focus-ring-width) solid var(--axen-focus-ring-color);
128
+ }
129
+
130
+ /* ── Ghost text (predict) ────────────────────── */
131
+ ._predictWrap_1hzxx_131 {
132
+ position: relative;
133
+ display: flex;
134
+ align-items: center;
135
+ }
136
+
137
+ ._ghostText_1hzxx_137 {
138
+ position: absolute;
139
+ left: var(--axen-field-padding-x);
140
+ top: 50%;
141
+ transform: translateY(-50%);
142
+ color: var(--axen-color-text-disabled);
143
+ font-family: var(--axen-font-family);
144
+ font-size: var(--axen-font-size-md);
145
+ pointer-events: none;
146
+ white-space: nowrap;
147
+ overflow: hidden;
148
+ }
149
+
150
+ ._ghostHidden_1hzxx_150 {
151
+ visibility: hidden;
152
+ position: absolute;
153
+ white-space: pre;
154
+ font-family: var(--axen-font-family);
155
+ font-size: var(--axen-font-size-md);
156
+ }
157
+
158
+ /* ── Mobile adjustments ──────────────────────── */
159
+ @media (max-width: 599px) {
160
+ ._dropdown_1hzxx_32 {
161
+ max-height: 200px;
162
+ }
163
+
164
+ ._option_1hzxx_48 {
165
+ min-height: 48px;
166
+ padding: var(--axen-space-sm) var(--axen-space-md);
167
+ }
168
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ const inputWrap = "_inputWrap_1hzxx_1";
4
+ const spinner = "_spinner_1hzxx_7";
5
+ const dropdown = "_dropdown_1hzxx_32";
6
+ const option = "_option_1hzxx_48";
7
+ const optionActive = "_optionActive_1hzxx_63";
8
+ const optionDisabled = "_optionDisabled_1hzxx_67";
9
+ const noResults = "_noResults_1hzxx_72";
10
+ const chipWrap = "_chipWrap_1hzxx_83";
11
+ const chip = "_chip_1hzxx_83";
12
+ const chipRemove = "_chipRemove_1hzxx_105";
13
+ const predictWrap = "_predictWrap_1hzxx_131";
14
+ const ghostText = "_ghostText_1hzxx_137";
15
+ const ghostHidden = "_ghostHidden_1hzxx_150";
16
+ const localStyles = {
17
+ inputWrap,
18
+ spinner,
19
+ dropdown,
20
+ option,
21
+ optionActive,
22
+ optionDisabled,
23
+ noResults,
24
+ chipWrap,
25
+ chip,
26
+ chipRemove,
27
+ predictWrap,
28
+ ghostText,
29
+ ghostHidden
30
+ };
31
+ exports.chip = chip;
32
+ exports.chipRemove = chipRemove;
33
+ exports.chipWrap = chipWrap;
34
+ exports.default = localStyles;
35
+ exports.dropdown = dropdown;
36
+ exports.ghostHidden = ghostHidden;
37
+ exports.ghostText = ghostText;
38
+ exports.inputWrap = inputWrap;
39
+ exports.noResults = noResults;
40
+ exports.option = option;
41
+ exports.optionActive = optionActive;
42
+ exports.optionDisabled = optionDisabled;
43
+ exports.predictWrap = predictWrap;
44
+ exports.spinner = spinner;