@proyecto-viviana/solidaria 0.2.4 → 0.2.8

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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/dist/actiongroup/createActionGroup.d.ts +29 -0
  3. package/dist/actiongroup/createActionGroup.d.ts.map +1 -0
  4. package/dist/actiongroup/index.d.ts +2 -0
  5. package/dist/actiongroup/index.d.ts.map +1 -0
  6. package/dist/autocomplete/createAutocomplete.d.ts +6 -2
  7. package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
  8. package/dist/breadcrumbs/createBreadcrumbs.d.ts +2 -0
  9. package/dist/breadcrumbs/createBreadcrumbs.d.ts.map +1 -1
  10. package/dist/button/createToggleButtonGroup.d.ts +32 -0
  11. package/dist/button/createToggleButtonGroup.d.ts.map +1 -0
  12. package/dist/button/index.d.ts +2 -0
  13. package/dist/button/index.d.ts.map +1 -1
  14. package/dist/calendar/createCalendarCell.d.ts +2 -0
  15. package/dist/calendar/createCalendarCell.d.ts.map +1 -1
  16. package/dist/calendar/createCalendarGrid.d.ts.map +1 -1
  17. package/dist/calendar/createRangeCalendarCell.d.ts +3 -1
  18. package/dist/calendar/createRangeCalendarCell.d.ts.map +1 -1
  19. package/dist/checkbox/createCheckboxGroup.d.ts +5 -1
  20. package/dist/checkbox/createCheckboxGroup.d.ts.map +1 -1
  21. package/dist/collections/index.d.ts +56 -0
  22. package/dist/collections/index.d.ts.map +1 -0
  23. package/dist/color/createColorArea.d.ts.map +1 -1
  24. package/dist/color/createColorSlider.d.ts.map +1 -1
  25. package/dist/color/createColorWheel.d.ts.map +1 -1
  26. package/dist/combobox/createComboBox.d.ts +6 -0
  27. package/dist/combobox/createComboBox.d.ts.map +1 -1
  28. package/dist/datepicker/createDatePicker.d.ts +6 -0
  29. package/dist/datepicker/createDatePicker.d.ts.map +1 -1
  30. package/dist/datepicker/createDateRangePicker.d.ts +40 -0
  31. package/dist/datepicker/createDateRangePicker.d.ts.map +1 -0
  32. package/dist/datepicker/createDateSegment.d.ts +1 -1
  33. package/dist/datepicker/createDateSegment.d.ts.map +1 -1
  34. package/dist/datepicker/createTimeSegment.d.ts +29 -0
  35. package/dist/datepicker/createTimeSegment.d.ts.map +1 -0
  36. package/dist/datepicker/index.d.ts +2 -0
  37. package/dist/datepicker/index.d.ts.map +1 -1
  38. package/dist/disclosure/createDisclosureGroup.d.ts +2 -1
  39. package/dist/disclosure/createDisclosureGroup.d.ts.map +1 -1
  40. package/dist/dnd/createDrag.d.ts.map +1 -1
  41. package/dist/dnd/createDraggableCollection.d.ts +4 -0
  42. package/dist/dnd/createDraggableCollection.d.ts.map +1 -1
  43. package/dist/dnd/createDraggableItem.d.ts.map +1 -1
  44. package/dist/dnd/createDrop.d.ts.map +1 -1
  45. package/dist/dnd/createDroppableCollection.d.ts +32 -1
  46. package/dist/dnd/createDroppableCollection.d.ts.map +1 -1
  47. package/dist/dnd/createDroppableItem.d.ts.map +1 -1
  48. package/dist/dnd/index.d.ts +1 -1
  49. package/dist/dnd/index.d.ts.map +1 -1
  50. package/dist/grid/createGrid.d.ts.map +1 -1
  51. package/dist/gridlist/createGridList.d.ts.map +1 -1
  52. package/dist/index.d.ts +6 -4
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +4659 -3452
  55. package/dist/index.js.map +1 -7
  56. package/dist/index.ssr.js +4659 -3452
  57. package/dist/index.ssr.js.map +1 -7
  58. package/dist/interactions/createFocus.d.ts.map +1 -1
  59. package/dist/interactions/createFocusWithin.d.ts.map +1 -1
  60. package/dist/link/createLink.d.ts +10 -0
  61. package/dist/link/createLink.d.ts.map +1 -1
  62. package/dist/listbox/createListBox.d.ts +1 -0
  63. package/dist/listbox/createListBox.d.ts.map +1 -1
  64. package/dist/listbox/createOption.d.ts.map +1 -1
  65. package/dist/menu/createMenu.d.ts +1 -0
  66. package/dist/menu/createMenu.d.ts.map +1 -1
  67. package/dist/meter/createMeter.d.ts.map +1 -1
  68. package/dist/numberfield/createNumberField.d.ts +18 -0
  69. package/dist/numberfield/createNumberField.d.ts.map +1 -1
  70. package/dist/overlays/createModal.d.ts +16 -0
  71. package/dist/overlays/createModal.d.ts.map +1 -1
  72. package/dist/overlays/createOverlay.d.ts.map +1 -1
  73. package/dist/overlays/index.d.ts +1 -1
  74. package/dist/overlays/index.d.ts.map +1 -1
  75. package/dist/popover/createOverlayPosition.d.ts.map +1 -1
  76. package/dist/popover/createPopover.d.ts.map +1 -1
  77. package/dist/progress/createProgressBar.d.ts.map +1 -1
  78. package/dist/radio/createRadioGroup.d.ts +2 -2
  79. package/dist/radio/createRadioGroup.d.ts.map +1 -1
  80. package/dist/searchfield/createSearchField.d.ts.map +1 -1
  81. package/dist/select/createHiddenSelect.d.ts.map +1 -1
  82. package/dist/select/createSelect.d.ts.map +1 -1
  83. package/dist/slider/createSlider.d.ts.map +1 -1
  84. package/dist/table/createTable.d.ts.map +1 -1
  85. package/dist/tabs/createTabs.d.ts +1 -1
  86. package/dist/tabs/createTabs.d.ts.map +1 -1
  87. package/dist/tag/createTag.d.ts.map +1 -1
  88. package/dist/tag/createTagGroup.d.ts.map +1 -1
  89. package/dist/toast/createToast.d.ts +4 -0
  90. package/dist/toast/createToast.d.ts.map +1 -1
  91. package/dist/toast/createToastRegion.d.ts.map +1 -1
  92. package/dist/toolbar/createToolbar.d.ts.map +1 -1
  93. package/dist/tooltip/createTooltipTrigger.d.ts.map +1 -1
  94. package/dist/tree/createTree.d.ts.map +1 -1
  95. package/dist/tree/createTreeItem.d.ts.map +1 -1
  96. package/dist/tree/types.d.ts +4 -0
  97. package/dist/tree/types.d.ts.map +1 -1
  98. package/dist/utils/env.d.ts +1 -1
  99. package/dist/utils/env.d.ts.map +1 -1
  100. package/dist/utils/platform.d.ts.map +1 -1
  101. package/dist/visually-hidden/createVisuallyHidden.d.ts.map +1 -1
  102. package/package.json +8 -6
  103. package/src/actiongroup/createActionGroup.ts +324 -0
  104. package/src/actiongroup/index.ts +8 -0
  105. package/src/autocomplete/createAutocomplete.ts +32 -9
  106. package/src/breadcrumbs/createBreadcrumbs.ts +10 -15
  107. package/src/button/createButton.ts +1 -1
  108. package/src/button/createToggleButtonGroup.ts +128 -0
  109. package/src/button/index.ts +9 -0
  110. package/src/calendar/createCalendarCell.ts +6 -4
  111. package/src/calendar/createCalendarGrid.ts +27 -18
  112. package/src/calendar/createRangeCalendarCell.ts +26 -9
  113. package/src/checkbox/createCheckboxGroup.ts +21 -4
  114. package/src/collections/index.ts +242 -0
  115. package/src/color/createColorArea.ts +380 -314
  116. package/src/color/createColorField.ts +137 -137
  117. package/src/color/createColorSlider.ts +286 -197
  118. package/src/color/createColorSwatch.ts +40 -40
  119. package/src/color/createColorWheel.ts +218 -208
  120. package/src/color/index.ts +24 -24
  121. package/src/color/types.ts +116 -116
  122. package/src/combobox/createComboBox.ts +670 -647
  123. package/src/combobox/index.ts +6 -6
  124. package/src/datepicker/createDatePicker.ts +54 -16
  125. package/src/datepicker/createDateRangePicker.ts +246 -0
  126. package/src/datepicker/createDateSegment.ts +185 -31
  127. package/src/datepicker/createTimeSegment.ts +370 -0
  128. package/src/datepicker/index.ts +14 -0
  129. package/src/dialog/createDialog.ts +120 -120
  130. package/src/dialog/index.ts +2 -2
  131. package/src/dialog/types.ts +19 -19
  132. package/src/disclosure/createDisclosureGroup.ts +5 -2
  133. package/src/dnd/createDrag.ts +224 -209
  134. package/src/dnd/createDraggableCollection.ts +96 -63
  135. package/src/dnd/createDraggableItem.ts +259 -243
  136. package/src/dnd/createDrop.ts +322 -321
  137. package/src/dnd/createDroppableCollection.ts +682 -293
  138. package/src/dnd/createDroppableItem.ts +215 -213
  139. package/src/dnd/index.ts +55 -47
  140. package/src/dnd/types.ts +89 -89
  141. package/src/dnd/utils.ts +294 -294
  142. package/src/focus/createAutoFocus.ts +321 -321
  143. package/src/focus/createFocusRestore.ts +313 -313
  144. package/src/focus/createVirtualFocus.ts +396 -396
  145. package/src/form/createFormValidation.ts +224 -224
  146. package/src/form/index.ts +11 -11
  147. package/src/grid/createGrid.ts +3 -1
  148. package/src/gridlist/createGridList.ts +16 -0
  149. package/src/gridlist/createGridListItem.ts +1 -1
  150. package/src/i18n/NumberFormatter.ts +266 -266
  151. package/src/i18n/createCollator.ts +79 -79
  152. package/src/i18n/createDateFormatter.ts +83 -83
  153. package/src/i18n/createFilter.ts +131 -131
  154. package/src/i18n/createNumberFormatter.ts +52 -52
  155. package/src/i18n/index.ts +40 -40
  156. package/src/i18n/locale.tsx +188 -188
  157. package/src/i18n/utils.ts +99 -99
  158. package/src/index.ts +51 -0
  159. package/src/interactions/createFocus.ts +6 -5
  160. package/src/interactions/createFocusWithin.ts +6 -5
  161. package/src/interactions/createLongPress.ts +174 -174
  162. package/src/interactions/createMove.ts +289 -289
  163. package/src/interactions/createPress.ts +5 -5
  164. package/src/landmark/createLandmark.ts +377 -377
  165. package/src/landmark/index.ts +8 -8
  166. package/src/link/createLink.ts +23 -8
  167. package/src/listbox/createListBox.ts +308 -269
  168. package/src/listbox/createOption.ts +162 -151
  169. package/src/listbox/index.ts +12 -12
  170. package/src/live-announcer/announce.ts +322 -322
  171. package/src/live-announcer/index.ts +9 -9
  172. package/src/menu/createMenu.ts +405 -396
  173. package/src/menu/createMenuItem.ts +149 -149
  174. package/src/menu/createMenuTrigger.ts +88 -88
  175. package/src/menu/index.ts +18 -18
  176. package/src/meter/createMeter.ts +1 -6
  177. package/src/numberfield/createNumberField.ts +311 -268
  178. package/src/numberfield/index.ts +5 -5
  179. package/src/overlays/ariaHideOutside.ts +219 -219
  180. package/src/overlays/createInteractOutside.ts +149 -149
  181. package/src/overlays/createModal.tsx +238 -202
  182. package/src/overlays/createOverlay.ts +165 -155
  183. package/src/overlays/createOverlayTrigger.ts +85 -85
  184. package/src/overlays/createPreventScroll.ts +266 -266
  185. package/src/overlays/index.ts +48 -44
  186. package/src/popover/calculatePosition.ts +6 -6
  187. package/src/popover/createOverlayPosition.ts +7 -4
  188. package/src/popover/createPopover.ts +21 -7
  189. package/src/progress/createProgressBar.ts +6 -1
  190. package/src/radio/createRadioGroup.ts +88 -14
  191. package/src/searchfield/createSearchField.ts +241 -186
  192. package/src/searchfield/index.ts +2 -2
  193. package/src/select/createHiddenSelect.tsx +263 -236
  194. package/src/select/createSelect.ts +373 -395
  195. package/src/select/index.ts +14 -14
  196. package/src/slider/createSlider.ts +364 -349
  197. package/src/slider/index.ts +2 -2
  198. package/src/ssr/index.tsx +370 -370
  199. package/src/table/createTable.ts +3 -1
  200. package/src/table/createTableColumnHeader.ts +1 -1
  201. package/src/table/createTableRow.ts +1 -1
  202. package/src/tabs/createTabs.ts +80 -51
  203. package/src/tag/createTag.ts +135 -6
  204. package/src/tag/createTagGroup.ts +7 -2
  205. package/src/toast/createToast.ts +8 -2
  206. package/src/toast/createToastRegion.ts +0 -1
  207. package/src/toolbar/createToolbar.ts +75 -1
  208. package/src/tooltip/createTooltip.ts +79 -79
  209. package/src/tooltip/createTooltipTrigger.ts +226 -222
  210. package/src/tooltip/index.ts +6 -6
  211. package/src/tree/createTree.ts +261 -246
  212. package/src/tree/createTreeItem.ts +282 -233
  213. package/src/tree/createTreeSelectionCheckbox.ts +68 -68
  214. package/src/tree/index.ts +16 -16
  215. package/src/tree/types.ts +91 -87
  216. package/src/utils/env.ts +55 -54
  217. package/src/utils/platform.ts +16 -6
  218. package/src/visually-hidden/createVisuallyHidden.ts +139 -124
  219. package/src/visually-hidden/index.ts +6 -6
@@ -1,186 +1,241 @@
1
- /**
2
- * Provides the behavior and accessibility implementation for a search field.
3
- * A search field allows a user to enter and clear a search query.
4
- * Based on @react-aria/searchfield useSearchField.
5
- */
6
-
7
- import { type JSX } from 'solid-js';
8
- import { createTextField, type AriaTextFieldProps, type TextFieldAria } from '../textfield';
9
- import { mergeProps } from '../utils';
10
- import { type MaybeAccessor, access } from '../utils/reactivity';
11
- import type { SearchFieldState } from '@proyecto-viviana/solid-stately';
12
-
13
- export interface AriaSearchFieldProps extends Omit<AriaTextFieldProps, 'type'> {
14
- /** Handler that is called when the user submits the search (pressing Enter). */
15
- onSubmit?: (value: string) => void;
16
- /** Handler that is called when the clear button is pressed or Escape clears the field. */
17
- onClear?: () => void;
18
- }
19
-
20
- export interface SearchFieldAria extends Omit<TextFieldAria, 'inputProps'> {
21
- /** Props for the input element. */
22
- inputProps: JSX.InputHTMLAttributes<HTMLInputElement>;
23
- /** Props for the clear button. */
24
- clearButtonProps: {
25
- 'aria-label': string;
26
- tabIndex: number;
27
- disabled?: boolean;
28
- onMouseDown: (e: MouseEvent) => void;
29
- onClick: () => void;
30
- };
31
- }
32
-
33
- /**
34
- * Provides the behavior and accessibility implementation for a search field.
35
- */
36
- export function createSearchField(
37
- props: MaybeAccessor<AriaSearchFieldProps>,
38
- state: SearchFieldState,
39
- inputRef?: () => HTMLInputElement | null
40
- ): SearchFieldAria {
41
- const getProps = () => access(props);
42
-
43
- // Use createTextField for the base implementation
44
- const textFieldAria = createTextField({
45
- get value() {
46
- return state.value();
47
- },
48
- get isDisabled() {
49
- return getProps().isDisabled;
50
- },
51
- get isReadOnly() {
52
- return getProps().isReadOnly;
53
- },
54
- get isRequired() {
55
- return getProps().isRequired;
56
- },
57
- get isInvalid() {
58
- return getProps().isInvalid;
59
- },
60
- get label() {
61
- return getProps().label;
62
- },
63
- get 'aria-label'() {
64
- return getProps()['aria-label'];
65
- },
66
- get 'aria-labelledby'() {
67
- return getProps()['aria-labelledby'];
68
- },
69
- get 'aria-describedby'() {
70
- return getProps()['aria-describedby'];
71
- },
72
- get description() {
73
- return getProps().description;
74
- },
75
- get errorMessage() {
76
- return getProps().errorMessage;
77
- },
78
- get placeholder() {
79
- return getProps().placeholder;
80
- },
81
- get name() {
82
- return getProps().name;
83
- },
84
- get autoFocus() {
85
- return getProps().autoFocus;
86
- },
87
- get autoComplete() {
88
- return getProps().autoComplete;
89
- },
90
- get maxLength() {
91
- return getProps().maxLength;
92
- },
93
- get minLength() {
94
- return getProps().minLength;
95
- },
96
- get pattern() {
97
- return getProps().pattern;
98
- },
99
- type: 'search',
100
- onChange: (value: string) => {
101
- state.setValue(value);
102
- getProps().onChange?.(value);
103
- },
104
- });
105
-
106
- // Handle keyboard events for search field
107
- const onKeyDown: JSX.EventHandler<HTMLInputElement, KeyboardEvent> = (e) => {
108
- const p = getProps();
109
-
110
- if (p.isDisabled || p.isReadOnly) {
111
- if (e.key === 'Enter') {
112
- e.preventDefault();
113
- }
114
- return;
115
- }
116
-
117
- if (e.key === 'Enter' && p.onSubmit) {
118
- e.preventDefault();
119
- p.onSubmit(state.value());
120
- }
121
-
122
- if (e.key === 'Escape') {
123
- const currentValue = state.value();
124
- const inputValue = inputRef?.()?.value ?? '';
125
-
126
- // Only clear if there's a value
127
- if (currentValue !== '' || inputValue !== '') {
128
- e.preventDefault();
129
- e.stopPropagation();
130
- state.setValue('');
131
- p.onClear?.();
132
- }
133
- }
134
- };
135
-
136
- // Handle clear button click
137
- const onClearButtonClick = () => {
138
- const p = getProps();
139
- state.setValue('');
140
- p.onClear?.();
141
- // Focus the input after clearing
142
- inputRef?.()?.focus();
143
- };
144
-
145
- // Prevent focus from leaving input on mobile when clicking clear button
146
- const onClearButtonMouseDown = (e: MouseEvent) => {
147
- e.preventDefault();
148
- };
149
-
150
- return {
151
- get labelProps() {
152
- return textFieldAria.labelProps;
153
- },
154
- get inputProps() {
155
- return mergeProps(
156
- textFieldAria.inputProps as Record<string, unknown>,
157
- {
158
- onKeyDown,
159
- // Clear defaultValue since it's handled by state
160
- defaultValue: undefined,
161
- } as Record<string, unknown>
162
- ) as JSX.InputHTMLAttributes<HTMLInputElement>;
163
- },
164
- get clearButtonProps() {
165
- const p = getProps();
166
- const isDisabled = p.isDisabled || p.isReadOnly;
167
-
168
- return {
169
- 'aria-label': 'Clear search',
170
- tabIndex: -1, // Exclude from tab order
171
- disabled: isDisabled,
172
- onMouseDown: onClearButtonMouseDown,
173
- onClick: onClearButtonClick,
174
- };
175
- },
176
- get descriptionProps() {
177
- return textFieldAria.descriptionProps;
178
- },
179
- get errorMessageProps() {
180
- return textFieldAria.errorMessageProps;
181
- },
182
- get isInvalid() {
183
- return textFieldAria.isInvalid;
184
- },
185
- };
186
- }
1
+ /**
2
+ * Provides the behavior and accessibility implementation for a search field.
3
+ * A search field allows a user to enter and clear a search query.
4
+ * Based on @react-aria/searchfield useSearchField.
5
+ */
6
+
7
+ import { type JSX } from 'solid-js';
8
+ import { createTextField, type AriaTextFieldProps, type TextFieldAria } from '../textfield';
9
+ import { mergeProps } from '../utils';
10
+ import { type MaybeAccessor, access } from '../utils/reactivity';
11
+ import type { SearchFieldState } from '@proyecto-viviana/solid-stately';
12
+
13
+ export interface AriaSearchFieldProps extends Omit<AriaTextFieldProps, 'type'> {
14
+ /** Handler that is called when the user submits the search (pressing Enter). */
15
+ onSubmit?: (value: string) => void;
16
+ /** Handler that is called when the clear button is pressed or Escape clears the field. */
17
+ onClear?: () => void;
18
+ }
19
+
20
+ export interface SearchFieldAria extends Omit<TextFieldAria, 'inputProps'> {
21
+ /** Props for the input element. */
22
+ inputProps: JSX.InputHTMLAttributes<HTMLInputElement>;
23
+ /** Props for the clear button. */
24
+ clearButtonProps: {
25
+ 'aria-label': string;
26
+ tabIndex: number;
27
+ disabled?: boolean;
28
+ onMouseDown: (e: MouseEvent) => void;
29
+ onClick: () => void;
30
+ };
31
+ }
32
+
33
+ /**
34
+ * Provides the behavior and accessibility implementation for a search field.
35
+ */
36
+ export function createSearchField(
37
+ props: MaybeAccessor<AriaSearchFieldProps>,
38
+ state: SearchFieldState,
39
+ inputRef?: () => HTMLInputElement | null
40
+ ): SearchFieldAria {
41
+ const getProps = () => access(props);
42
+
43
+ // Use createTextField for the base implementation
44
+ const textFieldAria = createTextField({
45
+ get value() {
46
+ return state.value();
47
+ },
48
+ get isDisabled() {
49
+ return getProps().isDisabled;
50
+ },
51
+ get isReadOnly() {
52
+ return getProps().isReadOnly;
53
+ },
54
+ get isRequired() {
55
+ return getProps().isRequired;
56
+ },
57
+ get isInvalid() {
58
+ return getProps().isInvalid;
59
+ },
60
+ get label() {
61
+ return getProps().label;
62
+ },
63
+ get 'aria-label'() {
64
+ return getProps()['aria-label'];
65
+ },
66
+ get 'aria-labelledby'() {
67
+ return getProps()['aria-labelledby'];
68
+ },
69
+ get 'aria-describedby'() {
70
+ return getProps()['aria-describedby'];
71
+ },
72
+ get description() {
73
+ return getProps().description;
74
+ },
75
+ get errorMessage() {
76
+ return getProps().errorMessage;
77
+ },
78
+ get placeholder() {
79
+ return getProps().placeholder;
80
+ },
81
+ get name() {
82
+ return getProps().name;
83
+ },
84
+ get autoFocus() {
85
+ return getProps().autoFocus;
86
+ },
87
+ get autoComplete() {
88
+ return getProps().autoComplete;
89
+ },
90
+ get inputMode() {
91
+ return getProps().inputMode;
92
+ },
93
+ get autoCorrect() {
94
+ return getProps().autoCorrect;
95
+ },
96
+ get autoCapitalize() {
97
+ return getProps().autoCapitalize;
98
+ },
99
+ get spellCheck() {
100
+ return getProps().spellCheck;
101
+ },
102
+ get maxLength() {
103
+ return getProps().maxLength;
104
+ },
105
+ get minLength() {
106
+ return getProps().minLength;
107
+ },
108
+ get pattern() {
109
+ return getProps().pattern;
110
+ },
111
+ get onFocus() {
112
+ return getProps().onFocus;
113
+ },
114
+ get onBlur() {
115
+ return getProps().onBlur;
116
+ },
117
+ get onFocusChange() {
118
+ return getProps().onFocusChange;
119
+ },
120
+ get onKeyDown() {
121
+ return getProps().onKeyDown;
122
+ },
123
+ get onKeyUp() {
124
+ return getProps().onKeyUp;
125
+ },
126
+ get onCopy() {
127
+ return getProps().onCopy;
128
+ },
129
+ get onCut() {
130
+ return getProps().onCut;
131
+ },
132
+ get onPaste() {
133
+ return getProps().onPaste;
134
+ },
135
+ get onCompositionStart() {
136
+ return getProps().onCompositionStart;
137
+ },
138
+ get onCompositionEnd() {
139
+ return getProps().onCompositionEnd;
140
+ },
141
+ get onCompositionUpdate() {
142
+ return getProps().onCompositionUpdate;
143
+ },
144
+ get onSelect() {
145
+ return getProps().onSelect;
146
+ },
147
+ get onBeforeInput() {
148
+ return getProps().onBeforeInput;
149
+ },
150
+ get onInput() {
151
+ return getProps().onInput;
152
+ },
153
+ type: 'search',
154
+ onChange: (value: string) => {
155
+ state.setValue(value);
156
+ getProps().onChange?.(value);
157
+ },
158
+ });
159
+
160
+ // Handle keyboard events for search field
161
+ const onKeyDown: JSX.EventHandler<HTMLInputElement, KeyboardEvent> = (e) => {
162
+ const p = getProps();
163
+
164
+ if (p.isDisabled || p.isReadOnly) {
165
+ if (e.key === 'Enter') {
166
+ e.preventDefault();
167
+ }
168
+ return;
169
+ }
170
+
171
+ if (e.key === 'Enter' && p.onSubmit) {
172
+ e.preventDefault();
173
+ p.onSubmit(state.value());
174
+ }
175
+
176
+ if (e.key === 'Escape') {
177
+ const currentValue = state.value();
178
+ const inputValue = inputRef?.()?.value ?? '';
179
+
180
+ // Only clear if there's a value
181
+ if (currentValue !== '' || inputValue !== '') {
182
+ e.preventDefault();
183
+ e.stopPropagation();
184
+ state.setValue('');
185
+ p.onClear?.();
186
+ }
187
+ }
188
+ };
189
+
190
+ // Handle clear button click
191
+ const onClearButtonClick = () => {
192
+ const p = getProps();
193
+ if (p.isDisabled || p.isReadOnly) return;
194
+ state.setValue('');
195
+ p.onClear?.();
196
+ // Focus the input after clearing
197
+ inputRef?.()?.focus();
198
+ };
199
+
200
+ // Prevent focus from leaving input on mobile when clicking clear button
201
+ const onClearButtonMouseDown = (e: MouseEvent) => {
202
+ e.preventDefault();
203
+ };
204
+
205
+ return {
206
+ get labelProps() {
207
+ return textFieldAria.labelProps;
208
+ },
209
+ get inputProps() {
210
+ return mergeProps(
211
+ {
212
+ onKeyDown,
213
+ // Clear defaultValue since it's handled by state
214
+ defaultValue: undefined,
215
+ } as Record<string, unknown>,
216
+ textFieldAria.inputProps as Record<string, unknown>
217
+ ) as JSX.InputHTMLAttributes<HTMLInputElement>;
218
+ },
219
+ get clearButtonProps() {
220
+ const p = getProps();
221
+ const isDisabled = p.isDisabled || p.isReadOnly;
222
+
223
+ return {
224
+ 'aria-label': 'Clear search',
225
+ tabIndex: -1, // Exclude from tab order
226
+ disabled: isDisabled,
227
+ onMouseDown: onClearButtonMouseDown,
228
+ onClick: onClearButtonClick,
229
+ };
230
+ },
231
+ get descriptionProps() {
232
+ return textFieldAria.descriptionProps;
233
+ },
234
+ get errorMessageProps() {
235
+ return textFieldAria.errorMessageProps;
236
+ },
237
+ get isInvalid() {
238
+ return textFieldAria.isInvalid;
239
+ },
240
+ };
241
+ }
@@ -1,2 +1,2 @@
1
- export { createSearchField } from './createSearchField';
2
- export type { AriaSearchFieldProps, SearchFieldAria } from './createSearchField';
1
+ export { createSearchField } from './createSearchField';
2
+ export type { AriaSearchFieldProps, SearchFieldAria } from './createSearchField';