@rovula/ui 0.1.41 → 0.1.42

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.
@@ -0,0 +1,74 @@
1
+ import React, { ReactNode } from "react";
2
+ import { type InputProps } from "../TextInput/TextInput";
3
+ export type AutoCompleteOption = {
4
+ value: string;
5
+ label: string;
6
+ };
7
+ /**
8
+ * InputProps that AutoComplete manages internally.
9
+ * These are excluded from the public API so callers cannot accidentally
10
+ * override internal event wiring or ARIA attributes.
11
+ */
12
+ type OmittedInputProps = "value" | "onChange" | "onKeyDown" | "onSelect" | "role" | "aria-expanded" | "aria-haspopup" | "aria-autocomplete" | "aria-activedescendant" | "aria-controls" | "autoComplete" | "hasClearIcon";
13
+ export type AutoCompleteProps<T extends AutoCompleteOption = AutoCompleteOption> = {
14
+ /** Options provided by caller (already filtered/fetched externally) */
15
+ options: T[];
16
+ /** Controlled value — the current input text */
17
+ value?: string;
18
+ /**
19
+ * Called on every change: typing or clearing.
20
+ * Parent should update `value` from this.
21
+ */
22
+ onChange?: (value: string) => void;
23
+ /**
24
+ * Called only when user explicitly selects an option from the list.
25
+ * Receives the full option object (including any domain-specific fields).
26
+ */
27
+ onSelect?: (option: T) => void;
28
+ onBlur?: () => void;
29
+ /** Called with the current query when the user types */
30
+ onSearch?: (query: string) => void;
31
+ /** Show a loading spinner inside the dropdown */
32
+ loading?: boolean;
33
+ /** Text shown when options is empty and not loading */
34
+ noOptionsText?: string;
35
+ /**
36
+ * When true, show the noOptionsText message when options is empty.
37
+ * Defaults to false (popover stays closed when no options).
38
+ */
39
+ showNoOptions?: boolean;
40
+ /**
41
+ * Custom render for each option item.
42
+ * Receives the option and whether it is currently selected.
43
+ * The wrapper button (styles + click handler) is provided by AutoComplete.
44
+ */
45
+ renderOption?: (option: T, isSelected: boolean) => ReactNode;
46
+ /**
47
+ * Override client-side filtering.
48
+ * Pass `(x) => x` to disable filtering entirely (when results come from an API).
49
+ * Defaults to identity (no filtering).
50
+ */
51
+ filterOptions?: (options: T[]) => T[];
52
+ /**
53
+ * Render the options list via a React portal so it escapes containers
54
+ * with `overflow: hidden/auto`.
55
+ * Set to false when inside a Dialog — portal content is blocked by
56
+ * Radix Dialog's focus trap and aria-modal, making items unclickable.
57
+ * Defaults to true.
58
+ */
59
+ portal?: boolean;
60
+ /** Extra className applied to the options list container */
61
+ listboxClassName?: string;
62
+ /** Extra inline styles applied to the options list container */
63
+ listboxStyle?: React.CSSProperties;
64
+ /** Extra className applied to each option item */
65
+ optionClassName?: string;
66
+ /** Extra inline styles applied to each option item */
67
+ optionStyle?: React.CSSProperties;
68
+ "data-testid"?: string;
69
+ } & Omit<InputProps, OmittedInputProps>;
70
+ declare function AutoCompleteInner<T extends AutoCompleteOption = AutoCompleteOption>({ options, value, onChange, onSelect, onBlur, onSearch, loading, noOptionsText, showNoOptions, renderOption, filterOptions, portal, listboxClassName, listboxStyle, optionClassName, optionStyle, "data-testid": testId, id, label, fullwidth, size, rounded, variant, disabled, ...rest }: AutoCompleteProps<T>, ref: React.ForwardedRef<HTMLInputElement>): import("react/jsx-runtime").JSX.Element;
71
+ declare const AutoComplete: <T extends AutoCompleteOption = AutoCompleteOption>(props: AutoCompleteProps<T> & {
72
+ ref?: React.ForwardedRef<HTMLInputElement>;
73
+ }) => ReturnType<typeof AutoCompleteInner>;
74
+ export default AutoComplete;
@@ -0,0 +1,361 @@
1
+ import React from "react";
2
+ import type { StoryObj } from "@storybook/react";
3
+ import AutoComplete, { type AutoCompleteOption } from "./AutoComplete";
4
+ declare const meta: {
5
+ title: string;
6
+ component: <T extends AutoCompleteOption = AutoCompleteOption>(props: import("./AutoComplete").AutoCompleteProps<T> & {
7
+ ref?: React.ForwardedRef<HTMLInputElement>;
8
+ }) => ReturnType<(<T_1 extends AutoCompleteOption = AutoCompleteOption>({ options, value, onChange, onSelect, onBlur, onSearch, loading, noOptionsText, showNoOptions, renderOption, filterOptions, portal, listboxClassName, listboxStyle, optionClassName, optionStyle, "data-testid": testId, id, label, fullwidth, size, rounded, variant, disabled, ...rest }: import("./AutoComplete").AutoCompleteProps<T_1>, ref: React.ForwardedRef<HTMLInputElement>) => import("react/jsx-runtime").JSX.Element)>;
9
+ tags: string[];
10
+ parameters: {
11
+ layout: string;
12
+ };
13
+ decorators: ((Story: import("@storybook/csf").PartialStoryFn<import("@storybook/react").ReactRenderer, {
14
+ options: AutoCompleteOption[];
15
+ value?: string | undefined;
16
+ onChange?: ((value: string) => void) | undefined;
17
+ onSelect?: ((option: AutoCompleteOption) => void) | undefined;
18
+ onBlur?: ((() => void) & React.FocusEventHandler<HTMLInputElement>) | undefined;
19
+ onSearch?: ((query: string) => void) | undefined;
20
+ loading?: boolean | undefined;
21
+ noOptionsText?: string | undefined;
22
+ showNoOptions?: boolean | undefined;
23
+ renderOption?: ((option: AutoCompleteOption, isSelected: boolean) => React.ReactNode) | undefined;
24
+ filterOptions?: ((options: AutoCompleteOption[]) => AutoCompleteOption[]) | undefined;
25
+ portal?: boolean | undefined;
26
+ listboxClassName?: string | undefined;
27
+ listboxStyle?: React.CSSProperties | undefined;
28
+ optionClassName?: string | undefined;
29
+ optionStyle?: React.CSSProperties | undefined;
30
+ "data-testid"?: string | undefined;
31
+ variant?: "flat" | "outline" | "underline" | undefined;
32
+ suppressHydrationWarning?: boolean | undefined | undefined;
33
+ className?: string | undefined;
34
+ color?: string | undefined | undefined;
35
+ height?: number | string | undefined | undefined;
36
+ id?: string | undefined;
37
+ lang?: string | undefined | undefined;
38
+ max?: number | string | undefined | undefined;
39
+ min?: number | string | undefined | undefined;
40
+ name?: string | undefined | undefined;
41
+ style?: React.CSSProperties | undefined;
42
+ type?: React.HTMLInputTypeAttribute | undefined;
43
+ width?: number | string | undefined | undefined;
44
+ tabIndex?: number | undefined | undefined;
45
+ format?: ((value: string) => string) | undefined;
46
+ "aria-atomic"?: (boolean | "true" | "false") | undefined;
47
+ "aria-braillelabel"?: string | undefined | undefined;
48
+ "aria-brailleroledescription"?: string | undefined | undefined;
49
+ "aria-busy"?: (boolean | "true" | "false") | undefined;
50
+ "aria-checked"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
51
+ "aria-colcount"?: number | undefined | undefined;
52
+ "aria-colindex"?: number | undefined | undefined;
53
+ "aria-colindextext"?: string | undefined | undefined;
54
+ "aria-colspan"?: number | undefined | undefined;
55
+ "aria-current"?: boolean | "false" | "true" | "page" | "step" | "location" | "date" | "time" | undefined | undefined;
56
+ "aria-describedby"?: string | undefined | undefined;
57
+ "aria-description"?: string | undefined | undefined;
58
+ "aria-details"?: string | undefined | undefined;
59
+ "aria-disabled"?: (boolean | "true" | "false") | undefined;
60
+ "aria-dropeffect"?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined | undefined;
61
+ "aria-errormessage"?: string | undefined | undefined;
62
+ "aria-flowto"?: string | undefined | undefined;
63
+ "aria-grabbed"?: (boolean | "true" | "false") | undefined;
64
+ "aria-hidden"?: (boolean | "true" | "false") | undefined;
65
+ "aria-invalid"?: boolean | "false" | "true" | "grammar" | "spelling" | undefined | undefined;
66
+ "aria-keyshortcuts"?: string | undefined | undefined;
67
+ "aria-label"?: string | undefined | undefined;
68
+ "aria-labelledby"?: string | undefined | undefined;
69
+ "aria-level"?: number | undefined | undefined;
70
+ "aria-live"?: "off" | "assertive" | "polite" | undefined | undefined;
71
+ "aria-modal"?: (boolean | "true" | "false") | undefined;
72
+ "aria-multiline"?: (boolean | "true" | "false") | undefined;
73
+ "aria-multiselectable"?: (boolean | "true" | "false") | undefined;
74
+ "aria-orientation"?: "horizontal" | "vertical" | undefined | undefined;
75
+ "aria-owns"?: string | undefined | undefined;
76
+ "aria-placeholder"?: string | undefined | undefined;
77
+ "aria-posinset"?: number | undefined | undefined;
78
+ "aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
79
+ "aria-readonly"?: (boolean | "true" | "false") | undefined;
80
+ "aria-relevant"?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined | undefined;
81
+ "aria-required"?: (boolean | "true" | "false") | undefined;
82
+ "aria-roledescription"?: string | undefined | undefined;
83
+ "aria-rowcount"?: number | undefined | undefined;
84
+ "aria-rowindex"?: number | undefined | undefined;
85
+ "aria-rowindextext"?: string | undefined | undefined;
86
+ "aria-rowspan"?: number | undefined | undefined;
87
+ "aria-selected"?: (boolean | "true" | "false") | undefined;
88
+ "aria-setsize"?: number | undefined | undefined;
89
+ "aria-sort"?: "none" | "ascending" | "descending" | "other" | undefined | undefined;
90
+ "aria-valuemax"?: number | undefined | undefined;
91
+ "aria-valuemin"?: number | undefined | undefined;
92
+ "aria-valuenow"?: number | undefined | undefined;
93
+ "aria-valuetext"?: string | undefined | undefined;
94
+ children?: React.ReactNode;
95
+ dangerouslySetInnerHTML?: {
96
+ __html: string | TrustedHTML;
97
+ } | undefined | undefined;
98
+ onCopy?: React.ClipboardEventHandler<HTMLInputElement> | undefined;
99
+ onCopyCapture?: React.ClipboardEventHandler<HTMLInputElement> | undefined;
100
+ onCut?: React.ClipboardEventHandler<HTMLInputElement> | undefined;
101
+ onCutCapture?: React.ClipboardEventHandler<HTMLInputElement> | undefined;
102
+ onPaste?: React.ClipboardEventHandler<HTMLInputElement> | undefined;
103
+ onPasteCapture?: React.ClipboardEventHandler<HTMLInputElement> | undefined;
104
+ onCompositionEnd?: React.CompositionEventHandler<HTMLInputElement> | undefined;
105
+ onCompositionEndCapture?: React.CompositionEventHandler<HTMLInputElement> | undefined;
106
+ onCompositionStart?: React.CompositionEventHandler<HTMLInputElement> | undefined;
107
+ onCompositionStartCapture?: React.CompositionEventHandler<HTMLInputElement> | undefined;
108
+ onCompositionUpdate?: React.CompositionEventHandler<HTMLInputElement> | undefined;
109
+ onCompositionUpdateCapture?: React.CompositionEventHandler<HTMLInputElement> | undefined;
110
+ onFocus?: React.FocusEventHandler<HTMLInputElement> | undefined;
111
+ onFocusCapture?: React.FocusEventHandler<HTMLInputElement> | undefined;
112
+ onBlurCapture?: React.FocusEventHandler<HTMLInputElement> | undefined;
113
+ onChangeCapture?: React.FormEventHandler<HTMLInputElement> | undefined;
114
+ onBeforeInput?: React.FormEventHandler<HTMLInputElement> | undefined;
115
+ onBeforeInputCapture?: React.FormEventHandler<HTMLInputElement> | undefined;
116
+ onInput?: React.FormEventHandler<HTMLInputElement> | undefined;
117
+ onInputCapture?: React.FormEventHandler<HTMLInputElement> | undefined;
118
+ onReset?: React.FormEventHandler<HTMLInputElement> | undefined;
119
+ onResetCapture?: React.FormEventHandler<HTMLInputElement> | undefined;
120
+ onSubmit?: React.FormEventHandler<HTMLInputElement> | undefined;
121
+ onSubmitCapture?: React.FormEventHandler<HTMLInputElement> | undefined;
122
+ onInvalid?: React.FormEventHandler<HTMLInputElement> | undefined;
123
+ onInvalidCapture?: React.FormEventHandler<HTMLInputElement> | undefined;
124
+ onLoad?: React.ReactEventHandler<HTMLInputElement> | undefined;
125
+ onLoadCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
126
+ onError?: React.ReactEventHandler<HTMLInputElement> | undefined;
127
+ onErrorCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
128
+ onKeyDownCapture?: React.KeyboardEventHandler<HTMLInputElement> | undefined;
129
+ onKeyPress?: React.KeyboardEventHandler<HTMLInputElement> | undefined;
130
+ onKeyPressCapture?: React.KeyboardEventHandler<HTMLInputElement> | undefined;
131
+ onKeyUp?: React.KeyboardEventHandler<HTMLInputElement> | undefined;
132
+ onKeyUpCapture?: React.KeyboardEventHandler<HTMLInputElement> | undefined;
133
+ onAbort?: React.ReactEventHandler<HTMLInputElement> | undefined;
134
+ onAbortCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
135
+ onCanPlay?: React.ReactEventHandler<HTMLInputElement> | undefined;
136
+ onCanPlayCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
137
+ onCanPlayThrough?: React.ReactEventHandler<HTMLInputElement> | undefined;
138
+ onCanPlayThroughCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
139
+ onDurationChange?: React.ReactEventHandler<HTMLInputElement> | undefined;
140
+ onDurationChangeCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
141
+ onEmptied?: React.ReactEventHandler<HTMLInputElement> | undefined;
142
+ onEmptiedCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
143
+ onEncrypted?: React.ReactEventHandler<HTMLInputElement> | undefined;
144
+ onEncryptedCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
145
+ onEnded?: React.ReactEventHandler<HTMLInputElement> | undefined;
146
+ onEndedCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
147
+ onLoadedData?: React.ReactEventHandler<HTMLInputElement> | undefined;
148
+ onLoadedDataCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
149
+ onLoadedMetadata?: React.ReactEventHandler<HTMLInputElement> | undefined;
150
+ onLoadedMetadataCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
151
+ onLoadStart?: React.ReactEventHandler<HTMLInputElement> | undefined;
152
+ onLoadStartCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
153
+ onPause?: React.ReactEventHandler<HTMLInputElement> | undefined;
154
+ onPauseCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
155
+ onPlay?: React.ReactEventHandler<HTMLInputElement> | undefined;
156
+ onPlayCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
157
+ onPlaying?: React.ReactEventHandler<HTMLInputElement> | undefined;
158
+ onPlayingCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
159
+ onProgress?: React.ReactEventHandler<HTMLInputElement> | undefined;
160
+ onProgressCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
161
+ onRateChange?: React.ReactEventHandler<HTMLInputElement> | undefined;
162
+ onRateChangeCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
163
+ onResize?: React.ReactEventHandler<HTMLInputElement> | undefined;
164
+ onResizeCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
165
+ onSeeked?: React.ReactEventHandler<HTMLInputElement> | undefined;
166
+ onSeekedCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
167
+ onSeeking?: React.ReactEventHandler<HTMLInputElement> | undefined;
168
+ onSeekingCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
169
+ onStalled?: React.ReactEventHandler<HTMLInputElement> | undefined;
170
+ onStalledCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
171
+ onSuspend?: React.ReactEventHandler<HTMLInputElement> | undefined;
172
+ onSuspendCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
173
+ onTimeUpdate?: React.ReactEventHandler<HTMLInputElement> | undefined;
174
+ onTimeUpdateCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
175
+ onVolumeChange?: React.ReactEventHandler<HTMLInputElement> | undefined;
176
+ onVolumeChangeCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
177
+ onWaiting?: React.ReactEventHandler<HTMLInputElement> | undefined;
178
+ onWaitingCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
179
+ onAuxClick?: React.MouseEventHandler<HTMLInputElement> | undefined;
180
+ onAuxClickCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
181
+ onClick?: React.MouseEventHandler<HTMLInputElement> | undefined;
182
+ onClickCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
183
+ onContextMenu?: React.MouseEventHandler<HTMLInputElement> | undefined;
184
+ onContextMenuCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
185
+ onDoubleClick?: React.MouseEventHandler<HTMLInputElement> | undefined;
186
+ onDoubleClickCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
187
+ onDrag?: React.DragEventHandler<HTMLInputElement> | undefined;
188
+ onDragCapture?: React.DragEventHandler<HTMLInputElement> | undefined;
189
+ onDragEnd?: React.DragEventHandler<HTMLInputElement> | undefined;
190
+ onDragEndCapture?: React.DragEventHandler<HTMLInputElement> | undefined;
191
+ onDragEnter?: React.DragEventHandler<HTMLInputElement> | undefined;
192
+ onDragEnterCapture?: React.DragEventHandler<HTMLInputElement> | undefined;
193
+ onDragExit?: React.DragEventHandler<HTMLInputElement> | undefined;
194
+ onDragExitCapture?: React.DragEventHandler<HTMLInputElement> | undefined;
195
+ onDragLeave?: React.DragEventHandler<HTMLInputElement> | undefined;
196
+ onDragLeaveCapture?: React.DragEventHandler<HTMLInputElement> | undefined;
197
+ onDragOver?: React.DragEventHandler<HTMLInputElement> | undefined;
198
+ onDragOverCapture?: React.DragEventHandler<HTMLInputElement> | undefined;
199
+ onDragStart?: React.DragEventHandler<HTMLInputElement> | undefined;
200
+ onDragStartCapture?: React.DragEventHandler<HTMLInputElement> | undefined;
201
+ onDrop?: React.DragEventHandler<HTMLInputElement> | undefined;
202
+ onDropCapture?: React.DragEventHandler<HTMLInputElement> | undefined;
203
+ onMouseDown?: React.MouseEventHandler<HTMLInputElement> | undefined;
204
+ onMouseDownCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
205
+ onMouseEnter?: React.MouseEventHandler<HTMLInputElement> | undefined;
206
+ onMouseLeave?: React.MouseEventHandler<HTMLInputElement> | undefined;
207
+ onMouseMove?: React.MouseEventHandler<HTMLInputElement> | undefined;
208
+ onMouseMoveCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
209
+ onMouseOut?: React.MouseEventHandler<HTMLInputElement> | undefined;
210
+ onMouseOutCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
211
+ onMouseOver?: React.MouseEventHandler<HTMLInputElement> | undefined;
212
+ onMouseOverCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
213
+ onMouseUp?: React.MouseEventHandler<HTMLInputElement> | undefined;
214
+ onMouseUpCapture?: React.MouseEventHandler<HTMLInputElement> | undefined;
215
+ onSelectCapture?: React.ReactEventHandler<HTMLInputElement> | undefined;
216
+ onTouchCancel?: React.TouchEventHandler<HTMLInputElement> | undefined;
217
+ onTouchCancelCapture?: React.TouchEventHandler<HTMLInputElement> | undefined;
218
+ onTouchEnd?: React.TouchEventHandler<HTMLInputElement> | undefined;
219
+ onTouchEndCapture?: React.TouchEventHandler<HTMLInputElement> | undefined;
220
+ onTouchMove?: React.TouchEventHandler<HTMLInputElement> | undefined;
221
+ onTouchMoveCapture?: React.TouchEventHandler<HTMLInputElement> | undefined;
222
+ onTouchStart?: React.TouchEventHandler<HTMLInputElement> | undefined;
223
+ onTouchStartCapture?: React.TouchEventHandler<HTMLInputElement> | undefined;
224
+ onPointerDown?: React.PointerEventHandler<HTMLInputElement> | undefined;
225
+ onPointerDownCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
226
+ onPointerMove?: React.PointerEventHandler<HTMLInputElement> | undefined;
227
+ onPointerMoveCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
228
+ onPointerUp?: React.PointerEventHandler<HTMLInputElement> | undefined;
229
+ onPointerUpCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
230
+ onPointerCancel?: React.PointerEventHandler<HTMLInputElement> | undefined;
231
+ onPointerCancelCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
232
+ onPointerEnter?: React.PointerEventHandler<HTMLInputElement> | undefined;
233
+ onPointerLeave?: React.PointerEventHandler<HTMLInputElement> | undefined;
234
+ onPointerOver?: React.PointerEventHandler<HTMLInputElement> | undefined;
235
+ onPointerOverCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
236
+ onPointerOut?: React.PointerEventHandler<HTMLInputElement> | undefined;
237
+ onPointerOutCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
238
+ onGotPointerCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
239
+ onGotPointerCaptureCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
240
+ onLostPointerCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
241
+ onLostPointerCaptureCapture?: React.PointerEventHandler<HTMLInputElement> | undefined;
242
+ onScroll?: React.UIEventHandler<HTMLInputElement> | undefined;
243
+ onScrollCapture?: React.UIEventHandler<HTMLInputElement> | undefined;
244
+ onWheel?: React.WheelEventHandler<HTMLInputElement> | undefined;
245
+ onWheelCapture?: React.WheelEventHandler<HTMLInputElement> | undefined;
246
+ onAnimationStart?: React.AnimationEventHandler<HTMLInputElement> | undefined;
247
+ onAnimationStartCapture?: React.AnimationEventHandler<HTMLInputElement> | undefined;
248
+ onAnimationEnd?: React.AnimationEventHandler<HTMLInputElement> | undefined;
249
+ onAnimationEndCapture?: React.AnimationEventHandler<HTMLInputElement> | undefined;
250
+ onAnimationIteration?: React.AnimationEventHandler<HTMLInputElement> | undefined;
251
+ onAnimationIterationCapture?: React.AnimationEventHandler<HTMLInputElement> | undefined;
252
+ onTransitionEnd?: React.TransitionEventHandler<HTMLInputElement> | undefined;
253
+ onTransitionEndCapture?: React.TransitionEventHandler<HTMLInputElement> | undefined;
254
+ form?: string | undefined | undefined;
255
+ list?: string | undefined | undefined;
256
+ status?: "default" | "warning" | "error" | undefined;
257
+ step?: number | string | undefined | undefined;
258
+ normalize?: ((value: string) => string) | undefined;
259
+ warning?: boolean | undefined;
260
+ error?: boolean | undefined;
261
+ size?: "sm" | "md" | "lg" | undefined;
262
+ disabled?: boolean | undefined;
263
+ fullwidth?: boolean | undefined;
264
+ title?: string | undefined | undefined;
265
+ startIcon?: React.ReactNode;
266
+ endIcon?: React.ReactNode;
267
+ formAction?: string | undefined;
268
+ formEncType?: string | undefined | undefined;
269
+ formMethod?: string | undefined | undefined;
270
+ formNoValidate?: boolean | undefined | undefined;
271
+ formTarget?: string | undefined | undefined;
272
+ defaultChecked?: boolean | undefined | undefined;
273
+ defaultValue?: string | number | readonly string[] | undefined;
274
+ suppressContentEditableWarning?: boolean | undefined | undefined;
275
+ accessKey?: string | undefined | undefined;
276
+ autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {}) | undefined;
277
+ autoFocus?: boolean | undefined | undefined;
278
+ contentEditable?: "inherit" | (boolean | "true" | "false") | "plaintext-only" | undefined;
279
+ contextMenu?: string | undefined | undefined;
280
+ dir?: string | undefined | undefined;
281
+ draggable?: (boolean | "true" | "false") | undefined;
282
+ enterKeyHint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined | undefined;
283
+ hidden?: boolean | undefined | undefined;
284
+ nonce?: string | undefined | undefined;
285
+ slot?: string | undefined | undefined;
286
+ spellCheck?: (boolean | "true" | "false") | undefined;
287
+ translate?: "yes" | "no" | undefined | undefined;
288
+ radioGroup?: string | undefined | undefined;
289
+ about?: string | undefined | undefined;
290
+ content?: string | undefined | undefined;
291
+ datatype?: string | undefined | undefined;
292
+ inlist?: any;
293
+ prefix?: string | undefined | undefined;
294
+ property?: string | undefined | undefined;
295
+ rel?: string | undefined | undefined;
296
+ resource?: string | undefined | undefined;
297
+ rev?: string | undefined | undefined;
298
+ typeof?: string | undefined | undefined;
299
+ vocab?: string | undefined | undefined;
300
+ autoCorrect?: string | undefined | undefined;
301
+ autoSave?: string | undefined | undefined;
302
+ itemProp?: string | undefined | undefined;
303
+ itemScope?: boolean | undefined | undefined;
304
+ itemType?: string | undefined | undefined;
305
+ itemID?: string | undefined | undefined;
306
+ itemRef?: string | undefined | undefined;
307
+ results?: number | undefined | undefined;
308
+ security?: string | undefined | undefined;
309
+ unselectable?: "on" | "off" | undefined | undefined;
310
+ inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined | undefined;
311
+ is?: string | undefined | undefined;
312
+ rounded?: "none" | "normal" | "full" | undefined;
313
+ hasSearchIcon?: boolean | undefined;
314
+ isFloatingLabel?: boolean | undefined;
315
+ accept?: string | undefined | undefined;
316
+ alt?: string | undefined | undefined;
317
+ capture?: boolean | "user" | "environment" | undefined | undefined;
318
+ checked?: boolean | undefined | undefined;
319
+ maxLength?: number | undefined | undefined;
320
+ minLength?: number | undefined | undefined;
321
+ multiple?: boolean | undefined | undefined;
322
+ pattern?: string | undefined | undefined;
323
+ placeholder?: string | undefined | undefined;
324
+ readOnly?: boolean | undefined | undefined;
325
+ required?: boolean | undefined;
326
+ src?: string | undefined | undefined;
327
+ label?: string | undefined;
328
+ iconMode?: "flat" | "solid" | undefined;
329
+ helperText?: string | undefined;
330
+ errorMessage?: string | undefined;
331
+ warningMessage?: string | undefined;
332
+ keepCloseIconOnValue?: boolean | undefined;
333
+ keepFooterSpace?: boolean | undefined;
334
+ labelClassName?: string | undefined;
335
+ classes?: {
336
+ iconWrapper?: string;
337
+ iconSearchWrapper?: string;
338
+ icon?: string;
339
+ startIconWrapper?: string;
340
+ endIconWrapper?: string;
341
+ } | undefined;
342
+ onClickStartIcon?: (() => void) | undefined;
343
+ onClickEndIcon?: (() => void) | undefined;
344
+ renderStartIcon?: (() => React.ReactNode) | undefined;
345
+ renderEndIcon?: (() => React.ReactNode) | undefined;
346
+ trimOnCommit?: boolean | undefined;
347
+ normalizeOnCommit?: ((value: string) => string) | undefined;
348
+ ref?: React.ForwardedRef<HTMLInputElement> | undefined;
349
+ }>) => import("react/jsx-runtime").JSX.Element)[];
350
+ };
351
+ export default meta;
352
+ export declare const Default: StoryObj<typeof AutoComplete>;
353
+ export declare const ShowNoOptionsMessage: StoryObj;
354
+ export declare const FreeSolo: StoryObj;
355
+ export declare const Async: StoryObj;
356
+ export declare const WithFormValidation: StoryObj;
357
+ export declare const InsideDialog: StoryObj;
358
+ export declare const Sizes: StoryObj;
359
+ export declare const States: StoryObj;
360
+ export declare const LoadingState: StoryObj;
361
+ export declare const KeyboardNavigation: StoryObj;
@@ -0,0 +1,2 @@
1
+ export { default } from "./AutoComplete";
2
+ export type { AutoCompleteProps, AutoCompleteOption } from "./AutoComplete";
@@ -9,6 +9,9 @@ export { default as TextArea } from "./components/TextArea/TextArea";
9
9
  export { default as Text } from "./components/Text/Text";
10
10
  export { default as Tabs } from "./components/Tabs/Tabs";
11
11
  export { default as Dropdown } from "./components/Dropdown/Dropdown";
12
+ export { menuItemBaseStyles } from "./components/Dropdown/Dropdown";
13
+ export { default as AutoComplete } from "./components/AutoComplete/AutoComplete";
14
+ export type { AutoCompleteProps, AutoCompleteOption } from "./components/AutoComplete/AutoComplete";
12
15
  export { Checkbox } from "./components/Checkbox/Checkbox";
13
16
  export { Label } from "./components/Label/Label";
14
17
  export { Input } from "./components/Input/Input";
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { ReactElement, ReactNode, FC, ComponentPropsWithoutRef, CSSProperties, HTMLAttributes, FormHTMLAttributes, ComponentType } from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
4
5
  import * as class_variance_authority_dist_types from 'class-variance-authority/dist/types';
5
6
  import * as LabelPrimitive from '@radix-ui/react-label';
6
7
  import { VariantProps } from 'class-variance-authority';
7
- import * as react_jsx_runtime from 'react/jsx-runtime';
8
8
  import { DayPicker, Modifiers } from 'react-day-picker';
9
9
  import * as PopoverPrimitive from '@radix-ui/react-popover';
10
10
  import { RowData, Row, ColumnDef, SortingState, PaginationState, RowSelectionState, Cell, ExpandedState, Header } from '@tanstack/react-table';
@@ -378,6 +378,7 @@ type TabsProps = {
378
378
  };
379
379
  declare const Tabs: React__default.FC<TabsProps>;
380
380
 
381
+ declare const menuItemBaseStyles: string;
381
382
  type RenderLabelCallbackArg$1 = {
382
383
  value: string;
383
384
  label: string;
@@ -472,6 +473,78 @@ declare const Dropdown: React__default.ForwardRefExoticComponent<{
472
473
  portal?: boolean;
473
474
  } & Omit<InputProps, "onSelect" | "value"> & React__default.RefAttributes<HTMLInputElement>>;
474
475
 
476
+ type AutoCompleteOption = {
477
+ value: string;
478
+ label: string;
479
+ };
480
+ /**
481
+ * InputProps that AutoComplete manages internally.
482
+ * These are excluded from the public API so callers cannot accidentally
483
+ * override internal event wiring or ARIA attributes.
484
+ */
485
+ type OmittedInputProps = "value" | "onChange" | "onKeyDown" | "onSelect" | "role" | "aria-expanded" | "aria-haspopup" | "aria-autocomplete" | "aria-activedescendant" | "aria-controls" | "autoComplete" | "hasClearIcon";
486
+ type AutoCompleteProps<T extends AutoCompleteOption = AutoCompleteOption> = {
487
+ /** Options provided by caller (already filtered/fetched externally) */
488
+ options: T[];
489
+ /** Controlled value — the current input text */
490
+ value?: string;
491
+ /**
492
+ * Called on every change: typing or clearing.
493
+ * Parent should update `value` from this.
494
+ */
495
+ onChange?: (value: string) => void;
496
+ /**
497
+ * Called only when user explicitly selects an option from the list.
498
+ * Receives the full option object (including any domain-specific fields).
499
+ */
500
+ onSelect?: (option: T) => void;
501
+ onBlur?: () => void;
502
+ /** Called with the current query when the user types */
503
+ onSearch?: (query: string) => void;
504
+ /** Show a loading spinner inside the dropdown */
505
+ loading?: boolean;
506
+ /** Text shown when options is empty and not loading */
507
+ noOptionsText?: string;
508
+ /**
509
+ * When true, show the noOptionsText message when options is empty.
510
+ * Defaults to false (popover stays closed when no options).
511
+ */
512
+ showNoOptions?: boolean;
513
+ /**
514
+ * Custom render for each option item.
515
+ * Receives the option and whether it is currently selected.
516
+ * The wrapper button (styles + click handler) is provided by AutoComplete.
517
+ */
518
+ renderOption?: (option: T, isSelected: boolean) => ReactNode;
519
+ /**
520
+ * Override client-side filtering.
521
+ * Pass `(x) => x` to disable filtering entirely (when results come from an API).
522
+ * Defaults to identity (no filtering).
523
+ */
524
+ filterOptions?: (options: T[]) => T[];
525
+ /**
526
+ * Render the options list via a React portal so it escapes containers
527
+ * with `overflow: hidden/auto`.
528
+ * Set to false when inside a Dialog — portal content is blocked by
529
+ * Radix Dialog's focus trap and aria-modal, making items unclickable.
530
+ * Defaults to true.
531
+ */
532
+ portal?: boolean;
533
+ /** Extra className applied to the options list container */
534
+ listboxClassName?: string;
535
+ /** Extra inline styles applied to the options list container */
536
+ listboxStyle?: React__default.CSSProperties;
537
+ /** Extra className applied to each option item */
538
+ optionClassName?: string;
539
+ /** Extra inline styles applied to each option item */
540
+ optionStyle?: React__default.CSSProperties;
541
+ "data-testid"?: string;
542
+ } & Omit<InputProps, OmittedInputProps>;
543
+ declare function AutoCompleteInner<T extends AutoCompleteOption = AutoCompleteOption>({ options, value, onChange, onSelect, onBlur, onSearch, loading, noOptionsText, showNoOptions, renderOption, filterOptions, portal, listboxClassName, listboxStyle, optionClassName, optionStyle, "data-testid": testId, id, label, fullwidth, size, rounded, variant, disabled, ...rest }: AutoCompleteProps<T>, ref: React__default.ForwardedRef<HTMLInputElement>): react_jsx_runtime.JSX.Element;
544
+ declare const AutoComplete: <T extends AutoCompleteOption = AutoCompleteOption>(props: AutoCompleteProps<T> & {
545
+ ref?: React__default.ForwardedRef<HTMLInputElement>;
546
+ }) => ReturnType<typeof AutoCompleteInner>;
547
+
475
548
  declare const Checkbox: React$1.ForwardRefExoticComponent<Omit<CheckboxPrimitive.CheckboxProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
476
549
 
477
550
  declare const Label: React$1.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & React$1.RefAttributes<HTMLLabelElement>, "ref"> & VariantProps<(props?: ({
@@ -2288,4 +2361,4 @@ declare const srgbToHex: (color: string) => string;
2288
2361
  */
2289
2362
  declare function getLucideIconNames(): Promise<string[]>;
2290
2363
 
2291
- export { ActionButton, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Badge, type BadgeColor, type BadgeProps, Button, type ButtonProps, Calendar, Checkbox, Collapsible, type ColumnManagementOptions, ConfirmDialog, type ConfirmDialogProps, type ControlledFormFactoryOptions, type CustomSliderProps, DataTable, type DataTableEditingProps, type DataTablePaginationMode, type DataTableProps, DatePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Dropdown, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type DropdownProps, type EditDisplayMode, type EditTrigger, type EditableColumnDef, Field, FieldMessage, type FieldMessageProps, type FieldProps, FocusedScrollView, Footer, type FooterProps, type FooterVariant, Form, type FormController, FormDialog, type FormDialogAction, type FormDialogProps, type FormProps, Icon, Input, InputFilter, type InputFilterProps, type InputProps, Label, Loading, type MaskRule, MaskedTextInput, type MaskedTextInputProps, Menu, DropdownMenuItem as MenuItem, type MenuItemType, DropdownMenuLabel as MenuLabel, type MenuOption, type MenuProps, DropdownMenuSeparator as MenuSeparator, Navbar, type NavbarProps, type NavbarVariant, NumberInput, type NumberInputProps, type OptionLike, type Options$1 as Options, OtpInput, OtpInputGroup, type OtpInputGroupProps, type OtpInputProps, PasswordInput, type PasswordInputProps, Popover, PopoverContent, PopoverTrigger, ProgressBar, RadioGroup, RadioGroupItem, ScrollArea, type ScrollAreaProps, type ScrollbarSize, Search, type SearchProps, SeverityBadge, type SeverityBadgeProps, type SeverityLevel, Slider, type SliderProps, Switch, THEME_COLOR_KEYS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TablePagination, type TablePaginationProps, TableRow, Tabs, Text, TextArea, type TextAreaProps, TextInput, type ThemeColorKey, Toast$1 as Toast, ToastAction, type ToastActionElement, ToastClose, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipSimple, TooltipTrigger, Tree, type TreeData, TreeItem, type TreeItemProps, type TreeProps, type UseControlledFormOptions, type UseOptionBridgeOptions, ValidationHintList, type ValidationHintListProps, type ValidationHintMode, type ValidationHintRule, type ValidationHintState, cn, createControlledForm, createYupResolver, getEndDateOfDay, getLucideIconNames, getStartDateOfDay, getStartEndTimestampOfDay, getThemeColor, getThemeColors, getTimestampUTC, reducer, resloveTimestamp, srgbToHex, toast, useControlledForm, useOptionBridge, usePrevious, useToast };
2364
+ export { ActionButton, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AutoComplete, type AutoCompleteOption, type AutoCompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Badge, type BadgeColor, type BadgeProps, Button, type ButtonProps, Calendar, Checkbox, Collapsible, type ColumnManagementOptions, ConfirmDialog, type ConfirmDialogProps, type ControlledFormFactoryOptions, type CustomSliderProps, DataTable, type DataTableEditingProps, type DataTablePaginationMode, type DataTableProps, DatePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Dropdown, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type DropdownProps, type EditDisplayMode, type EditTrigger, type EditableColumnDef, Field, FieldMessage, type FieldMessageProps, type FieldProps, FocusedScrollView, Footer, type FooterProps, type FooterVariant, Form, type FormController, FormDialog, type FormDialogAction, type FormDialogProps, type FormProps, Icon, Input, InputFilter, type InputFilterProps, type InputProps, Label, Loading, type MaskRule, MaskedTextInput, type MaskedTextInputProps, Menu, DropdownMenuItem as MenuItem, type MenuItemType, DropdownMenuLabel as MenuLabel, type MenuOption, type MenuProps, DropdownMenuSeparator as MenuSeparator, Navbar, type NavbarProps, type NavbarVariant, NumberInput, type NumberInputProps, type OptionLike, type Options$1 as Options, OtpInput, OtpInputGroup, type OtpInputGroupProps, type OtpInputProps, PasswordInput, type PasswordInputProps, Popover, PopoverContent, PopoverTrigger, ProgressBar, RadioGroup, RadioGroupItem, ScrollArea, type ScrollAreaProps, type ScrollbarSize, Search, type SearchProps, SeverityBadge, type SeverityBadgeProps, type SeverityLevel, Slider, type SliderProps, Switch, THEME_COLOR_KEYS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TablePagination, type TablePaginationProps, TableRow, Tabs, Text, TextArea, type TextAreaProps, TextInput, type ThemeColorKey, Toast$1 as Toast, ToastAction, type ToastActionElement, ToastClose, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipSimple, TooltipTrigger, Tree, type TreeData, TreeItem, type TreeItemProps, type TreeProps, type UseControlledFormOptions, type UseOptionBridgeOptions, ValidationHintList, type ValidationHintListProps, type ValidationHintMode, type ValidationHintRule, type ValidationHintState, cn, createControlledForm, createYupResolver, getEndDateOfDay, getLucideIconNames, getStartDateOfDay, getStartEndTimestampOfDay, getThemeColor, getThemeColors, getTimestampUTC, menuItemBaseStyles, reducer, resloveTimestamp, srgbToHex, toast, useControlledForm, useOptionBridge, usePrevious, useToast };
package/dist/index.js CHANGED
@@ -11,6 +11,8 @@ export { default as TextArea } from "./components/TextArea/TextArea";
11
11
  export { default as Text } from "./components/Text/Text";
12
12
  export { default as Tabs } from "./components/Tabs/Tabs";
13
13
  export { default as Dropdown } from "./components/Dropdown/Dropdown";
14
+ export { menuItemBaseStyles } from "./components/Dropdown/Dropdown";
15
+ export { default as AutoComplete } from "./components/AutoComplete/AutoComplete";
14
16
  export { Checkbox } from "./components/Checkbox/Checkbox";
15
17
  export { Label } from "./components/Label/Label";
16
18
  export { Input } from "./components/Input/Input";
@@ -4761,6 +4761,10 @@ input[type=number] {
4761
4761
  max-width: 28rem;
4762
4762
  }
4763
4763
 
4764
+ .max-w-sm {
4765
+ max-width: 24rem;
4766
+ }
4767
+
4764
4768
  .flex-1 {
4765
4769
  flex: 1 1 0%;
4766
4770
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rovula/ui",
3
- "version": "0.1.41",
3
+ "version": "0.1.42",
4
4
  "main": "dist/cjs/bundle.js",
5
5
  "module": "dist/esm/bundle.js",
6
6
  "types": "dist/index.d.ts",