@gooddata/sdk-ui-kit 11.42.0-alpha.1 → 11.42.0-alpha.3

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 (68) hide show
  1. package/esm/@ui/UiAutocomplete/UiAutocomplete.d.ts +9 -0
  2. package/esm/@ui/UiAutocomplete/UiAutocomplete.d.ts.map +1 -0
  3. package/esm/@ui/UiAutocomplete/UiAutocomplete.js +230 -0
  4. package/esm/@ui/UiAutocomplete/types.d.ts +61 -0
  5. package/esm/@ui/UiAutocomplete/types.d.ts.map +1 -0
  6. package/esm/@ui/UiAutocomplete/types.js +2 -0
  7. package/esm/@ui/UiAutocomplete/useAsyncListSource.d.ts +42 -0
  8. package/esm/@ui/UiAutocomplete/useAsyncListSource.d.ts.map +1 -0
  9. package/esm/@ui/UiAutocomplete/useAsyncListSource.js +112 -0
  10. package/esm/@ui/UiCombobox/UiComboboxInput.d.ts +27 -4
  11. package/esm/@ui/UiCombobox/UiComboboxInput.d.ts.map +1 -1
  12. package/esm/@ui/UiCombobox/UiComboboxInput.js +38 -31
  13. package/esm/@ui/UiCombobox/UiComboboxList.js +2 -2
  14. package/esm/@ui/UiCombobox/UiComboboxListItem.d.ts +3 -13
  15. package/esm/@ui/UiCombobox/UiComboboxListItem.d.ts.map +1 -1
  16. package/esm/@ui/UiCombobox/UiComboboxListItem.js +13 -23
  17. package/esm/@ui/UiCombobox/UiComboboxPopup.d.ts +6 -3
  18. package/esm/@ui/UiCombobox/UiComboboxPopup.d.ts.map +1 -1
  19. package/esm/@ui/UiCombobox/UiComboboxPopup.js +5 -7
  20. package/esm/@ui/UiCombobox/types.d.ts +17 -9
  21. package/esm/@ui/UiCombobox/types.d.ts.map +1 -1
  22. package/esm/@ui/UiCombobox/useCombobox.d.ts.map +1 -1
  23. package/esm/@ui/UiCombobox/useCombobox.js +66 -161
  24. package/esm/@ui/UiCombobox/useComboboxChrome.d.ts +20 -0
  25. package/esm/@ui/UiCombobox/useComboboxChrome.d.ts.map +1 -0
  26. package/esm/@ui/UiCombobox/useComboboxChrome.js +89 -0
  27. package/esm/@ui/UiCombobox/useComboboxSelection.d.ts +23 -0
  28. package/esm/@ui/UiCombobox/useComboboxSelection.d.ts.map +1 -0
  29. package/esm/@ui/UiCombobox/useComboboxSelection.js +78 -0
  30. package/esm/@ui/UiDropdown/UiDropdown.js +3 -3
  31. package/esm/@ui/UiFloatingElement/UiFloatingElement.d.ts.map +1 -1
  32. package/esm/@ui/UiFloatingElement/UiFloatingElement.js +3 -2
  33. package/esm/@ui/UiFloatingPanel/UiFloatingPanel.d.ts +28 -0
  34. package/esm/@ui/UiFloatingPanel/UiFloatingPanel.d.ts.map +1 -0
  35. package/esm/@ui/UiFloatingPanel/UiFloatingPanel.js +14 -0
  36. package/esm/@ui/UiTags/UiTags.d.ts.map +1 -1
  37. package/esm/@ui/UiTags/UiTags.js +2 -2
  38. package/esm/@ui/UiTextInput/UiTextInput.d.ts +13 -2
  39. package/esm/@ui/UiTextInput/UiTextInput.d.ts.map +1 -1
  40. package/esm/@ui/UiTextInput/UiTextInput.js +2 -2
  41. package/esm/@ui/UiTooltip/UiTooltip.d.ts.map +1 -1
  42. package/esm/@ui/UiTooltip/UiTooltip.js +10 -4
  43. package/esm/@ui/hooks/useCloseOnOutsideClick.d.ts +31 -0
  44. package/esm/@ui/hooks/useCloseOnOutsideClick.d.ts.map +1 -1
  45. package/esm/@ui/hooks/useCloseOnOutsideClick.js +73 -6
  46. package/esm/Tabs/Tabs.d.ts +2 -1
  47. package/esm/Tabs/Tabs.d.ts.map +1 -1
  48. package/esm/Tabs/Tabs.js +1 -1
  49. package/esm/WidgetNotice/WidgetNotice.d.ts.map +1 -1
  50. package/esm/WidgetNotice/WidgetNotice.js +1 -1
  51. package/esm/index.d.ts +5 -2
  52. package/esm/index.d.ts.map +1 -1
  53. package/esm/index.js +2 -0
  54. package/esm/locales.d.ts +17 -0
  55. package/esm/locales.d.ts.map +1 -1
  56. package/esm/locales.js +7 -0
  57. package/esm/sdk-ui-kit.d.ts +166 -31
  58. package/package.json +11 -11
  59. package/src/@ui/UiAutocomplete/UiAutocomplete.scss +53 -0
  60. package/src/@ui/UiCombobox/UiCombobox.scss +0 -16
  61. package/src/@ui/UiDropdown/UiDropdown.scss +1 -20
  62. package/src/@ui/UiFloatingPanel/UiFloatingPanel.scss +27 -0
  63. package/src/@ui/UiPopover/UiPopover.scss +8 -0
  64. package/src/@ui/UiTags/UiTags.scss +0 -4
  65. package/src/@ui/UiTextInput/UiTextInput.scss +6 -2
  66. package/src/@ui/index.scss +2 -0
  67. package/styles/css/main.css +64 -28
  68. package/styles/css/main.css.map +1 -1
@@ -0,0 +1,9 @@
1
+ import type { IUiAutocompleteOption, IUiAutocompleteProps } from "./types.js";
2
+ /**
3
+ * Async autocomplete: text input + sectioned listbox driven by a `loadOptions`
4
+ * loader. Implements the ARIA combobox+listbox APG pattern.
5
+ *
6
+ * @internal
7
+ */
8
+ export declare function UiAutocomplete<T extends IUiAutocompleteOption = IUiAutocompleteOption>({ loadOptions, selectedIds, onSelect, debounceMs, messages, accessibilityConfig, dataTestId }: IUiAutocompleteProps<T>): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=UiAutocomplete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UiAutocomplete.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiAutocomplete/UiAutocomplete.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAA0B,MAAM,YAAY,CAAC;AA+BtG;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,qBAAqB,GAAG,qBAAqB,EAAE,EACpF,WAAW,EACX,WAA6B,EAC7B,QAAQ,EACR,UAAgC,EAChC,QAAQ,EACR,mBAAmB,EACnB,UAAU,EACb,EAAE,oBAAoB,CAAC,CAAC,CAAC,2CAkOzB"}
@@ -0,0 +1,230 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { Fragment, useCallback, useId, useMemo } from "react";
4
+ import { useIntl } from "react-intl";
5
+ import { uiAutocompleteMessages } from "../../locales.js";
6
+ import { bem } from "../@utils/bem.js";
7
+ import { makeKeyboardNavigation } from "../@utils/keyboardNavigation.js";
8
+ import { UiComboboxContextProvider } from "../UiCombobox/UiComboboxContext.js";
9
+ import { UiComboboxInput } from "../UiCombobox/UiComboboxInput.js";
10
+ import { UiComboboxListItem } from "../UiCombobox/UiComboboxListItem.js";
11
+ import { UiComboboxPopup } from "../UiCombobox/UiComboboxPopup.js";
12
+ import { useComboboxChrome } from "../UiCombobox/useComboboxChrome.js";
13
+ import { UiSectionHeading } from "../UiSectionHeading/UiSectionHeading.js";
14
+ import { useAsyncListSource } from "./useAsyncListSource.js";
15
+ const { b, e } = bem("gd-ui-kit-autocomplete");
16
+ const DEFAULT_DEBOUNCE_MS = 400;
17
+ // Per-instance, per-generation synthetic id for the Load-more row; activating
18
+ // it triggers a page fetch instead of `onSelect`. `listboxId` keeps it unique
19
+ // across autocompletes on one page; `generation` makes it differ once the
20
+ // query reloads, so a stale highlight can't carry onto the next query's row.
21
+ const loadMoreId = (listboxId, generation) => `${listboxId}-load-more-${generation}`;
22
+ // Stable default so an omitted `selectedIds` doesn't feed a fresh array into the
23
+ // memo deps every render.
24
+ const NO_SELECTED_IDS = [];
25
+ // Mirrors `useCombobox`'s key map. Space, Home and End are left to the input
26
+ // so the user can edit the query text natively.
27
+ const autocompleteKeys = makeKeyboardNavigation({
28
+ onArrowDown: [{ code: "ArrowDown" }],
29
+ onArrowUp: [{ code: "ArrowUp" }],
30
+ onEnter: [{ code: ["Enter", "NumpadEnter"] }],
31
+ onEscape: [{ code: "Escape" }],
32
+ });
33
+ /**
34
+ * Async autocomplete: text input + sectioned listbox driven by a `loadOptions`
35
+ * loader. Implements the ARIA combobox+listbox APG pattern.
36
+ *
37
+ * @internal
38
+ */
39
+ export function UiAutocomplete({ loadOptions, selectedIds = NO_SELECTED_IDS, onSelect, debounceMs = DEFAULT_DEBOUNCE_MS, messages, accessibilityConfig, dataTestId, }) {
40
+ const intl = useIntl();
41
+ const listboxId = useId();
42
+ const copy = useMemo(() => ({
43
+ searchPlaceholder: messages?.searchPlaceholder ?? intl.formatMessage(uiAutocompleteMessages.searchPlaceholder),
44
+ stateLoading: messages?.stateLoading ?? intl.formatMessage(uiAutocompleteMessages.stateLoading),
45
+ stateError: messages?.stateError ?? intl.formatMessage(uiAutocompleteMessages.stateError),
46
+ stateNoMatch: messages?.stateNoMatch ?? intl.formatMessage(uiAutocompleteMessages.stateNoMatch),
47
+ loadMore: messages?.loadMore ?? intl.formatMessage(uiAutocompleteMessages.loadMore),
48
+ }), [intl, messages]);
49
+ const source = useAsyncListSource(loadOptions, { debounceMs });
50
+ // The Load-more row's id is stamped with the load generation, so a highlight
51
+ // left on it before a query change can't re-attach to the next query's row
52
+ // (a constant id would survive and let Enter page the wrong query — the
53
+ // synthetic row is the one id the by-id highlight tracking can't otherwise
54
+ // tell apart across queries, since real options carry distinct ids).
55
+ const loadMoreRowId = loadMoreId(listboxId, source.generation);
56
+ const selectedIdSet = useMemo(() => new Set(selectedIds), [selectedIds]);
57
+ // Flat list of the rows the highlight can land on. Section headings and
58
+ // status rows render around it but never participate.
59
+ const focusableOptions = useMemo(() => {
60
+ const options = [];
61
+ for (const section of source.sections) {
62
+ for (const option of section.options) {
63
+ if (selectedIdSet.has(option.id)) {
64
+ continue;
65
+ }
66
+ options.push({ id: option.id, label: option.label });
67
+ }
68
+ }
69
+ if (source.hasNextPage && source.status !== "loadingMore") {
70
+ options.push({ id: loadMoreRowId, label: copy.loadMore });
71
+ }
72
+ return options;
73
+ }, [source.sections, source.hasNextPage, source.status, selectedIdSet, copy.loadMore, loadMoreRowId]);
74
+ // Chrome tracks the highlight by row id, so a row that disappears (results
75
+ // change, Load-more row removed while its page loads) drops the highlight
76
+ // on its own — no manual resets to keep in sync.
77
+ const chrome = useComboboxChrome(focusableOptions);
78
+ const activeOptionData = useMemo(() => {
79
+ if (!chrome.activeOption) {
80
+ return undefined;
81
+ }
82
+ if (chrome.activeOption.id === loadMoreRowId) {
83
+ return "loadMore";
84
+ }
85
+ return findOptionById(source.sections, chrome.activeOption.id);
86
+ }, [chrome.activeOption, source.sections, loadMoreRowId]);
87
+ const handleSelect = useCallback((target) => {
88
+ if (target === "loadMore") {
89
+ // Drop the highlight while the next page loads: the Load-more row
90
+ // disappears, and a real option highlighted beforehand (e.g. clicked
91
+ // Load-more without hovering it first) must not stay Enter-armed.
92
+ chrome.setActiveIndex(null);
93
+ source.loadMore();
94
+ return;
95
+ }
96
+ onSelect(target);
97
+ // Clear the input + re-prime the loader so the next open shows the
98
+ // unfiltered first page rather than the previous query's results.
99
+ source.reset();
100
+ chrome.setIsOpen(false);
101
+ }, [chrome, source, onSelect]);
102
+ // Reopening after a failed load re-runs it, so every open path (click, type,
103
+ // and the keyboard arrows below) routes through this first to recover.
104
+ const retryIfErrored = useCallback(() => {
105
+ if (!chrome.isOpen && source.status === "error") {
106
+ source.retry();
107
+ }
108
+ }, [chrome.isOpen, source]);
109
+ const onInputKeyDown = useMemo(() => {
110
+ const onEnter = chrome.isOpen && activeOptionData ? () => handleSelect(activeOptionData) : undefined;
111
+ // Leave Escape unhandled when idle so an enclosing modal can dismiss.
112
+ const hasSomethingToClose = chrome.isOpen || source.inputValue.length > 0;
113
+ const onEscape = hasSomethingToClose
114
+ ? (event) => {
115
+ // Stop the native event too so an enclosing UiModalDialog's
116
+ // document Escape listener doesn't dismiss the whole dialog.
117
+ event.nativeEvent.stopPropagation();
118
+ if (chrome.isOpen) {
119
+ chrome.setIsOpen(false);
120
+ return;
121
+ }
122
+ source.reset();
123
+ }
124
+ : undefined;
125
+ return autocompleteKeys({
126
+ onArrowDown: () => {
127
+ retryIfErrored();
128
+ chrome.focusByDelta(1);
129
+ },
130
+ onArrowUp: () => {
131
+ retryIfErrored();
132
+ chrome.focusByDelta(-1);
133
+ },
134
+ onEnter,
135
+ onEscape,
136
+ });
137
+ }, [chrome, source, activeOptionData, handleSelect, retryIfErrored]);
138
+ const selectOptionFromContext = useCallback((option) => {
139
+ if (option.id === loadMoreRowId) {
140
+ handleSelect("loadMore");
141
+ return;
142
+ }
143
+ const resolved = findOptionById(source.sections, option.id);
144
+ if (resolved) {
145
+ handleSelect(resolved);
146
+ }
147
+ }, [handleSelect, source.sections, loadMoreRowId]);
148
+ // Stay visible across loading / error / no-match so the status row reaches
149
+ // the user; the sync combobox's "hide when empty" default does not apply here.
150
+ const shouldRenderPopup = chrome.isOpen;
151
+ const setIsOpen = useCallback((open) => {
152
+ if (open) {
153
+ retryIfErrored();
154
+ }
155
+ chrome.setIsOpen(open);
156
+ }, [chrome, retryIfErrored]);
157
+ const state = useMemo(() => ({
158
+ inputValue: source.inputValue,
159
+ onInputChange: (next) => {
160
+ source.setInputValue(next);
161
+ setIsOpen(true);
162
+ },
163
+ onInputKeyDown,
164
+ onInputBlur: () => chrome.setIsOpen(false),
165
+ availableOptions: focusableOptions,
166
+ activeIndex: chrome.activeIndex,
167
+ setActiveIndex: chrome.setActiveIndex,
168
+ activeOption: chrome.activeOption,
169
+ selectedOption: undefined,
170
+ selectOption: selectOptionFromContext,
171
+ isOpen: chrome.isOpen,
172
+ setIsOpen,
173
+ shouldRenderPopup,
174
+ anchorRef: chrome.anchorRef,
175
+ registerItemRef: chrome.registerItemRef,
176
+ creatable: false,
177
+ listboxId,
178
+ }), [
179
+ chrome,
180
+ source,
181
+ setIsOpen,
182
+ focusableOptions,
183
+ shouldRenderPopup,
184
+ onInputKeyDown,
185
+ selectOptionFromContext,
186
+ listboxId,
187
+ ]);
188
+ const visibleSections = source.sections
189
+ .map((section) => ({
190
+ ...section,
191
+ options: section.options.filter((o) => !selectedIdSet.has(o.id)),
192
+ }))
193
+ .filter((section) => section.options.length > 0);
194
+ // "No matching options" must mean the search found nothing — not that every
195
+ // match was hidden because it's already selected (a successful search). Key
196
+ // it off the loader's own result, before the selected-id filter.
197
+ const loaderReturnedNothing = source.sections.every((section) => section.options.length === 0);
198
+ const showEmptyState = source.status === "idle" && loaderReturnedNothing && !source.hasNextPage;
199
+ return (_jsx("div", { className: b(), "data-testid": dataTestId, children: _jsxs(UiComboboxContextProvider, { state: state, children: [
200
+ _jsx(UiComboboxInput, { placeholder: copy.searchPlaceholder, accessibilityConfig: accessibilityConfig }), _jsx(UiComboboxPopup, { children: _jsxs("ul", { className: e("list"), role: "listbox", id: listboxId, tabIndex: -1, children: [source.status === "loading" ? _jsx(StatusRow, { text: copy.stateLoading }) : null, source.status === "error" ? _jsx(StatusRow, { text: copy.stateError }) : null, visibleSections.length > 0 ? (_jsx(Sections, { sections: visibleSections, focusableOptions: focusableOptions })) : null, source.hasNextPage && source.status !== "loadingMore" ? (_jsx(LoadMoreRow, { id: loadMoreRowId, index: focusableOptions.findIndex((o) => o.id === loadMoreRowId), label: copy.loadMore })) : null, source.status === "loadingMore" ? _jsx(StatusRow, { text: copy.stateLoading }) : null, showEmptyState ? _jsx(StatusRow, { text: copy.stateNoMatch }) : null] }) })
201
+ ] }) }));
202
+ }
203
+ // `index` on each item must be its position in `focusableOptions` — chrome's
204
+ // active-index navigation and item-ref registry are keyed off that.
205
+ function Sections({ sections, focusableOptions, }) {
206
+ return sections.map((section) => (_jsxs(Fragment, { children: [
207
+ _jsx("li", { role: "presentation", className: e("section-header"), children: _jsx(UiSectionHeading, { label: section.label }) }), section.options.map((option) => {
208
+ const index = focusableOptions.findIndex((o) => o.id === option.id);
209
+ if (index < 0) {
210
+ return null;
211
+ }
212
+ return (_jsxs(UiComboboxListItem, { option: { id: option.id, label: option.label }, index: index, className: e("option"), children: [
213
+ _jsx("span", { className: e("option-label"), children: option.label }), option.secondaryText ? (_jsx("span", { className: e("option-secondary"), children: option.secondaryText })) : null] }, option.id));
214
+ })] }, section.id)));
215
+ }
216
+ function StatusRow({ text }) {
217
+ return (_jsx("li", { role: "presentation", className: e("state"), children: text }));
218
+ }
219
+ function LoadMoreRow({ id, index, label }) {
220
+ return (_jsx(UiComboboxListItem, { option: { id, label }, index: index, className: e("load-more"), children: _jsx("span", { children: label }) }));
221
+ }
222
+ function findOptionById(sections, id) {
223
+ for (const section of sections) {
224
+ const found = section.options.find((o) => o.id === id);
225
+ if (found) {
226
+ return found;
227
+ }
228
+ }
229
+ return undefined;
230
+ }
@@ -0,0 +1,61 @@
1
+ import { type IAccessibilityConfigBase } from "../../typings/accessibility.js";
2
+ /**
3
+ * Minimal option shape; specialized pickers map their domain objects onto it.
4
+ *
5
+ * @internal
6
+ */
7
+ export interface IUiAutocompleteOption {
8
+ id: string;
9
+ label: string;
10
+ /** Secondary label rendered muted next to the primary label. */
11
+ secondaryText?: string;
12
+ }
13
+ /** @internal */
14
+ export interface IUiAutocompleteSection<T extends IUiAutocompleteOption = IUiAutocompleteOption> {
15
+ id: string;
16
+ label: string;
17
+ options: T[];
18
+ }
19
+ /**
20
+ * User-facing copy overrides. Omitted fields fall back to the kit default.
21
+ *
22
+ * @internal
23
+ */
24
+ export interface IUiAutocompleteMessages {
25
+ searchPlaceholder?: string;
26
+ stateLoading?: string;
27
+ stateError?: string;
28
+ stateNoMatch?: string;
29
+ loadMore?: string;
30
+ }
31
+ /** @internal */
32
+ export interface IUiAutocompleteLoadResult<T extends IUiAutocompleteOption = IUiAutocompleteOption> {
33
+ sections: IUiAutocompleteSection<T>[];
34
+ /** Show a "Load more" row whose activation calls the loader with the next page. */
35
+ hasNextPage?: boolean;
36
+ }
37
+ /** @internal */
38
+ export interface IUiAutocompleteProps<T extends IUiAutocompleteOption = IUiAutocompleteOption> {
39
+ /**
40
+ * Called with the debounced search and zero-based `page` index. Page 0
41
+ * fires on every query change; subsequent pages fire on Load-more.
42
+ *
43
+ * Must be referentially stable (memoize with `useCallback`) — it is a
44
+ * fetch dependency, so a new identity each render re-runs the page-0 query.
45
+ */
46
+ loadOptions: (search: string, page: number) => Promise<IUiAutocompleteLoadResult<T>>;
47
+ /** Filtered out of the dropdown so the user cannot pick the same option twice. */
48
+ selectedIds?: ReadonlyArray<string>;
49
+ onSelect: (option: T) => void;
50
+ /** Debounce delay for the input → loader path. Defaults to 400 ms. */
51
+ debounceMs?: number;
52
+ messages?: IUiAutocompleteMessages;
53
+ /**
54
+ * Forwarded to the search input for the accessible name / description.
55
+ * The combobox-internal attributes (`role`, `ariaExpanded`, `ariaControls`,
56
+ * `ariaAutocomplete`) are owned by the component and cannot be overridden.
57
+ */
58
+ accessibilityConfig?: IAccessibilityConfigBase;
59
+ dataTestId?: string;
60
+ }
61
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiAutocomplete/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE/E;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,gBAAgB;AAChB,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,qBAAqB,GAAG,qBAAqB;IAC3F,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,EAAE,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,gBAAgB;AAChB,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,qBAAqB,GAAG,qBAAqB;IAC9F,QAAQ,EAAE,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,mFAAmF;IACnF,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,gBAAgB;AAChB,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,qBAAqB,GAAG,qBAAqB;IACzF;;;;;;OAMG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,kFAAkF;IAClF,WAAW,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,wEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,wBAAwB,CAAC;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB"}
@@ -0,0 +1,2 @@
1
+ // (C) 2026 GoodData Corporation
2
+ export {};
@@ -0,0 +1,42 @@
1
+ import type { IUiAutocompleteOption, IUiAutocompleteSection } from "./types.js";
2
+ type LoadResult<T extends IUiAutocompleteOption> = {
3
+ sections: IUiAutocompleteSection<T>[];
4
+ hasNextPage?: boolean;
5
+ };
6
+ /** @internal */
7
+ export type AsyncListSourceLoader<T extends IUiAutocompleteOption> = (search: string, page: number) => Promise<LoadResult<T>>;
8
+ /** @internal */
9
+ export interface IUseAsyncListSourceOptions {
10
+ debounceMs: number;
11
+ }
12
+ /**
13
+ * `loadingMore` keeps prior pages visible while the next page is in flight;
14
+ * `error` blanks out the list.
15
+ *
16
+ * @internal
17
+ */
18
+ export type AsyncListStatus = "loading" | "loadingMore" | "idle" | "error";
19
+ /** @internal */
20
+ export interface IAsyncListSource<T extends IUiAutocompleteOption> {
21
+ inputValue: string;
22
+ setInputValue: (next: string) => void;
23
+ sections: IUiAutocompleteSection<T>[];
24
+ status: AsyncListStatus;
25
+ hasNextPage: boolean;
26
+ loadMore: () => void;
27
+ reset: () => void;
28
+ /** Re-run the current page-0 query — used to recover from an error state. */
29
+ retry: () => void;
30
+ /** Increments on each page-0 load; lets callers tag per-query synthetic rows. */
31
+ generation: number;
32
+ }
33
+ /**
34
+ * Async data source for an autocomplete-shaped picker: debounce via
35
+ * `useDebouncedState`, fetching with stale-result protection via
36
+ * `useCancelablePromise`, section merge on pagination.
37
+ *
38
+ * @internal
39
+ */
40
+ export declare function useAsyncListSource<T extends IUiAutocompleteOption>(loadOptions: AsyncListSourceLoader<T>, { debounceMs }: IUseAsyncListSourceOptions): IAsyncListSource<T>;
41
+ export {};
42
+ //# sourceMappingURL=useAsyncListSource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAsyncListSource.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiAutocomplete/useAsyncListSource.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEhF,KAAK,UAAU,CAAC,CAAC,SAAS,qBAAqB,IAAI;IAC/C,QAAQ,EAAE,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,gBAAgB;AAChB,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,qBAAqB,IAAI,CACjE,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,KACX,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5B,gBAAgB;AAChB,MAAM,WAAW,0BAA0B;IACvC,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3E,gBAAgB;AAChB,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,qBAAqB;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,MAAM,EAAE,eAAe,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,+EAA6E;IAC7E,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;CACtB;AAeD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,qBAAqB,EAC9D,WAAW,EAAE,qBAAqB,CAAC,CAAC,CAAC,EACrC,EAAE,UAAU,EAAE,EAAE,0BAA0B,GAC3C,gBAAgB,CAAC,CAAC,CAAC,CAqHrB"}
@@ -0,0 +1,112 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { useCallback, useMemo, useState } from "react";
3
+ import { useCancelablePromise, useDebouncedState } from "@gooddata/sdk-ui";
4
+ /**
5
+ * Async data source for an autocomplete-shaped picker: debounce via
6
+ * `useDebouncedState`, fetching with stale-result protection via
7
+ * `useCancelablePromise`, section merge on pagination.
8
+ *
9
+ * @internal
10
+ */
11
+ export function useAsyncListSource(loadOptions, { debounceMs }) {
12
+ const [inputValue, setInputValue, debouncedQuery, setInputValueImmediate] = useDebouncedState("", debounceMs);
13
+ // Bumping `retryToken` re-runs page-0 even when the query is unchanged, so a
14
+ // failed load can recover (e.g. when the popup is reopened) without the user
15
+ // having to edit the search text.
16
+ const [retryToken, setRetryToken] = useState(0);
17
+ const retry = useCallback(() => setRetryToken((t) => t + 1), []);
18
+ // Each page-0 load bumps the generation; Load-more pages are tagged with the
19
+ // generation they belong to and ignored once it advances. Counting loads
20
+ // (not comparing result objects) stays correct even if a loader returns the
21
+ // same object for a repeated query.
22
+ const [generation, setGeneration] = useState(0);
23
+ const queryLoad = useCancelablePromise({ promise: () => loadOptions(debouncedQuery, 0), onSuccess: () => setGeneration((g) => g + 1) }, [debouncedQuery, loadOptions, retryToken]);
24
+ const [paginationState, setPagination] = useState(null);
25
+ const pagination = paginationState?.generation === generation ? paginationState : null;
26
+ const pendingPage = pagination?.pendingPage ?? null;
27
+ // While the typed value is ahead of the debounced one the fetch has not
28
+ // started yet, but the UI must already report loading (and below, drop the
29
+ // sections) so the previous query's options are not left clickable.
30
+ const isDebouncing = inputValue !== debouncedQuery;
31
+ const isQueryLoading = queryLoad.status === "pending" || queryLoad.status === "loading";
32
+ useCancelablePromise({
33
+ // Hold pagination until page-0 of the current query has settled, so a
34
+ // query change mid-pagination can't fetch the new query at an old page.
35
+ promise: pendingPage == null || isDebouncing || isQueryLoading
36
+ ? null
37
+ : () => loadOptions(debouncedQuery, pendingPage),
38
+ onSuccess: (result) => setPagination((prev) => prev?.pendingPage == null
39
+ ? prev
40
+ : {
41
+ generation: prev.generation,
42
+ sections: mergeSections(prev.sections, result.sections),
43
+ pagesLoaded: prev.pagesLoaded + 1,
44
+ hasNextPage: !!result.hasNextPage,
45
+ pendingPage: null,
46
+ }),
47
+ // Keep the already-loaded pages; dropping back to idle re-shows the
48
+ // Load-more row so the user can retry the failed page.
49
+ onError: () => setPagination((prev) => (prev ? { ...prev, pendingPage: null } : prev)),
50
+ }, [pendingPage, debouncedQuery, loadOptions, isDebouncing, isQueryLoading]);
51
+ const status = isDebouncing || isQueryLoading
52
+ ? "loading"
53
+ : queryLoad.status === "error"
54
+ ? "error"
55
+ : pendingPage == null
56
+ ? "idle"
57
+ : "loadingMore";
58
+ const sections = useMemo(() => {
59
+ if (status === "loading" || status === "error" || queryLoad.result === undefined) {
60
+ return [];
61
+ }
62
+ return pagination
63
+ ? mergeSections(queryLoad.result.sections, pagination.sections)
64
+ : queryLoad.result.sections;
65
+ }, [status, queryLoad.result, pagination]);
66
+ const hasNextPage = (status === "idle" || status === "loadingMore") &&
67
+ (pagination ? pagination.hasNextPage : !!queryLoad.result?.hasNextPage);
68
+ const loadMore = useCallback(() => {
69
+ if (status !== "idle" || !hasNextPage) {
70
+ return;
71
+ }
72
+ setPagination({
73
+ generation,
74
+ sections: pagination?.sections ?? [],
75
+ pagesLoaded: pagination?.pagesLoaded ?? 0,
76
+ hasNextPage,
77
+ pendingPage: (pagination?.pagesLoaded ?? 0) + 1,
78
+ });
79
+ }, [status, hasNextPage, generation, pagination]);
80
+ // `setInputValueImmediate` from useDebouncedState isn't memoized, but it only
81
+ // delegates to stable `useState` setters, so omitting it keeps `reset`
82
+ // referentially stable without going stale.
83
+ const reset = useCallback(() => {
84
+ setInputValueImmediate("");
85
+ setPagination(null);
86
+ // eslint-disable-next-line react-hooks/exhaustive-deps
87
+ }, []);
88
+ return useMemo(() => ({
89
+ inputValue,
90
+ setInputValue,
91
+ sections,
92
+ status,
93
+ hasNextPage,
94
+ loadMore,
95
+ reset,
96
+ retry,
97
+ generation,
98
+ }), [inputValue, setInputValue, sections, status, hasNextPage, loadMore, reset, retry, generation]);
99
+ }
100
+ function mergeSections(current, incoming) {
101
+ const merged = current.map((s) => ({ ...s, options: [...s.options] }));
102
+ for (const next of incoming) {
103
+ const existing = merged.find((s) => s.id === next.id);
104
+ if (existing) {
105
+ existing.options.push(...next.options);
106
+ }
107
+ else {
108
+ merged.push({ ...next, options: [...next.options] });
109
+ }
110
+ }
111
+ return merged;
112
+ }
@@ -1,6 +1,29 @@
1
- import { type InputHTMLAttributes } from "react";
1
+ import { type FocusEvent, type KeyboardEvent, type MouseEvent } from "react";
2
+ import { type IAccessibilityConfigBase } from "../../typings/accessibility.js";
2
3
  /** @internal */
3
- export type UiComboboxInputProps = InputHTMLAttributes<HTMLInputElement>;
4
- /** @internal */
5
- export declare const UiComboboxInput: import("react").ForwardRefExoticComponent<UiComboboxInputProps & import("react").RefAttributes<HTMLInputElement>>;
4
+ export interface IUiComboboxInputProps {
5
+ /**
6
+ * Accessible name/description for the input (e.g. `ariaLabel`,
7
+ * `ariaDescribedBy`). The combobox role and listbox-wiring attributes are
8
+ * owned by the component and override anything passed here.
9
+ */
10
+ accessibilityConfig?: IAccessibilityConfigBase;
11
+ /** Visible placeholder. */
12
+ placeholder?: string;
13
+ /** Form field name forwarded to the underlying input. */
14
+ name?: string;
15
+ autoFocus?: boolean;
16
+ onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
17
+ onFocus?: (event: FocusEvent<HTMLInputElement>) => void;
18
+ onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
19
+ onClick?: (event: MouseEvent<HTMLInputElement>) => void;
20
+ dataTestId?: string;
21
+ }
22
+ /**
23
+ * Binds `UiTextInput` to the surrounding `UiCombobox` state: value, keyboard
24
+ * handler, open/close, ARIA combobox+listbox attributes.
25
+ *
26
+ * @internal
27
+ */
28
+ export declare const UiComboboxInput: import("react").ForwardRefExoticComponent<IUiComboboxInputProps & import("react").RefAttributes<HTMLInputElement>>;
6
29
  //# sourceMappingURL=UiComboboxInput.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UiComboboxInput.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiCombobox/UiComboboxInput.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGH,KAAK,mBAAmB,EAG3B,MAAM,OAAO,CAAC;AAQf,gBAAgB;AAChB,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;AAEzE,gBAAgB;AAChB,eAAO,MAAM,eAAe,mHAqD3B,CAAC"}
1
+ {"version":3,"file":"UiComboboxInput.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiCombobox/UiComboboxInput.tsx"],"names":[],"mappings":"AAEA,OAAO,EACH,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,EAIlB,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAK/E,gBAAgB;AAChB,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,wBAAwB,CAAC;IAC/C,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACxD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,oHAsF3B,CAAC"}
@@ -1,37 +1,44 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- // (C) 2025 GoodData Corporation
3
- import { forwardRef, } from "react";
4
- import { useMergeRefs } from "@floating-ui/react";
5
- import cx from "classnames";
6
- import { e } from "./comboboxBem.js";
2
+ // (C) 2025-2026 GoodData Corporation
3
+ import { forwardRef, useCallback, } from "react";
4
+ import { UiTextInput } from "../UiTextInput/UiTextInput.js";
7
5
  import { useComboboxState } from "./UiComboboxContext.js";
8
- /** @internal */
6
+ /**
7
+ * Binds `UiTextInput` to the surrounding `UiCombobox` state: value, keyboard
8
+ * handler, open/close, ARIA combobox+listbox attributes.
9
+ *
10
+ * @internal
11
+ */
9
12
  export const UiComboboxInput = forwardRef(function UiComboboxInput(props, forwardedRef) {
10
- const { type, className, ...htmlInputProps } = props;
11
- const { inputValue, onInputChange, onInputKeyDown, onInputBlur, setReferenceRef, getReferenceProps, activeOption, } = useComboboxState();
12
- const ref = useMergeRefs([forwardedRef, setReferenceRef]);
13
- const referenceProps = getReferenceProps({
14
- ...htmlInputProps,
15
- autoComplete: "off",
16
- autoCapitalize: "none",
17
- autoCorrect: "off",
18
- // Most of the aria attributes already come from `getReferenceProps`
19
- "aria-activedescendant": activeOption?.id,
20
- "aria-autocomplete": "list",
21
- onKeyDown: handleKeyDown,
22
- onBlur: handleBlur,
23
- });
24
- function handleChange(event) {
25
- onInputChange(event.target.value);
26
- htmlInputProps.onChange?.(event);
27
- }
28
- function handleKeyDown(event) {
13
+ const { accessibilityConfig, placeholder, name, autoFocus, onKeyDown: callerOnKeyDown, onFocus: callerOnFocus, onBlur: callerOnBlur, onClick: callerOnClick, dataTestId, } = props;
14
+ const { inputValue, onInputChange, onInputKeyDown, onInputBlur, isOpen, setIsOpen, anchorRef, activeOption, listboxId, } = useComboboxState();
15
+ const handleKeyDown = useCallback((event) => {
29
16
  onInputKeyDown(event);
30
- htmlInputProps.onKeyDown?.(event);
31
- }
32
- function handleBlur(event) {
17
+ if (!event.isDefaultPrevented()) {
18
+ callerOnKeyDown?.(event);
19
+ }
20
+ }, [onInputKeyDown, callerOnKeyDown]);
21
+ const handleBlur = useCallback((event) => {
33
22
  onInputBlur();
34
- htmlInputProps.onBlur?.(event);
35
- }
36
- return (_jsx("input", { ...referenceProps, ref: ref, className: cx(e("input"), className), type: type ?? "text", value: inputValue, onChange: handleChange }));
23
+ callerOnBlur?.(event);
24
+ }, [onInputBlur, callerOnBlur]);
25
+ // Click toggles open state (matches floating-ui's default `useClick`),
26
+ // so the user can also click to close. Focus alone doesn't open —
27
+ // Tab / programmatic focus shouldn't expand the listbox.
28
+ const handleClick = useCallback((event) => {
29
+ setIsOpen(!isOpen);
30
+ callerOnClick?.(event);
31
+ }, [isOpen, setIsOpen, callerOnClick]);
32
+ return (_jsx(UiTextInput, { inputRef: forwardedRef, wrapperRef: anchorRef, value: inputValue, onChange: onInputChange, name: name, placeholder: placeholder, autoFocus: autoFocus,
33
+ // Browser autofill would overlap the listbox; the combobox
34
+ // owns its own typeahead so we suppress all native suggestions.
35
+ autoComplete: "off", autoCapitalize: "none", autoCorrect: "off", dataTestId: dataTestId, onKeyDown: handleKeyDown, onFocus: callerOnFocus, onBlur: handleBlur, onClick: handleClick, accessibilityConfig: {
36
+ ...accessibilityConfig,
37
+ role: "combobox",
38
+ ariaAutocomplete: "list",
39
+ ariaExpanded: isOpen,
40
+ ariaActiveDescendant: activeOption?.id,
41
+ ariaHaspopup: "listbox",
42
+ ariaControls: listboxId,
43
+ } }));
37
44
  });
@@ -7,6 +7,6 @@ import { useComboboxState } from "./UiComboboxContext.js";
7
7
  import { UiComboboxListItem } from "./UiComboboxListItem.js";
8
8
  /** @internal */
9
9
  export function UiComboboxList({ children, className, ...htmlProps }) {
10
- const { availableOptions } = useComboboxState();
11
- return (_jsx("ul", { role: "listbox", ...htmlProps, className: cx(e("list"), className), tabIndex: -1, children: availableOptions.map((option, index) => children ? (_jsx(Fragment, { children: children(option, index) }, option.id)) : (_jsx(UiComboboxListItem, { option: option, index: index }, option.id))) }));
10
+ const { availableOptions, listboxId } = useComboboxState();
11
+ return (_jsx("ul", { role: "listbox", ...htmlProps, id: listboxId, className: cx(e("list"), className), tabIndex: -1, children: availableOptions.map((option, index) => children ? (_jsx(Fragment, { children: children(option, index) }, option.id)) : (_jsx(UiComboboxListItem, { option: option, index: index }, option.id))) }));
12
12
  }
@@ -11,28 +11,18 @@ type UiComboboxListItemImplProps = IUiComboboxListItemProps & {
11
11
  isActive: boolean;
12
12
  isSelected: boolean;
13
13
  isDisabled: boolean;
14
- getItemProps: IUiComboboxState["getItemProps"];
15
14
  registerItemRef: IUiComboboxState["registerItemRef"];
15
+ setActiveIndex: IUiComboboxState["setActiveIndex"];
16
16
  selectOption: IUiComboboxState["selectOption"];
17
17
  };
18
18
  export declare const UiComboboxListItemImpl: import("react").NamedExoticComponent<UiComboboxListItemImplProps>;
19
19
  /** @internal */
20
20
  export type UiComboboxListItemLabelProps = HTMLAttributes<HTMLSpanElement>;
21
- /**
22
- * Renders the primary label content within a combobox list item.
23
- * Use this component for composable customization of list item content.
24
- *
25
- * @internal
26
- */
21
+ /** @internal */
27
22
  export declare function UiComboboxListItemLabel(props: UiComboboxListItemLabelProps): import("react/jsx-runtime").JSX.Element;
28
23
  /** @internal */
29
24
  export type UiComboboxListItemCreatableLabelProps = HTMLAttributes<HTMLSpanElement>;
30
- /**
31
- * Renders the "creatable" label suffix within a combobox list item.
32
- * Use this component for composable customization of list item content.
33
- *
34
- * @internal
35
- */
25
+ /** @internal */
36
26
  export declare function UiComboboxListItemCreatableLabel(props: UiComboboxListItemCreatableLabelProps): import("react/jsx-runtime").JSX.Element;
37
27
  export {};
38
28
  //# sourceMappingURL=UiComboboxListItem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UiComboboxListItem.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiCombobox/UiComboboxListItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAyB,MAAM,OAAO,CAAC;AAKnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtE,gBAAgB;AAChB,MAAM,WAAW,wBAAyB,SAAQ,cAAc,CAAC,aAAa,CAAC;IAC3E,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,gBAAgB;AAChB,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,wBAAwB,2CAmBjE;AAED,KAAK,2BAA2B,GAAG,wBAAwB,GAAG;IAC1D,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,eAAe,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;IACrD,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;CAClD,CAAC;AAEF,eAAO,MAAM,sBAAsB,mEAuDjC,CAAC;AAEH,gBAAgB;AAChB,MAAM,MAAM,4BAA4B,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAE3E;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,2CAO1E;AAED,gBAAgB;AAChB,MAAM,MAAM,qCAAqC,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAEpF;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,qCAAqC,2CAO5F"}
1
+ {"version":3,"file":"UiComboboxListItem.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiCombobox/UiComboboxListItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAyB,MAAM,OAAO,CAAC;AAKnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtE,gBAAgB;AAChB,MAAM,WAAW,wBAAyB,SAAQ,cAAc,CAAC,aAAa,CAAC;IAC3E,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,gBAAgB;AAChB,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,wBAAwB,2CAoBjE;AAED,KAAK,2BAA2B,GAAG,wBAAwB,GAAG;IAC1D,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;IACrD,cAAc,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IACnD,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;CAClD,CAAC;AAEF,eAAO,MAAM,sBAAsB,mEAyDjC,CAAC;AAEH,gBAAgB;AAChB,MAAM,MAAM,4BAA4B,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAE3E,gBAAgB;AAChB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,2CAO1E;AAED,gBAAgB;AAChB,MAAM,MAAM,qCAAqC,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAEpF,gBAAgB;AAChB,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,qCAAqC,2CAO5F"}