@tachui/forms 0.7.0-alpha1

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 (62) hide show
  1. package/LICENSE +363 -0
  2. package/dist/Form-ueYEcSg1.cjs +2 -0
  3. package/dist/Form-ueYEcSg1.cjs.map +1 -0
  4. package/dist/Form-ylAr3o_e.js +376 -0
  5. package/dist/Form-ylAr3o_e.js.map +1 -0
  6. package/dist/components/Form.d.ts +76 -0
  7. package/dist/components/Form.d.ts.map +1 -0
  8. package/dist/components/index.cjs +2 -0
  9. package/dist/components/index.cjs.map +1 -0
  10. package/dist/components/index.d.ts +9 -0
  11. package/dist/components/index.d.ts.map +1 -0
  12. package/dist/components/index.js +31 -0
  13. package/dist/components/index.js.map +1 -0
  14. package/dist/components/input/Checkbox.d.ts +42 -0
  15. package/dist/components/input/Checkbox.d.ts.map +1 -0
  16. package/dist/components/input/Radio.d.ts +36 -0
  17. package/dist/components/input/Radio.d.ts.map +1 -0
  18. package/dist/components/input/Select.d.ts +21 -0
  19. package/dist/components/input/Select.d.ts.map +1 -0
  20. package/dist/components/input/TextField.d.ts +58 -0
  21. package/dist/components/input/TextField.d.ts.map +1 -0
  22. package/dist/components/input/index.d.ts +11 -0
  23. package/dist/components/input/index.d.ts.map +1 -0
  24. package/dist/forms-complex-BiQsZZlT.js +361 -0
  25. package/dist/forms-complex-BiQsZZlT.js.map +1 -0
  26. package/dist/forms-complex-DLEnXXJ5.cjs +2 -0
  27. package/dist/forms-complex-DLEnXXJ5.cjs.map +1 -0
  28. package/dist/forms-core-B1bx1drO.js +839 -0
  29. package/dist/forms-core-B1bx1drO.js.map +1 -0
  30. package/dist/forms-core-W_JGVLAI.cjs +9 -0
  31. package/dist/forms-core-W_JGVLAI.cjs.map +1 -0
  32. package/dist/forms-inputs-6QdeMWFk.js +1075 -0
  33. package/dist/forms-inputs-6QdeMWFk.js.map +1 -0
  34. package/dist/forms-inputs-DQ5QI_SU.cjs +2 -0
  35. package/dist/forms-inputs-DQ5QI_SU.cjs.map +1 -0
  36. package/dist/index.cjs +2 -0
  37. package/dist/index.cjs.map +1 -0
  38. package/dist/index.d.ts +21 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +383 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/state/index.cjs +2 -0
  43. package/dist/state/index.cjs.map +1 -0
  44. package/dist/state/index.d.ts +46 -0
  45. package/dist/state/index.d.ts.map +1 -0
  46. package/dist/state/index.js +9 -0
  47. package/dist/state/index.js.map +1 -0
  48. package/dist/types/index.d.ts +452 -0
  49. package/dist/types/index.d.ts.map +1 -0
  50. package/dist/utils/formatters.d.ts +98 -0
  51. package/dist/utils/formatters.d.ts.map +1 -0
  52. package/dist/utils/validators.d.ts +101 -0
  53. package/dist/utils/validators.d.ts.map +1 -0
  54. package/dist/validation/component-validation.d.ts +52 -0
  55. package/dist/validation/component-validation.d.ts.map +1 -0
  56. package/dist/validation/index.cjs +2 -0
  57. package/dist/validation/index.cjs.map +1 -0
  58. package/dist/validation/index.d.ts +141 -0
  59. package/dist/validation/index.d.ts.map +1 -0
  60. package/dist/validation/index.js +21 -0
  61. package/dist/validation/index.js.map +1 -0
  62. package/package.json +65 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Select/Picker Component
3
+ *
4
+ * SwiftUI-inspired select component with search, multiple selection,
5
+ * async options loading, and comprehensive accessibility support.
6
+ */
7
+ import type { Component } from '@tachui/core';
8
+ import type { SelectProps } from '../../types';
9
+ /**
10
+ * Select component implementation
11
+ */
12
+ export declare const Select: Component<SelectProps>;
13
+ /**
14
+ * MultiSelect variant for clearer multiple selection intent
15
+ */
16
+ export declare const MultiSelect: Component<SelectProps>;
17
+ /**
18
+ * Combobox variant with always-searchable behavior
19
+ */
20
+ export declare const Combobox: Component<SelectProps>;
21
+ //# sourceMappingURL=Select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/input/Select.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAqB,MAAM,cAAc,CAAA;AAGhE,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,aAAa,CAAA;AAE5D;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,SAAS,CAAC,WAAW,CA+iBzC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,WAAW,CAE9C,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,CAAC,WAAW,CAE3C,CAAA"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * TextField Component - Enhanced
3
+ *
4
+ * SwiftUI-inspired text input with validation, formatting,
5
+ * reactive props, and comprehensive accessibility support.
6
+ *
7
+ * Now includes all core TextField features:
8
+ * - Advanced input types (date, time, color, etc.)
9
+ * - Signal-based reactive props
10
+ * - Formatting and parsing
11
+ * - Mobile/accessibility features
12
+ * - Typography control
13
+ */
14
+ import type { Component } from '@tachui/core';
15
+ import type { TextFieldProps } from '../../types';
16
+ /**
17
+ * Enhanced TextField component implementation
18
+ */
19
+ export declare const TextField: Component<TextFieldProps>;
20
+ export declare const EmailField: Component<TextFieldProps & {
21
+ validation?: TextFieldProps['validation'];
22
+ }>;
23
+ export declare const PasswordField: Component<TextFieldProps & {
24
+ validation?: TextFieldProps['validation'];
25
+ showStrengthIndicator?: boolean;
26
+ strongValidation?: boolean;
27
+ }>;
28
+ export declare const SearchField: Component<TextFieldProps>;
29
+ export declare const URLField: Component<TextFieldProps & {
30
+ validation?: TextFieldProps['validation'];
31
+ }>;
32
+ export declare const PhoneField: Component<TextFieldProps & {
33
+ validation?: TextFieldProps['validation'];
34
+ format?: 'us' | 'international';
35
+ }>;
36
+ export declare const NumberField: Component<TextFieldProps & {
37
+ min?: number;
38
+ max?: number;
39
+ precision?: number;
40
+ currency?: boolean;
41
+ }>;
42
+ export declare const CreditCardField: Component<TextFieldProps & {
43
+ validation?: TextFieldProps['validation'];
44
+ }>;
45
+ export declare const SSNField: Component<TextFieldProps & {
46
+ validation?: TextFieldProps['validation'];
47
+ }>;
48
+ export declare const PostalCodeField: Component<TextFieldProps & {
49
+ validation?: TextFieldProps['validation'];
50
+ }>;
51
+ export declare const TextArea: Component<TextFieldProps>;
52
+ export declare const DateField: Component<TextFieldProps & {
53
+ min?: string;
54
+ max?: string;
55
+ }>;
56
+ export declare const TimeField: Component<TextFieldProps>;
57
+ export declare const ColorField: Component<TextFieldProps>;
58
+ //# sourceMappingURL=TextField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextField.d.ts","sourceRoot":"","sources":["../../../src/components/input/TextField.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAA6B,MAAM,cAAc,CAAA;AAGxE,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAA;AAYjE;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,cAAc,CAqZ/C,CAAA;AASD,eAAO,MAAM,UAAU,EAAE,SAAS,CAChC,cAAc,GAAG;IACf,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;CAC1C,CAcF,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,CACnC,cAAc,GAAG;IACf,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;IACzC,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,CA6BF,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,CAAC,cAAc,CASjD,CAAA;AAED,eAAO,MAAM,QAAQ,EAAE,SAAS,CAC9B,cAAc,GAAG;IACf,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;CAC1C,CAaF,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,SAAS,CAChC,cAAc,GAAG;IACf,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;IACzC,MAAM,CAAC,EAAE,IAAI,GAAG,eAAe,CAAA;CAChC,CAiBF,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,CACjC,cAAc,GAAG;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAiCF,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,CACrC,cAAc,GAAG;IACf,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;CAC1C,CAgBF,CAAA;AAED,eAAO,MAAM,QAAQ,EAAE,SAAS,CAC9B,cAAc,GAAG;IACf,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;CAC1C,CAgBF,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,CACrC,cAAc,GAAG;IACf,UAAU,CAAC,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;CAC1C,CAgBF,CAAA;AAED,eAAO,MAAM,QAAQ,EAAE,SAAS,CAAC,cAAc,CAM9C,CAAA;AAGD,eAAO,MAAM,SAAS,EAAE,SAAS,CAC/B,cAAc,GAAG;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAwBF,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,cAAc,CAW/C,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,SAAS,CAAC,cAAc,CAMhD,CAAA"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * TachUI Forms - Input Components
3
+ *
4
+ * All form input components with SwiftUI-inspired APIs
5
+ */
6
+ export type { AutoCapitalization, CheckboxProps, KeyboardType, RadioProps, ReturnKeyType, SelectProps, TextFieldFormatter, TextFieldParser, TextFieldProps, TextFieldType, } from '../../types';
7
+ export { Checkbox, CheckboxGroup, Switch } from './Checkbox';
8
+ export { Radio, RadioGroup } from './Radio';
9
+ export { Combobox, MultiSelect, Select } from './Select';
10
+ export { ColorField, CreditCardField, DateField, EmailField, NumberField, PasswordField, PhoneField, PostalCodeField, SearchField, SSNField, TextArea, TextField, TimeField, URLField, } from './TextField';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/input/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,UAAU,EACV,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAC5D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAExD,OAAO,EACL,UAAU,EACV,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,aAAa,EACb,UAAU,EACV,eAAe,EACf,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,GACT,MAAM,aAAa,CAAA"}
@@ -0,0 +1,361 @@
1
+ import { createSignal as b, createEffect as Z, useLifecycle as ee, h as T, text as s, setupOutsideClickDetection as ae } from "@tachui/core";
2
+ import { c as te } from "./forms-core-B1bx1drO.js";
3
+ const j = (o) => {
4
+ const {
5
+ name: l,
6
+ label: $,
7
+ options: m,
8
+ multiple: n = !1,
9
+ searchable: u = !1,
10
+ clearable: q = !1,
11
+ placeholder: B = n ? "Select options..." : "Select an option...",
12
+ noOptionsMessage: P = "No options available",
13
+ loadingMessage: Q = "Loading...",
14
+ maxMenuHeight: _ = 200,
15
+ disabled: y = !1,
16
+ required: E = !1,
17
+ value: x,
18
+ defaultValue: K,
19
+ validation: F,
20
+ onChange: k,
21
+ onBlur: w,
22
+ onFocus: I,
23
+ error: N,
24
+ helperText: C,
25
+ ...g
26
+ } = o, c = o._formContext, t = te(l, x ?? K, F);
27
+ c && c.register(l, F);
28
+ const [i, v] = b(!1), [R, V] = b(!1), [A, D] = b(""), [p, h] = b(-1), [U] = b(!1);
29
+ x !== void 0 && Z(() => {
30
+ t.value() !== x && t.setValue(x);
31
+ });
32
+ const M = () => {
33
+ if (!u || !A())
34
+ return m;
35
+ const e = A().toLowerCase();
36
+ return m.filter(
37
+ (a) => a.label.toLowerCase().includes(e) || String(a.value).toLowerCase().includes(e)
38
+ );
39
+ }, z = () => {
40
+ const e = t.value();
41
+ if (n)
42
+ return !e || !Array.isArray(e) || e.length === 0 ? B : m.filter((r) => e.includes(r.value)).map((r) => r.label).join(", ");
43
+ {
44
+ if (e == null || e === "")
45
+ return B;
46
+ const a = m.find((r) => r.value === e);
47
+ return a ? a.label : String(e);
48
+ }
49
+ }, L = (e) => {
50
+ if (e.disabled) return;
51
+ let a;
52
+ if (n) {
53
+ const r = t.value() || [];
54
+ r.includes(e.value) ? a = r.filter((Y) => Y !== e.value) : a = [...r, e.value];
55
+ } else
56
+ a = e.value, v(!1), D("");
57
+ t.setValue(a), c && c.setValue(l, a), k && k(l, a, t);
58
+ }, S = () => {
59
+ if (y) return;
60
+ const e = !i();
61
+ v(e), e && (h(-1), u && D(""));
62
+ }, G = (e) => {
63
+ const a = e.target;
64
+ D(a.value), h(-1);
65
+ }, J = (e) => {
66
+ const a = M();
67
+ switch (e.key) {
68
+ case "Enter":
69
+ e.preventDefault(), i() ? p() >= 0 && a[p()] && L(a[p()]) : S();
70
+ break;
71
+ case " ":
72
+ (!u || !i()) && (e.preventDefault(), S());
73
+ break;
74
+ case "Escape":
75
+ e.preventDefault(), v(!1), D("");
76
+ break;
77
+ case "ArrowDown":
78
+ if (e.preventDefault(), !i())
79
+ S();
80
+ else {
81
+ const r = Math.min(p() + 1, a.length - 1);
82
+ h(r);
83
+ }
84
+ break;
85
+ case "ArrowUp":
86
+ if (e.preventDefault(), i()) {
87
+ const r = Math.max(p() - 1, -1);
88
+ h(r);
89
+ }
90
+ break;
91
+ case "Home":
92
+ i() && (e.preventDefault(), h(0));
93
+ break;
94
+ case "End":
95
+ i() && (e.preventDefault(), h(a.length - 1));
96
+ break;
97
+ case "Backspace":
98
+ q && !u && t.value() !== null && (e.preventDefault(), H());
99
+ break;
100
+ }
101
+ }, W = () => {
102
+ V(!0), t.onFocus(), I && I(l, t.value());
103
+ }, X = (e) => {
104
+ requestAnimationFrame(() => {
105
+ const a = e.relatedTarget;
106
+ e.target.closest("[data-tachui-select-container]")?.contains(a) || (V(!1), v(!1), t.onBlur(), w && w(l, t.value()));
107
+ });
108
+ }, H = () => {
109
+ const e = n ? [] : null;
110
+ t.setValue(e), c && c.setValue(l, e), k && k(l, e, t);
111
+ }, O = (e) => {
112
+ const a = t.value();
113
+ return n ? Array.isArray(a) && a.includes(e.value) : a === e.value;
114
+ }, d = N || t.error() || c?.getError(l), f = {
115
+ type: "component",
116
+ id: g.id || `select-${l}`,
117
+ cleanup: [],
118
+ render: () => ({
119
+ type: "element",
120
+ tag: "div",
121
+ props: {
122
+ ...g,
123
+ class: `tachui-select ${g.class || ""}`.trim(),
124
+ "data-tachui-select-container": !0,
125
+ "data-field-state": d ? "error" : t.validating() ? "validating" : "valid",
126
+ "data-open": i(),
127
+ "data-disabled": y,
128
+ "data-multiple": n,
129
+ "data-searchable": u
130
+ },
131
+ children: [
132
+ // Label
133
+ ...$ ? [
134
+ T(
135
+ "label",
136
+ {
137
+ for: g.id || l,
138
+ "data-tachui-label": !0,
139
+ "data-required": E
140
+ },
141
+ s($),
142
+ ...E ? [
143
+ T(
144
+ "span",
145
+ {
146
+ "aria-label": "required",
147
+ "data-required-indicator": !0
148
+ },
149
+ s(" *")
150
+ )
151
+ ] : []
152
+ )
153
+ ] : [],
154
+ // Select trigger
155
+ {
156
+ type: "element",
157
+ tag: "div",
158
+ props: {
159
+ id: g.id || l,
160
+ tabindex: y ? -1 : 0,
161
+ role: "combobox",
162
+ "aria-expanded": i(),
163
+ "aria-haspopup": "listbox",
164
+ "aria-invalid": !!d,
165
+ "aria-describedby": [d ? `${l}-error` : null, C ? `${l}-helper` : null].filter(Boolean).join(" ") || void 0,
166
+ onclick: S,
167
+ onkeydown: J,
168
+ onfocus: W,
169
+ onblur: X,
170
+ "data-tachui-select-trigger": !0,
171
+ "data-focused": R(),
172
+ "data-disabled": y,
173
+ "data-error": !!d
174
+ },
175
+ children: [
176
+ // Display value
177
+ {
178
+ type: "element",
179
+ tag: "div",
180
+ props: {
181
+ "data-tachui-select-value": !0,
182
+ "data-placeholder": !t.value() || n && (!t.value() || t.value().length === 0)
183
+ },
184
+ children: [s(z())]
185
+ },
186
+ // Actions (clear, dropdown arrow)
187
+ {
188
+ type: "element",
189
+ tag: "div",
190
+ props: {
191
+ "data-tachui-select-actions": !0
192
+ },
193
+ children: [
194
+ // Clear button
195
+ ...q && t.value() && (!n || Array.isArray(t.value()) && t.value().length > 0) ? [
196
+ {
197
+ type: "element",
198
+ tag: "button",
199
+ props: {
200
+ type: "button",
201
+ onclick: (e) => {
202
+ e.stopPropagation(), H();
203
+ },
204
+ "aria-label": "Clear selection",
205
+ "data-tachui-select-clear": !0
206
+ },
207
+ children: [s("×")]
208
+ }
209
+ ] : [],
210
+ // Dropdown arrow
211
+ {
212
+ type: "element",
213
+ tag: "div",
214
+ props: {
215
+ "data-tachui-select-arrow": !0,
216
+ "data-open": i()
217
+ },
218
+ children: [s("▼")]
219
+ }
220
+ ]
221
+ }
222
+ ]
223
+ },
224
+ // Dropdown menu
225
+ ...i() ? [
226
+ {
227
+ type: "element",
228
+ tag: "div",
229
+ props: {
230
+ "data-tachui-select-dropdown": !0,
231
+ style: {
232
+ maxHeight: `${_}px`
233
+ }
234
+ },
235
+ children: [
236
+ // Search input
237
+ ...u ? [
238
+ {
239
+ type: "element",
240
+ tag: "div",
241
+ props: {
242
+ "data-tachui-select-search": !0
243
+ },
244
+ children: [
245
+ {
246
+ type: "element",
247
+ tag: "input",
248
+ props: {
249
+ type: "text",
250
+ placeholder: "Search...",
251
+ value: A(),
252
+ oninput: G,
253
+ "data-tachui-select-search-input": !0
254
+ }
255
+ }
256
+ ]
257
+ }
258
+ ] : [],
259
+ // Options list
260
+ {
261
+ type: "element",
262
+ tag: "div",
263
+ props: {
264
+ role: "listbox",
265
+ "aria-multiselectable": n,
266
+ "data-tachui-select-options": !0
267
+ },
268
+ children: M().length > 0 ? M().map((e, a) => ({
269
+ type: "element",
270
+ tag: "div",
271
+ props: {
272
+ role: "option",
273
+ "aria-selected": O(e),
274
+ "aria-disabled": e.disabled,
275
+ onclick: () => L(e),
276
+ "data-tachui-select-option": !0,
277
+ "data-selected": O(e),
278
+ "data-highlighted": p() === a,
279
+ "data-disabled": e.disabled,
280
+ "data-group": e.group
281
+ },
282
+ children: [
283
+ // Selection indicator for multiple
284
+ ...n ? [
285
+ {
286
+ type: "element",
287
+ tag: "div",
288
+ props: {
289
+ "data-tachui-select-checkbox": !0,
290
+ "data-checked": O(e)
291
+ },
292
+ children: [s(O(e) ? "✓" : "")]
293
+ }
294
+ ] : [],
295
+ // Option label
296
+ s(e.label)
297
+ ]
298
+ })) : [
299
+ {
300
+ type: "element",
301
+ tag: "div",
302
+ props: {
303
+ "data-tachui-select-no-options": !0
304
+ },
305
+ children: [s(U() ? Q : P)]
306
+ }
307
+ ]
308
+ }
309
+ ]
310
+ }
311
+ ] : [],
312
+ // Error message
313
+ ...d ? [
314
+ {
315
+ type: "element",
316
+ tag: "div",
317
+ props: {
318
+ id: `${l}-error`,
319
+ role: "alert",
320
+ "aria-live": "polite",
321
+ "data-tachui-error": !0
322
+ },
323
+ children: [s(d)]
324
+ }
325
+ ] : [],
326
+ // Helper text
327
+ ...C && !d ? [
328
+ {
329
+ type: "element",
330
+ tag: "div",
331
+ props: {
332
+ id: `${l}-helper`,
333
+ "data-tachui-helper": !0
334
+ },
335
+ children: [s(C)]
336
+ }
337
+ ] : []
338
+ ]
339
+ }),
340
+ props: o
341
+ };
342
+ return f.cleanup || (f.cleanup = []), f.cleanup.push(() => {
343
+ c && c.unregister(l);
344
+ }), ee(f, {
345
+ onDOMReady: (e, a) => {
346
+ a && ae(
347
+ f,
348
+ () => {
349
+ i() && (v(!1), V(!1), t.onBlur(), w && w(l, t.value()));
350
+ },
351
+ "[data-tachui-select-container]"
352
+ );
353
+ }
354
+ }), f;
355
+ }, ie = (o) => j({ ...o, multiple: !0 }), ne = (o) => j({ ...o, searchable: !0 });
356
+ export {
357
+ ne as C,
358
+ ie as M,
359
+ j as S
360
+ };
361
+ //# sourceMappingURL=forms-complex-BiQsZZlT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forms-complex-BiQsZZlT.js","sources":["../src/components/input/Select.ts"],"sourcesContent":["/**\n * Select/Picker Component\n *\n * SwiftUI-inspired select component with search, multiple selection,\n * async options loading, and comprehensive accessibility support.\n */\n\nimport type { Component, ComponentInstance } from '@tachui/core'\nimport { createEffect, createSignal, h, text, useLifecycle, setupOutsideClickDetection } from '@tachui/core'\nimport { createField } from '../../state'\nimport type { SelectOption, SelectProps } from '../../types'\n\n/**\n * Select component implementation\n */\nexport const Select: Component<SelectProps> = (props) => {\n const {\n name,\n label,\n options,\n multiple = false,\n searchable = false,\n clearable = false,\n placeholder = multiple ? 'Select options...' : 'Select an option...',\n noOptionsMessage = 'No options available',\n loadingMessage = 'Loading...',\n maxMenuHeight = 200,\n disabled = false,\n required = false,\n value: controlledValue,\n defaultValue,\n validation,\n onChange,\n onBlur,\n onFocus,\n error: externalError,\n helperText,\n ...restProps\n } = props\n\n // Get form context if available\n const formContext = (props as any)._formContext\n\n // Create field state\n const field = createField(name, controlledValue ?? defaultValue, validation)\n\n // Register field with form if form context exists\n if (formContext) {\n formContext.register(name, validation)\n }\n\n const [isOpen, setIsOpen] = createSignal(false)\n const [focused, setFocused] = createSignal(false)\n const [searchQuery, setSearchQuery] = createSignal('')\n const [highlightedIndex, setHighlightedIndex] = createSignal(-1)\n const [loading] = createSignal(false)\n\n // Sync with controlled value\n if (controlledValue !== undefined) {\n createEffect(() => {\n if (field.value() !== controlledValue) {\n field.setValue(controlledValue)\n }\n })\n }\n\n // Filter options based on search query\n const filteredOptions = () => {\n if (!searchable || !searchQuery()) {\n return options\n }\n\n const query = searchQuery().toLowerCase()\n return options.filter(\n (option) =>\n option.label.toLowerCase().includes(query) ||\n String(option.value).toLowerCase().includes(query)\n )\n }\n\n // Get display value for selected option(s)\n const getDisplayValue = () => {\n const value = field.value()\n\n if (multiple) {\n if (!value || !Array.isArray(value) || value.length === 0) {\n return placeholder\n }\n\n const selectedOptions = options.filter((opt) => value.includes(opt.value))\n return selectedOptions.map((opt) => opt.label).join(', ')\n } else {\n if (value === null || value === undefined || value === '') {\n return placeholder\n }\n\n const selectedOption = options.find((opt) => opt.value === value)\n return selectedOption ? selectedOption.label : String(value)\n }\n }\n\n // Handle option selection\n const handleOptionSelect = (option: SelectOption) => {\n if (option.disabled) return\n\n let newValue: any\n\n if (multiple) {\n const currentValue = field.value() || []\n if (currentValue.includes(option.value)) {\n newValue = currentValue.filter((v: any) => v !== option.value)\n } else {\n newValue = [...currentValue, option.value]\n }\n } else {\n newValue = option.value\n setIsOpen(false)\n setSearchQuery('')\n }\n\n field.setValue(newValue)\n\n if (formContext) {\n formContext.setValue(name, newValue)\n }\n\n if (onChange) {\n onChange(name, newValue, field as any)\n }\n }\n\n // Handle dropdown toggle\n const toggleDropdown = () => {\n if (disabled) return\n\n const newOpen = !isOpen()\n setIsOpen(newOpen)\n\n if (newOpen) {\n setHighlightedIndex(-1)\n if (searchable) {\n setSearchQuery('')\n }\n }\n }\n\n // Handle search input\n const handleSearch = (event: Event) => {\n const target = event.target as HTMLInputElement\n setSearchQuery(target.value)\n setHighlightedIndex(-1)\n }\n\n // Handle keyboard navigation\n const handleKeyDown = (event: KeyboardEvent) => {\n const filtered = filteredOptions()\n\n switch (event.key) {\n case 'Enter':\n event.preventDefault()\n if (!isOpen()) {\n toggleDropdown()\n } else if (highlightedIndex() >= 0 && filtered[highlightedIndex()]) {\n handleOptionSelect(filtered[highlightedIndex()])\n }\n break\n\n case ' ':\n if (!searchable || !isOpen()) {\n event.preventDefault()\n toggleDropdown()\n }\n break\n\n case 'Escape':\n event.preventDefault()\n setIsOpen(false)\n setSearchQuery('')\n break\n\n case 'ArrowDown':\n event.preventDefault()\n if (!isOpen()) {\n toggleDropdown()\n } else {\n const nextIndex = Math.min(highlightedIndex() + 1, filtered.length - 1)\n setHighlightedIndex(nextIndex)\n }\n break\n\n case 'ArrowUp':\n event.preventDefault()\n if (isOpen()) {\n const prevIndex = Math.max(highlightedIndex() - 1, -1)\n setHighlightedIndex(prevIndex)\n }\n break\n\n case 'Home':\n if (isOpen()) {\n event.preventDefault()\n setHighlightedIndex(0)\n }\n break\n\n case 'End':\n if (isOpen()) {\n event.preventDefault()\n setHighlightedIndex(filtered.length - 1)\n }\n break\n\n case 'Backspace':\n if (clearable && !searchable && field.value() !== null) {\n event.preventDefault()\n handleClear()\n }\n break\n }\n }\n\n // Handle focus\n const handleFocus = () => {\n setFocused(true)\n field.onFocus()\n\n if (onFocus) {\n onFocus(name, field.value())\n }\n }\n\n // Handle blur\n const handleBlur = (event: FocusEvent) => {\n // ENHANCED: Use requestAnimationFrame instead of setTimeout for better performance\n requestAnimationFrame(() => {\n const relatedTarget = event.relatedTarget as Element\n const container = (event.target as Element).closest('[data-tachui-select-container]')\n\n if (!container?.contains(relatedTarget)) {\n setFocused(false)\n setIsOpen(false)\n field.onBlur()\n\n if (onBlur) {\n onBlur(name, field.value())\n }\n }\n })\n }\n\n // Handle clear\n const handleClear = () => {\n const newValue = multiple ? [] : null\n field.setValue(newValue)\n\n if (formContext) {\n formContext.setValue(name, newValue)\n }\n\n if (onChange) {\n onChange(name, newValue, field as any)\n }\n }\n\n // Check if option is selected\n const isOptionSelected = (option: SelectOption) => {\n const value = field.value()\n\n if (multiple) {\n return Array.isArray(value) && value.includes(option.value)\n }\n\n return value === option.value\n }\n\n // Determine error message\n const errorMessage = externalError || field.error() || formContext?.getError(name)\n\n const componentInstance: ComponentInstance = {\n type: 'component',\n id: restProps.id || `select-${name}`,\n cleanup: [],\n render: () => ({\n type: 'element',\n tag: 'div',\n props: {\n ...restProps,\n class: `tachui-select ${restProps.class || ''}`.trim(),\n 'data-tachui-select-container': true,\n 'data-field-state': errorMessage ? 'error' : field.validating() ? 'validating' : 'valid',\n 'data-open': isOpen(),\n 'data-disabled': disabled,\n 'data-multiple': multiple,\n 'data-searchable': searchable,\n },\n children: [\n // Label\n ...(label\n ? [\n h(\n 'label',\n {\n for: restProps.id || name,\n 'data-tachui-label': true,\n 'data-required': required,\n },\n text(label),\n ...(required\n ? [\n h(\n 'span',\n {\n 'aria-label': 'required',\n 'data-required-indicator': true,\n },\n text(' *')\n ),\n ]\n : [])\n ),\n ]\n : []),\n\n // Select trigger\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n id: restProps.id || name,\n tabindex: disabled ? -1 : 0,\n role: 'combobox',\n 'aria-expanded': isOpen(),\n 'aria-haspopup': 'listbox',\n 'aria-invalid': !!errorMessage,\n 'aria-describedby':\n [errorMessage ? `${name}-error` : null, helperText ? `${name}-helper` : null]\n .filter(Boolean)\n .join(' ') || undefined,\n onclick: toggleDropdown,\n onkeydown: handleKeyDown,\n onfocus: handleFocus,\n onblur: handleBlur,\n 'data-tachui-select-trigger': true,\n 'data-focused': focused(),\n 'data-disabled': disabled,\n 'data-error': !!errorMessage,\n },\n children: [\n // Display value\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-value': true,\n 'data-placeholder':\n !field.value() || (multiple && (!field.value() || field.value().length === 0)),\n },\n children: [text(getDisplayValue())],\n },\n\n // Actions (clear, dropdown arrow)\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-actions': true,\n },\n children: [\n // Clear button\n ...(clearable &&\n field.value() &&\n (!multiple || (Array.isArray(field.value()) && field.value().length > 0))\n ? [\n {\n type: 'element' as const,\n tag: 'button',\n props: {\n type: 'button',\n onclick: (e: Event) => {\n e.stopPropagation()\n handleClear()\n },\n 'aria-label': 'Clear selection',\n 'data-tachui-select-clear': true,\n },\n children: [text('×')],\n },\n ]\n : []),\n\n // Dropdown arrow\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-arrow': true,\n 'data-open': isOpen(),\n },\n children: [text('▼')],\n },\n ],\n },\n ],\n },\n\n // Dropdown menu\n ...(isOpen()\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-dropdown': true,\n style: {\n maxHeight: `${maxMenuHeight}px`,\n },\n },\n children: [\n // Search input\n ...(searchable\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-search': true,\n },\n children: [\n {\n type: 'element' as const,\n tag: 'input',\n props: {\n type: 'text',\n placeholder: 'Search...',\n value: searchQuery(),\n oninput: handleSearch,\n 'data-tachui-select-search-input': true,\n },\n },\n ],\n },\n ]\n : []),\n\n // Options list\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n role: 'listbox',\n 'aria-multiselectable': multiple,\n 'data-tachui-select-options': true,\n },\n children:\n filteredOptions().length > 0\n ? filteredOptions().map((option, index) => ({\n type: 'element' as const,\n tag: 'div',\n props: {\n role: 'option',\n 'aria-selected': isOptionSelected(option),\n 'aria-disabled': option.disabled,\n onclick: () => handleOptionSelect(option),\n 'data-tachui-select-option': true,\n 'data-selected': isOptionSelected(option),\n 'data-highlighted': highlightedIndex() === index,\n 'data-disabled': option.disabled,\n 'data-group': option.group,\n },\n children: [\n // Selection indicator for multiple\n ...(multiple\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-checkbox': true,\n 'data-checked': isOptionSelected(option),\n },\n children: [text(isOptionSelected(option) ? '✓' : '')],\n },\n ]\n : []),\n\n // Option label\n text(option.label),\n ],\n }))\n : [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-no-options': true,\n },\n children: [text(loading() ? loadingMessage : noOptionsMessage)],\n },\n ],\n },\n ],\n },\n ]\n : []),\n\n // Error message\n ...(errorMessage\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n id: `${name}-error`,\n role: 'alert',\n 'aria-live': 'polite',\n 'data-tachui-error': true,\n },\n children: [text(errorMessage)],\n },\n ]\n : []),\n\n // Helper text\n ...(helperText && !errorMessage\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n id: `${name}-helper`,\n 'data-tachui-helper': true,\n },\n children: [text(helperText)],\n },\n ]\n : []),\n ],\n }),\n props: props,\n }\n\n // Add form cleanup\n if (!componentInstance.cleanup) componentInstance.cleanup = []\n componentInstance.cleanup.push(() => {\n if (formContext) {\n formContext.unregister(name)\n }\n })\n\n // ENHANCED: Set up lifecycle hooks for improved click outside detection\n useLifecycle(componentInstance, {\n onDOMReady: (_elements, primaryElement) => {\n if (primaryElement) {\n // Set up enhanced outside click detection instead of relying on setTimeout blur\n setupOutsideClickDetection(\n componentInstance,\n () => {\n if (isOpen()) {\n setIsOpen(false)\n setFocused(false)\n field.onBlur()\n \n if (onBlur) {\n onBlur(name, field.value())\n }\n }\n },\n '[data-tachui-select-container]'\n )\n }\n }\n })\n\n return componentInstance\n}\n\n/**\n * MultiSelect variant for clearer multiple selection intent\n */\nexport const MultiSelect: Component<SelectProps> = (props) => {\n return Select({ ...props, multiple: true })\n}\n\n/**\n * Combobox variant with always-searchable behavior\n */\nexport const Combobox: Component<SelectProps> = (props) => {\n return Select({ ...props, searchable: true })\n}\n"],"names":["Select","props","name","label","options","multiple","searchable","clearable","placeholder","noOptionsMessage","loadingMessage","maxMenuHeight","disabled","required","controlledValue","defaultValue","validation","onChange","onBlur","onFocus","externalError","helperText","restProps","formContext","field","createField","isOpen","setIsOpen","createSignal","focused","setFocused","searchQuery","setSearchQuery","highlightedIndex","setHighlightedIndex","loading","createEffect","filteredOptions","query","option","getDisplayValue","value","opt","selectedOption","handleOptionSelect","newValue","currentValue","v","toggleDropdown","newOpen","handleSearch","event","target","handleKeyDown","filtered","nextIndex","prevIndex","handleClear","handleFocus","handleBlur","relatedTarget","isOptionSelected","errorMessage","componentInstance","h","text","index","useLifecycle","_elements","primaryElement","setupOutsideClickDetection","MultiSelect","Combobox"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const l=require("@tachui/core"),X=require("./forms-core-W_JGVLAI.cjs"),M=o=>{const{name:r,label:q,options:b,multiple:s=!1,searchable:d=!1,clearable:$=!1,placeholder:B=s?"Select options...":"Select an option...",noOptionsMessage:T="No options available",loadingMessage:j="Loading...",maxMenuHeight:P=200,disabled:m=!1,required:E=!1,value:y,defaultValue:Q,validation:F,onChange:x,onBlur:S,onFocus:I,error:_,helperText:C,...g}=o,c=o._formContext,a=X.createField(r,y??Q,F);c&&c.register(r,F);const[n,v]=l.createSignal(!1),[K,O]=l.createSignal(!1),[V,k]=l.createSignal(""),[p,h]=l.createSignal(-1),[N]=l.createSignal(!1);y!==void 0&&l.createEffect(()=>{a.value()!==y&&a.setValue(y)});const A=()=>{if(!d||!V())return b;const e=V().toLowerCase();return b.filter(t=>t.label.toLowerCase().includes(e)||String(t.value).toLowerCase().includes(e))},R=()=>{const e=a.value();if(s)return!e||!Array.isArray(e)||e.length===0?B:b.filter(i=>e.includes(i.value)).map(i=>i.label).join(", ");{if(e==null||e==="")return B;const t=b.find(i=>i.value===e);return t?t.label:String(e)}},L=e=>{if(e.disabled)return;let t;if(s){const i=a.value()||[];i.includes(e.value)?t=i.filter(W=>W!==e.value):t=[...i,e.value]}else t=e.value,v(!1),k("");a.setValue(t),c&&c.setValue(r,t),x&&x(r,t,a)},w=()=>{if(m)return;const e=!n();v(e),e&&(h(-1),d&&k(""))},U=e=>{const t=e.target;k(t.value),h(-1)},z=e=>{const t=A();switch(e.key){case"Enter":e.preventDefault(),n()?p()>=0&&t[p()]&&L(t[p()]):w();break;case" ":(!d||!n())&&(e.preventDefault(),w());break;case"Escape":e.preventDefault(),v(!1),k("");break;case"ArrowDown":if(e.preventDefault(),!n())w();else{const i=Math.min(p()+1,t.length-1);h(i)}break;case"ArrowUp":if(e.preventDefault(),n()){const i=Math.max(p()-1,-1);h(i)}break;case"Home":n()&&(e.preventDefault(),h(0));break;case"End":n()&&(e.preventDefault(),h(t.length-1));break;case"Backspace":$&&!d&&a.value()!==null&&(e.preventDefault(),H());break}},G=()=>{O(!0),a.onFocus(),I&&I(r,a.value())},J=e=>{requestAnimationFrame(()=>{const t=e.relatedTarget;e.target.closest("[data-tachui-select-container]")?.contains(t)||(O(!1),v(!1),a.onBlur(),S&&S(r,a.value()))})},H=()=>{const e=s?[]:null;a.setValue(e),c&&c.setValue(r,e),x&&x(r,e,a)},D=e=>{const t=a.value();return s?Array.isArray(t)&&t.includes(e.value):t===e.value},u=_||a.error()||c?.getError(r),f={type:"component",id:g.id||`select-${r}`,cleanup:[],render:()=>({type:"element",tag:"div",props:{...g,class:`tachui-select ${g.class||""}`.trim(),"data-tachui-select-container":!0,"data-field-state":u?"error":a.validating()?"validating":"valid","data-open":n(),"data-disabled":m,"data-multiple":s,"data-searchable":d},children:[...q?[l.h("label",{for:g.id||r,"data-tachui-label":!0,"data-required":E},l.text(q),...E?[l.h("span",{"aria-label":"required","data-required-indicator":!0},l.text(" *"))]:[])]:[],{type:"element",tag:"div",props:{id:g.id||r,tabindex:m?-1:0,role:"combobox","aria-expanded":n(),"aria-haspopup":"listbox","aria-invalid":!!u,"aria-describedby":[u?`${r}-error`:null,C?`${r}-helper`:null].filter(Boolean).join(" ")||void 0,onclick:w,onkeydown:z,onfocus:G,onblur:J,"data-tachui-select-trigger":!0,"data-focused":K(),"data-disabled":m,"data-error":!!u},children:[{type:"element",tag:"div",props:{"data-tachui-select-value":!0,"data-placeholder":!a.value()||s&&(!a.value()||a.value().length===0)},children:[l.text(R())]},{type:"element",tag:"div",props:{"data-tachui-select-actions":!0},children:[...$&&a.value()&&(!s||Array.isArray(a.value())&&a.value().length>0)?[{type:"element",tag:"button",props:{type:"button",onclick:e=>{e.stopPropagation(),H()},"aria-label":"Clear selection","data-tachui-select-clear":!0},children:[l.text("×")]}]:[],{type:"element",tag:"div",props:{"data-tachui-select-arrow":!0,"data-open":n()},children:[l.text("▼")]}]}]},...n()?[{type:"element",tag:"div",props:{"data-tachui-select-dropdown":!0,style:{maxHeight:`${P}px`}},children:[...d?[{type:"element",tag:"div",props:{"data-tachui-select-search":!0},children:[{type:"element",tag:"input",props:{type:"text",placeholder:"Search...",value:V(),oninput:U,"data-tachui-select-search-input":!0}}]}]:[],{type:"element",tag:"div",props:{role:"listbox","aria-multiselectable":s,"data-tachui-select-options":!0},children:A().length>0?A().map((e,t)=>({type:"element",tag:"div",props:{role:"option","aria-selected":D(e),"aria-disabled":e.disabled,onclick:()=>L(e),"data-tachui-select-option":!0,"data-selected":D(e),"data-highlighted":p()===t,"data-disabled":e.disabled,"data-group":e.group},children:[...s?[{type:"element",tag:"div",props:{"data-tachui-select-checkbox":!0,"data-checked":D(e)},children:[l.text(D(e)?"✓":"")]}]:[],l.text(e.label)]})):[{type:"element",tag:"div",props:{"data-tachui-select-no-options":!0},children:[l.text(N()?j:T)]}]}]}]:[],...u?[{type:"element",tag:"div",props:{id:`${r}-error`,role:"alert","aria-live":"polite","data-tachui-error":!0},children:[l.text(u)]}]:[],...C&&!u?[{type:"element",tag:"div",props:{id:`${r}-helper`,"data-tachui-helper":!0},children:[l.text(C)]}]:[]]}),props:o};return f.cleanup||(f.cleanup=[]),f.cleanup.push(()=>{c&&c.unregister(r)}),l.useLifecycle(f,{onDOMReady:(e,t)=>{t&&l.setupOutsideClickDetection(f,()=>{n()&&(v(!1),O(!1),a.onBlur(),S&&S(r,a.value()))},"[data-tachui-select-container]")}}),f},Y=o=>M({...o,multiple:!0}),Z=o=>M({...o,searchable:!0});exports.Combobox=Z;exports.MultiSelect=Y;exports.Select=M;
2
+ //# sourceMappingURL=forms-complex-DLEnXXJ5.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forms-complex-DLEnXXJ5.cjs","sources":["../src/components/input/Select.ts"],"sourcesContent":["/**\n * Select/Picker Component\n *\n * SwiftUI-inspired select component with search, multiple selection,\n * async options loading, and comprehensive accessibility support.\n */\n\nimport type { Component, ComponentInstance } from '@tachui/core'\nimport { createEffect, createSignal, h, text, useLifecycle, setupOutsideClickDetection } from '@tachui/core'\nimport { createField } from '../../state'\nimport type { SelectOption, SelectProps } from '../../types'\n\n/**\n * Select component implementation\n */\nexport const Select: Component<SelectProps> = (props) => {\n const {\n name,\n label,\n options,\n multiple = false,\n searchable = false,\n clearable = false,\n placeholder = multiple ? 'Select options...' : 'Select an option...',\n noOptionsMessage = 'No options available',\n loadingMessage = 'Loading...',\n maxMenuHeight = 200,\n disabled = false,\n required = false,\n value: controlledValue,\n defaultValue,\n validation,\n onChange,\n onBlur,\n onFocus,\n error: externalError,\n helperText,\n ...restProps\n } = props\n\n // Get form context if available\n const formContext = (props as any)._formContext\n\n // Create field state\n const field = createField(name, controlledValue ?? defaultValue, validation)\n\n // Register field with form if form context exists\n if (formContext) {\n formContext.register(name, validation)\n }\n\n const [isOpen, setIsOpen] = createSignal(false)\n const [focused, setFocused] = createSignal(false)\n const [searchQuery, setSearchQuery] = createSignal('')\n const [highlightedIndex, setHighlightedIndex] = createSignal(-1)\n const [loading] = createSignal(false)\n\n // Sync with controlled value\n if (controlledValue !== undefined) {\n createEffect(() => {\n if (field.value() !== controlledValue) {\n field.setValue(controlledValue)\n }\n })\n }\n\n // Filter options based on search query\n const filteredOptions = () => {\n if (!searchable || !searchQuery()) {\n return options\n }\n\n const query = searchQuery().toLowerCase()\n return options.filter(\n (option) =>\n option.label.toLowerCase().includes(query) ||\n String(option.value).toLowerCase().includes(query)\n )\n }\n\n // Get display value for selected option(s)\n const getDisplayValue = () => {\n const value = field.value()\n\n if (multiple) {\n if (!value || !Array.isArray(value) || value.length === 0) {\n return placeholder\n }\n\n const selectedOptions = options.filter((opt) => value.includes(opt.value))\n return selectedOptions.map((opt) => opt.label).join(', ')\n } else {\n if (value === null || value === undefined || value === '') {\n return placeholder\n }\n\n const selectedOption = options.find((opt) => opt.value === value)\n return selectedOption ? selectedOption.label : String(value)\n }\n }\n\n // Handle option selection\n const handleOptionSelect = (option: SelectOption) => {\n if (option.disabled) return\n\n let newValue: any\n\n if (multiple) {\n const currentValue = field.value() || []\n if (currentValue.includes(option.value)) {\n newValue = currentValue.filter((v: any) => v !== option.value)\n } else {\n newValue = [...currentValue, option.value]\n }\n } else {\n newValue = option.value\n setIsOpen(false)\n setSearchQuery('')\n }\n\n field.setValue(newValue)\n\n if (formContext) {\n formContext.setValue(name, newValue)\n }\n\n if (onChange) {\n onChange(name, newValue, field as any)\n }\n }\n\n // Handle dropdown toggle\n const toggleDropdown = () => {\n if (disabled) return\n\n const newOpen = !isOpen()\n setIsOpen(newOpen)\n\n if (newOpen) {\n setHighlightedIndex(-1)\n if (searchable) {\n setSearchQuery('')\n }\n }\n }\n\n // Handle search input\n const handleSearch = (event: Event) => {\n const target = event.target as HTMLInputElement\n setSearchQuery(target.value)\n setHighlightedIndex(-1)\n }\n\n // Handle keyboard navigation\n const handleKeyDown = (event: KeyboardEvent) => {\n const filtered = filteredOptions()\n\n switch (event.key) {\n case 'Enter':\n event.preventDefault()\n if (!isOpen()) {\n toggleDropdown()\n } else if (highlightedIndex() >= 0 && filtered[highlightedIndex()]) {\n handleOptionSelect(filtered[highlightedIndex()])\n }\n break\n\n case ' ':\n if (!searchable || !isOpen()) {\n event.preventDefault()\n toggleDropdown()\n }\n break\n\n case 'Escape':\n event.preventDefault()\n setIsOpen(false)\n setSearchQuery('')\n break\n\n case 'ArrowDown':\n event.preventDefault()\n if (!isOpen()) {\n toggleDropdown()\n } else {\n const nextIndex = Math.min(highlightedIndex() + 1, filtered.length - 1)\n setHighlightedIndex(nextIndex)\n }\n break\n\n case 'ArrowUp':\n event.preventDefault()\n if (isOpen()) {\n const prevIndex = Math.max(highlightedIndex() - 1, -1)\n setHighlightedIndex(prevIndex)\n }\n break\n\n case 'Home':\n if (isOpen()) {\n event.preventDefault()\n setHighlightedIndex(0)\n }\n break\n\n case 'End':\n if (isOpen()) {\n event.preventDefault()\n setHighlightedIndex(filtered.length - 1)\n }\n break\n\n case 'Backspace':\n if (clearable && !searchable && field.value() !== null) {\n event.preventDefault()\n handleClear()\n }\n break\n }\n }\n\n // Handle focus\n const handleFocus = () => {\n setFocused(true)\n field.onFocus()\n\n if (onFocus) {\n onFocus(name, field.value())\n }\n }\n\n // Handle blur\n const handleBlur = (event: FocusEvent) => {\n // ENHANCED: Use requestAnimationFrame instead of setTimeout for better performance\n requestAnimationFrame(() => {\n const relatedTarget = event.relatedTarget as Element\n const container = (event.target as Element).closest('[data-tachui-select-container]')\n\n if (!container?.contains(relatedTarget)) {\n setFocused(false)\n setIsOpen(false)\n field.onBlur()\n\n if (onBlur) {\n onBlur(name, field.value())\n }\n }\n })\n }\n\n // Handle clear\n const handleClear = () => {\n const newValue = multiple ? [] : null\n field.setValue(newValue)\n\n if (formContext) {\n formContext.setValue(name, newValue)\n }\n\n if (onChange) {\n onChange(name, newValue, field as any)\n }\n }\n\n // Check if option is selected\n const isOptionSelected = (option: SelectOption) => {\n const value = field.value()\n\n if (multiple) {\n return Array.isArray(value) && value.includes(option.value)\n }\n\n return value === option.value\n }\n\n // Determine error message\n const errorMessage = externalError || field.error() || formContext?.getError(name)\n\n const componentInstance: ComponentInstance = {\n type: 'component',\n id: restProps.id || `select-${name}`,\n cleanup: [],\n render: () => ({\n type: 'element',\n tag: 'div',\n props: {\n ...restProps,\n class: `tachui-select ${restProps.class || ''}`.trim(),\n 'data-tachui-select-container': true,\n 'data-field-state': errorMessage ? 'error' : field.validating() ? 'validating' : 'valid',\n 'data-open': isOpen(),\n 'data-disabled': disabled,\n 'data-multiple': multiple,\n 'data-searchable': searchable,\n },\n children: [\n // Label\n ...(label\n ? [\n h(\n 'label',\n {\n for: restProps.id || name,\n 'data-tachui-label': true,\n 'data-required': required,\n },\n text(label),\n ...(required\n ? [\n h(\n 'span',\n {\n 'aria-label': 'required',\n 'data-required-indicator': true,\n },\n text(' *')\n ),\n ]\n : [])\n ),\n ]\n : []),\n\n // Select trigger\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n id: restProps.id || name,\n tabindex: disabled ? -1 : 0,\n role: 'combobox',\n 'aria-expanded': isOpen(),\n 'aria-haspopup': 'listbox',\n 'aria-invalid': !!errorMessage,\n 'aria-describedby':\n [errorMessage ? `${name}-error` : null, helperText ? `${name}-helper` : null]\n .filter(Boolean)\n .join(' ') || undefined,\n onclick: toggleDropdown,\n onkeydown: handleKeyDown,\n onfocus: handleFocus,\n onblur: handleBlur,\n 'data-tachui-select-trigger': true,\n 'data-focused': focused(),\n 'data-disabled': disabled,\n 'data-error': !!errorMessage,\n },\n children: [\n // Display value\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-value': true,\n 'data-placeholder':\n !field.value() || (multiple && (!field.value() || field.value().length === 0)),\n },\n children: [text(getDisplayValue())],\n },\n\n // Actions (clear, dropdown arrow)\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-actions': true,\n },\n children: [\n // Clear button\n ...(clearable &&\n field.value() &&\n (!multiple || (Array.isArray(field.value()) && field.value().length > 0))\n ? [\n {\n type: 'element' as const,\n tag: 'button',\n props: {\n type: 'button',\n onclick: (e: Event) => {\n e.stopPropagation()\n handleClear()\n },\n 'aria-label': 'Clear selection',\n 'data-tachui-select-clear': true,\n },\n children: [text('×')],\n },\n ]\n : []),\n\n // Dropdown arrow\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-arrow': true,\n 'data-open': isOpen(),\n },\n children: [text('▼')],\n },\n ],\n },\n ],\n },\n\n // Dropdown menu\n ...(isOpen()\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-dropdown': true,\n style: {\n maxHeight: `${maxMenuHeight}px`,\n },\n },\n children: [\n // Search input\n ...(searchable\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-search': true,\n },\n children: [\n {\n type: 'element' as const,\n tag: 'input',\n props: {\n type: 'text',\n placeholder: 'Search...',\n value: searchQuery(),\n oninput: handleSearch,\n 'data-tachui-select-search-input': true,\n },\n },\n ],\n },\n ]\n : []),\n\n // Options list\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n role: 'listbox',\n 'aria-multiselectable': multiple,\n 'data-tachui-select-options': true,\n },\n children:\n filteredOptions().length > 0\n ? filteredOptions().map((option, index) => ({\n type: 'element' as const,\n tag: 'div',\n props: {\n role: 'option',\n 'aria-selected': isOptionSelected(option),\n 'aria-disabled': option.disabled,\n onclick: () => handleOptionSelect(option),\n 'data-tachui-select-option': true,\n 'data-selected': isOptionSelected(option),\n 'data-highlighted': highlightedIndex() === index,\n 'data-disabled': option.disabled,\n 'data-group': option.group,\n },\n children: [\n // Selection indicator for multiple\n ...(multiple\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-checkbox': true,\n 'data-checked': isOptionSelected(option),\n },\n children: [text(isOptionSelected(option) ? '✓' : '')],\n },\n ]\n : []),\n\n // Option label\n text(option.label),\n ],\n }))\n : [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n 'data-tachui-select-no-options': true,\n },\n children: [text(loading() ? loadingMessage : noOptionsMessage)],\n },\n ],\n },\n ],\n },\n ]\n : []),\n\n // Error message\n ...(errorMessage\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n id: `${name}-error`,\n role: 'alert',\n 'aria-live': 'polite',\n 'data-tachui-error': true,\n },\n children: [text(errorMessage)],\n },\n ]\n : []),\n\n // Helper text\n ...(helperText && !errorMessage\n ? [\n {\n type: 'element' as const,\n tag: 'div',\n props: {\n id: `${name}-helper`,\n 'data-tachui-helper': true,\n },\n children: [text(helperText)],\n },\n ]\n : []),\n ],\n }),\n props: props,\n }\n\n // Add form cleanup\n if (!componentInstance.cleanup) componentInstance.cleanup = []\n componentInstance.cleanup.push(() => {\n if (formContext) {\n formContext.unregister(name)\n }\n })\n\n // ENHANCED: Set up lifecycle hooks for improved click outside detection\n useLifecycle(componentInstance, {\n onDOMReady: (_elements, primaryElement) => {\n if (primaryElement) {\n // Set up enhanced outside click detection instead of relying on setTimeout blur\n setupOutsideClickDetection(\n componentInstance,\n () => {\n if (isOpen()) {\n setIsOpen(false)\n setFocused(false)\n field.onBlur()\n \n if (onBlur) {\n onBlur(name, field.value())\n }\n }\n },\n '[data-tachui-select-container]'\n )\n }\n }\n })\n\n return componentInstance\n}\n\n/**\n * MultiSelect variant for clearer multiple selection intent\n */\nexport const MultiSelect: Component<SelectProps> = (props) => {\n return Select({ ...props, multiple: true })\n}\n\n/**\n * Combobox variant with always-searchable behavior\n */\nexport const Combobox: Component<SelectProps> = (props) => {\n return Select({ ...props, searchable: true })\n}\n"],"names":["Select","props","name","label","options","multiple","searchable","clearable","placeholder","noOptionsMessage","loadingMessage","maxMenuHeight","disabled","required","controlledValue","defaultValue","validation","onChange","onBlur","onFocus","externalError","helperText","restProps","formContext","field","createField","isOpen","setIsOpen","createSignal","focused","setFocused","searchQuery","setSearchQuery","highlightedIndex","setHighlightedIndex","loading","createEffect","filteredOptions","query","option","getDisplayValue","value","opt","selectedOption","handleOptionSelect","newValue","currentValue","v","toggleDropdown","newOpen","handleSearch","event","target","handleKeyDown","filtered","nextIndex","prevIndex","handleClear","handleFocus","handleBlur","relatedTarget","isOptionSelected","errorMessage","componentInstance","h","text","index","useLifecycle","_elements","primaryElement","setupOutsideClickDetection","MultiSelect","Combobox"],"mappings":"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"}