@backstage/ui 0.15.1-next.0 → 0.16.0

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 (52) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/dist/components/Combobox/Combobox.esm.js +150 -52
  3. package/dist/components/Combobox/Combobox.esm.js.map +1 -1
  4. package/dist/components/Combobox/Combobox.module.css.esm.js +2 -2
  5. package/dist/components/Combobox/ComboboxItem.esm.js +76 -0
  6. package/dist/components/Combobox/ComboboxItem.esm.js.map +1 -0
  7. package/dist/components/Combobox/ComboboxListBox.esm.js +215 -17
  8. package/dist/components/Combobox/ComboboxListBox.esm.js.map +1 -1
  9. package/dist/components/Combobox/definition.esm.js +62 -3
  10. package/dist/components/Combobox/definition.esm.js.map +1 -1
  11. package/dist/components/Combobox/useAsyncComboboxState.esm.js +133 -0
  12. package/dist/components/Combobox/useAsyncComboboxState.esm.js.map +1 -0
  13. package/dist/components/Header/HeaderNav.esm.js +0 -1
  14. package/dist/components/Header/HeaderNav.esm.js.map +1 -1
  15. package/dist/components/Select/Select.esm.js +87 -19
  16. package/dist/components/Select/Select.esm.js.map +1 -1
  17. package/dist/components/Select/Select.module.css.esm.js +2 -2
  18. package/dist/components/Select/SelectContent.esm.js +70 -18
  19. package/dist/components/Select/SelectContent.esm.js.map +1 -1
  20. package/dist/components/Select/SelectItem.esm.js +76 -0
  21. package/dist/components/Select/SelectItem.esm.js.map +1 -0
  22. package/dist/components/Select/SelectListBox.esm.js +175 -19
  23. package/dist/components/Select/SelectListBox.esm.js.map +1 -1
  24. package/dist/components/Select/SelectTrigger.esm.js +1 -1
  25. package/dist/components/Select/SelectTrigger.esm.js.map +1 -1
  26. package/dist/components/Select/definition.esm.js +72 -9
  27. package/dist/components/Select/definition.esm.js.map +1 -1
  28. package/dist/components/Skeleton/Skeleton.module.css.esm.js +2 -2
  29. package/dist/components/Skeleton/definition.esm.js +1 -0
  30. package/dist/components/Skeleton/definition.esm.js.map +1 -1
  31. package/dist/components/Table/Table.module.css.esm.js +2 -2
  32. package/dist/components/Table/components/Table.esm.js +60 -57
  33. package/dist/components/Table/components/Table.esm.js.map +1 -1
  34. package/dist/components/Table/definition.esm.js +2 -1
  35. package/dist/components/Table/definition.esm.js.map +1 -1
  36. package/dist/components/TablePagination/TablePagination.esm.js +4 -1
  37. package/dist/components/TablePagination/TablePagination.esm.js.map +1 -1
  38. package/dist/components/Tabs/TabsIndicators.esm.js +155 -108
  39. package/dist/components/Tabs/TabsIndicators.esm.js.map +1 -1
  40. package/dist/css/styles.css +4 -4
  41. package/dist/hooks/useCollectionAdapter.esm.js +67 -0
  42. package/dist/hooks/useCollectionAdapter.esm.js.map +1 -0
  43. package/dist/hooks/useDelayedVisibility.esm.js +17 -0
  44. package/dist/hooks/useDelayedVisibility.esm.js.map +1 -0
  45. package/dist/hooks/useTrackedSelectionKeys.esm.js +23 -0
  46. package/dist/hooks/useTrackedSelectionKeys.esm.js.map +1 -0
  47. package/dist/index.d.ts +742 -77
  48. package/dist/index.esm.js +5 -2
  49. package/dist/index.esm.js.map +1 -1
  50. package/dist/utils/selectableCollection.esm.js +75 -0
  51. package/dist/utils/selectableCollection.esm.js.map +1 -0
  52. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,172 @@
1
1
  # @backstage/ui
2
2
 
3
+ ## 0.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fc4e624: `Combobox` now supports async collections, incremental loading, client and server search, and rich or custom item rendering. Loading placeholders expose `.bui-ComboboxLoading` and `.bui-ComboboxLoadingRow`, and stale visible results expose `data-stale` on `.bui-ComboboxList`.
8
+
9
+ **BREAKING**: The public `ComboboxProps` interface is now a union type.
10
+
11
+ **Migration:**
12
+
13
+ **Required on upgrade:**
14
+
15
+ Replace interfaces that extend `ComboboxProps` with type intersections.
16
+
17
+ ```diff
18
+ - interface MyComboboxProps extends ComboboxProps {
19
+ - trackingId: string;
20
+ - }
21
+ + type MyComboboxProps = ComboboxProps & {
22
+ + trackingId: string;
23
+ + };
24
+ ```
25
+
26
+ **Optional migration away from deprecated APIs:**
27
+
28
+ Prefer `id` instead of `value` for plain options. Existing array-valued options using `value` remain supported as a deprecated compatibility path, but new option content fields and async option sources require `id`.
29
+
30
+ Move input state and custom filtering into the nested `search` configuration:
31
+
32
+ ```diff
33
+ - <Combobox inputValue={query} onInputChange={setQuery} />
34
+ + <Combobox search={{ inputValue: query, onInputChange: setQuery }} />
35
+ ```
36
+
37
+ The existing top-level input state props remain supported as a deprecated compatibility path for plain-array `options`.
38
+
39
+ **Affected components:** Combobox
40
+
41
+ - fc4e624: `Select` now supports async collections, incremental loading, client and server search, and rich or custom item rendering. Loading placeholders expose `.bui-SelectLoading` and `.bui-SelectLoadingRow`, and stale retained results expose `data-stale` on `.bui-SelectList`.
42
+
43
+ **BREAKING**: The public `SelectProps` interface is now a union type, and Select popover list content is no longer a direct child of `.bui-SelectPopover`.
44
+
45
+ **Migration:**
46
+
47
+ **Required on upgrade:**
48
+
49
+ Replace interfaces that extend `SelectProps` with type intersections.
50
+
51
+ ```diff
52
+ - interface MySelectProps extends SelectProps {
53
+ - trackingId: string;
54
+ - }
55
+ + type MySelectProps = SelectProps & {
56
+ + trackingId: string;
57
+ + };
58
+ ```
59
+
60
+ Update CSS selectors that rely on list content being a direct child of `.bui-SelectPopover`. Select popovers now use the standard BUI Popover content structure, with contents wrapped in `.bui-Box.bui-PopoverContent`. The existing `.bui-Popover.bui-SelectPopover` root classes are unchanged.
61
+
62
+ **Optional migration away from deprecated APIs:**
63
+
64
+ Prefer `id` instead of `value` for plain options. Existing array-valued options using `value` remain supported as a deprecated compatibility path, but new option content fields and async option sources require `id`.
65
+
66
+ Replace `searchable` and `searchPlaceholder` with nested `search` configuration:
67
+
68
+ ```diff
69
+ - <Select searchable searchPlaceholder="Search owners" />
70
+ + <Select search={{ placeholder: 'Search owners' }} />
71
+ ```
72
+
73
+ **Affected components:** Select
74
+
75
+ ### Patch Changes
76
+
77
+ - 3d6c2e4: Updated the dark theme neutral background tokens to provide clearer contrast between neutral surfaces.
78
+ - c86efcd: Fixed the Table component not filling its container width in Firefox. The `overflow` style is now applied to a wrapper element instead of the `<table>` element directly, which avoids a Firefox behavior where non-visible overflow on tables causes them to shrink-wrap to content size.
79
+ - adf94f5: Make Skeleton component background aware, automatically adjusting its color to maintain visible contrast against neutral parent surfaces.
80
+
81
+ **Affected components:** Skeleton
82
+
83
+ - b06b3c7: Fixed header tab links to respect the configured router `basename`.
84
+
85
+ **Affected components:** Header
86
+
87
+ - 14a101f: Switch now adapts its track and thumb colors based on the background context of its parent container, and uses the accent token family when selected.
88
+
89
+ **Affected components:** Switch
90
+
91
+ - 66c4e55: Fixed tab indicator not updating position when tab content changes width dynamically.
92
+ - b33bb24: Added a new `NumberField` component for numeric input with support for min, max, step, and keyboard increment/decrement.
93
+
94
+ **Affected components:** NumberField
95
+
96
+ - 350407d: Fixed async pagination in `Combobox` and `Select` popovers so additional pages load as users scroll instead of loading every page immediately. `Combobox` now uses `.bui-PopoverContent` as its scroll container, while all `Select` variants use the new `.bui-SelectResults` results container.
97
+
98
+ Searchable `Select` keeps its search field fixed while results scroll. The new public classes `.bui-SelectContent` and `.bui-SelectResults` expose this layout for theme customization.
99
+
100
+ **Affected components:** Combobox, Select
101
+
102
+ - e989f95: Fixed `Combobox` client search crashing when used with plain options.
103
+
104
+ **Affected components:** Combobox
105
+
106
+ - 1f709a3: Fixed Header breadcrumb typography so it remains consistent when component styles are loaded in different orders.
107
+
108
+ **Affected components:** Header
109
+
110
+ - 5d80f77: Introduces a new set of semantic color token families — Accent, Announcement, Warning, Negative, and Positive — each providing a consistent set of background, foreground, and border tokens for both light and dark themes. A gray scale (`--bui-gray-1` through `--bui-gray-11`) and updated foreground tokens are also included.
111
+
112
+ The previous tokens remain in place for backward compatibility but are now deprecated and will be removed in a future release.
113
+
114
+ **Migration:**
115
+
116
+ **Neutral backgrounds**
117
+
118
+ The neutral background tokens keep their existing names (`--bui-bg-app`, `--bui-bg-neutral-1` through `--bui-bg-neutral-4`) but are updated with new solid-color values for both light and dark themes. No token renaming is required. The `-hover`, `-pressed`, and `-disabled` interaction variants of these tokens are deprecated and should be removed.
119
+
120
+ **Foreground**
121
+
122
+ | Deprecated | Replacement |
123
+ | ------------------ | ----------------------- |
124
+ | `--bui-fg-danger` | `--bui-fg-negative` |
125
+ | `--bui-fg-success` | `--bui-fg-positive` |
126
+ | `--bui-fg-info` | `--bui-fg-announcement` |
127
+
128
+ **Accent**
129
+
130
+ | Deprecated | Replacement |
131
+ | ------------------------- | -------------------------- |
132
+ | `--bui-bg-solid` | `--bui-accent-bg` |
133
+ | `--bui-bg-solid-hover` | `--bui-accent-bg-hover` |
134
+ | `--bui-bg-solid-disabled` | `--bui-accent-bg-disabled` |
135
+ | `--bui-fg-solid` | `--bui-accent-fg` |
136
+ | `--bui-fg-solid-disabled` | `--bui-accent-fg-disabled` |
137
+
138
+ **Positive**
139
+
140
+ | Deprecated | Replacement |
141
+ | ------------------------ | --------------------------- |
142
+ | `--bui-bg-success` | `--bui-positive-bg-subdued` |
143
+ | `--bui-fg-success-on-bg` | `--bui-positive-fg-subdued` |
144
+ | `--bui-border-success` | `--bui-positive-border` |
145
+
146
+ **Negative**
147
+
148
+ | Deprecated | Replacement |
149
+ | ----------------------- | --------------------------- |
150
+ | `--bui-bg-danger` | `--bui-negative-bg-subdued` |
151
+ | `--bui-fg-danger-on-bg` | `--bui-negative-fg-subdued` |
152
+ | `--bui-border-danger` | `--bui-negative-border` |
153
+
154
+ **Warning**
155
+
156
+ | Deprecated | Replacement |
157
+ | ------------------------ | -------------------------- |
158
+ | `--bui-bg-warning` | `--bui-warning-bg-subdued` |
159
+ | `--bui-fg-warning-on-bg` | `--bui-warning-fg-subdued` |
160
+ | `--bui-border-warning` | `--bui-warning-border` |
161
+
162
+ **Announcement**
163
+
164
+ | Deprecated | Replacement |
165
+ | --------------------- | ------------------------------- |
166
+ | `--bui-bg-info` | `--bui-announcement-bg-subdued` |
167
+ | `--bui-fg-info-on-bg` | `--bui-announcement-fg-subdued` |
168
+ | `--bui-border-info` | `--bui-announcement-border` |
169
+
3
170
  ## 0.15.1-next.0
4
171
 
5
172
  ### Patch Changes
@@ -12,60 +12,158 @@ import { FieldError } from '../FieldError/FieldError.esm.js';
12
12
  import '../FieldError/FieldError.module.css.esm.js';
13
13
  import { ComboboxInput } from './ComboboxInput.esm.js';
14
14
  import { ComboboxListBox } from './ComboboxListBox.esm.js';
15
+ import { useCollectionAdapter } from '../../hooks/useCollectionAdapter.esm.js';
16
+ import { resolveCollectionSource, isAsyncListSource } from '../../utils/selectableCollection.esm.js';
17
+ import { useAsyncComboboxState, getAsyncComboboxItemTextValue } from './useAsyncComboboxState.esm.js';
15
18
 
16
- const Combobox = forwardRef(
17
- (props, ref) => {
18
- const { contains } = useFilter({ sensitivity: "base" });
19
- const { ownProps, restProps, dataAttributes } = useDefinition(
20
- ComboboxDefinition,
21
- props
22
- );
23
- const {
24
- classes,
25
- label,
26
- description,
27
- options,
28
- icon,
29
- placeholder,
30
- isRequired,
31
- secondaryLabel
32
- } = ownProps;
33
- const ariaLabel = restProps["aria-label"];
34
- const ariaLabelledBy = restProps["aria-labelledby"];
35
- useEffect(() => {
36
- if (!label && !ariaLabel && !ariaLabelledBy) {
37
- console.warn(
38
- "Combobox requires either a visible label, aria-label, or aria-labelledby for accessibility"
39
- );
40
- }
41
- }, [label, ariaLabel, ariaLabelledBy]);
42
- const secondaryLabelText = secondaryLabel || (isRequired ? "Required" : null);
43
- return /* @__PURE__ */ jsxs(
44
- ComboBox,
45
- {
46
- className: classes.root,
47
- defaultFilter: contains,
48
- ...dataAttributes,
49
- ref,
50
- ...restProps,
51
- children: [
52
- /* @__PURE__ */ jsx(
53
- FieldLabel,
54
- {
55
- label,
56
- secondaryLabel: secondaryLabelText,
57
- description,
58
- descriptionSlot: "description"
59
- }
60
- ),
61
- /* @__PURE__ */ jsx(ComboboxInput, { icon, placeholder }),
62
- /* @__PURE__ */ jsx(FieldError, {}),
63
- /* @__PURE__ */ jsx(Popover, { className: classes.popover, hideArrow: true, ...dataAttributes, children: /* @__PURE__ */ jsx(ComboboxListBox, { options }) })
64
- ]
65
- }
66
- );
19
+ function resolveComboboxStateProps({
20
+ runtimeState,
21
+ asyncState,
22
+ collection,
23
+ hasSearch
24
+ }) {
25
+ if (asyncState) {
26
+ return asyncState;
67
27
  }
68
- );
28
+ const selectionProps = {
29
+ value: runtimeState.value,
30
+ defaultValue: runtimeState.defaultValue,
31
+ onChange: runtimeState.onChange
32
+ };
33
+ if (hasSearch) {
34
+ return {
35
+ ...selectionProps,
36
+ inputValue: collection.inputValue,
37
+ defaultInputValue: collection.defaultInputValue,
38
+ onInputChange: collection.onInputChange
39
+ };
40
+ }
41
+ return {
42
+ ...selectionProps,
43
+ inputValue: runtimeState.inputValue,
44
+ defaultInputValue: runtimeState.defaultInputValue,
45
+ onInputChange: runtimeState.onInputChange
46
+ };
47
+ }
48
+ function ComboboxImpl(props, ref) {
49
+ const { contains } = useFilter({ sensitivity: "base" });
50
+ const { ownProps, restProps, dataAttributes } = useDefinition(
51
+ ComboboxDefinition,
52
+ props
53
+ );
54
+ const {
55
+ classes,
56
+ label,
57
+ description,
58
+ options,
59
+ items,
60
+ children,
61
+ dependencies,
62
+ icon,
63
+ placeholder,
64
+ isRequired,
65
+ secondaryLabel,
66
+ search,
67
+ loading
68
+ } = ownProps;
69
+ const ariaLabel = restProps["aria-label"];
70
+ const ariaLabelledBy = restProps["aria-labelledby"];
71
+ useEffect(() => {
72
+ if (!label && !ariaLabel && !ariaLabelledBy) {
73
+ console.warn(
74
+ "Combobox requires either a visible label, aria-label, or aria-labelledby for accessibility"
75
+ );
76
+ }
77
+ }, [label, ariaLabel, ariaLabelledBy]);
78
+ const secondaryLabelText = secondaryLabel || (isRequired ? "Required" : null);
79
+ const collectionSource = resolveCollectionSource({
80
+ options,
81
+ items
82
+ });
83
+ const collection = useCollectionAdapter({
84
+ items: collectionSource.source,
85
+ search,
86
+ loading,
87
+ retainSelectedItems: false
88
+ });
89
+ const renderedItems = collectionSource.rendersItems ? collection.canonicalItems : void 0;
90
+ const rootItems = renderedItems ?? (collectionSource.options !== void 0 && search !== void 0 ? collection.canonicalItems : void 0);
91
+ const searchProps = typeof search === "object" ? search : void 0;
92
+ const isDirectAsyncServer = searchProps?.mode === "server" && isAsyncListSource(collectionSource.source);
93
+ const shouldDisableRootFilter = searchProps?.mode === "server" || searchProps?.filter !== void 0;
94
+ const {
95
+ value,
96
+ defaultValue,
97
+ onChange,
98
+ inputValue,
99
+ defaultInputValue,
100
+ onInputChange,
101
+ ...ariaProps
102
+ } = restProps;
103
+ const asyncComboboxProps = isDirectAsyncServer ? {
104
+ source: collectionSource.source,
105
+ value,
106
+ defaultValue,
107
+ onChange,
108
+ allowsCustomValue: restProps.allowsCustomValue
109
+ } : void 0;
110
+ const asyncComboboxState = useAsyncComboboxState(asyncComboboxProps);
111
+ const comboboxStateProps = resolveComboboxStateProps({
112
+ runtimeState: {
113
+ value,
114
+ defaultValue,
115
+ onChange,
116
+ inputValue,
117
+ defaultInputValue,
118
+ onInputChange
119
+ },
120
+ asyncState: asyncComboboxState,
121
+ collection,
122
+ hasSearch: search !== void 0
123
+ });
124
+ const defaultFilter = shouldDisableRootFilter ? () => true : contains;
125
+ const getItemTextValue = isDirectAsyncServer && items !== void 0 ? getAsyncComboboxItemTextValue : void 0;
126
+ return /* @__PURE__ */ jsxs(
127
+ ComboBox,
128
+ {
129
+ className: classes.root,
130
+ defaultFilter,
131
+ items: rootItems,
132
+ ...dataAttributes,
133
+ ref,
134
+ ...ariaProps,
135
+ ...comboboxStateProps,
136
+ allowsEmptyCollection: true,
137
+ children: [
138
+ /* @__PURE__ */ jsx(
139
+ FieldLabel,
140
+ {
141
+ label,
142
+ secondaryLabel: secondaryLabelText,
143
+ description,
144
+ descriptionSlot: "description"
145
+ }
146
+ ),
147
+ /* @__PURE__ */ jsx(ComboboxInput, { icon, placeholder }),
148
+ /* @__PURE__ */ jsx(FieldError, {}),
149
+ /* @__PURE__ */ jsx(Popover, { className: classes.popover, hideArrow: true, ...dataAttributes, children: /* @__PURE__ */ jsx(
150
+ ComboboxListBox,
151
+ {
152
+ options: collectionSource.options,
153
+ items: renderedItems,
154
+ dependencies,
155
+ search,
156
+ loading: collection.loading,
157
+ isStale: collection.isStale,
158
+ getItemTextValue,
159
+ children
160
+ }
161
+ ) })
162
+ ]
163
+ }
164
+ );
165
+ }
166
+ const Combobox = forwardRef(ComboboxImpl);
69
167
  Combobox.displayName = "Combobox";
70
168
 
71
169
  export { Combobox };
@@ -1 +1 @@
1
- {"version":3,"file":"Combobox.esm.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { forwardRef, useEffect } from 'react';\nimport { ComboBox as AriaComboBox } from 'react-aria-components';\nimport { useFilter } from 'react-aria';\nimport { ComboboxProps } from './types';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { ComboboxDefinition } from './definition';\nimport { Popover } from '../Popover';\nimport { FieldLabel } from '../FieldLabel';\nimport { FieldError } from '../FieldError';\nimport { ComboboxInput } from './ComboboxInput';\nimport { ComboboxListBox } from './ComboboxListBox';\n\n/**\n * A text input combined with a dropdown list of options. The user can type to filter\n * suggestions, navigate with the keyboard, and pick a value. With `allowsCustomValue`\n * the typed text can be committed even if no option matches.\n *\n * @public\n */\nexport const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(\n (props, ref) => {\n const { contains } = useFilter({ sensitivity: 'base' });\n const { ownProps, restProps, dataAttributes } = useDefinition(\n ComboboxDefinition,\n props,\n );\n const {\n classes,\n label,\n description,\n options,\n icon,\n placeholder,\n isRequired,\n secondaryLabel,\n } = ownProps;\n\n const ariaLabel = restProps['aria-label'];\n const ariaLabelledBy = restProps['aria-labelledby'];\n\n useEffect(() => {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n 'Combobox requires either a visible label, aria-label, or aria-labelledby for accessibility',\n );\n }\n }, [label, ariaLabel, ariaLabelledBy]);\n\n const secondaryLabelText =\n secondaryLabel || (isRequired ? 'Required' : null);\n\n return (\n <AriaComboBox\n className={classes.root}\n defaultFilter={contains}\n {...dataAttributes}\n ref={ref}\n {...restProps}\n >\n <FieldLabel\n label={label}\n secondaryLabel={secondaryLabelText}\n description={description}\n descriptionSlot=\"description\"\n />\n <ComboboxInput icon={icon} placeholder={placeholder} />\n <FieldError />\n <Popover className={classes.popover} hideArrow {...dataAttributes}>\n <ComboboxListBox options={options} />\n </Popover>\n </AriaComboBox>\n );\n },\n);\n\nCombobox.displayName = 'Combobox';\n"],"names":["AriaComboBox"],"mappings":";;;;;;;;;;;;;;;AAmCO,MAAM,QAAA,GAAW,UAAA;AAAA,EACtB,CAAC,OAAO,GAAA,KAAQ;AACd,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,UAAU,EAAE,WAAA,EAAa,QAAQ,CAAA;AACtD,IAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,cAAA,EAAe,GAAI,aAAA;AAAA,MAC9C,kBAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAM;AAAA,MACJ,OAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF,GAAI,QAAA;AAEJ,IAAA,MAAM,SAAA,GAAY,UAAU,YAAY,CAAA;AACxC,IAAA,MAAM,cAAA,GAAiB,UAAU,iBAAiB,CAAA;AAElD,IAAA,SAAA,CAAU,MAAM;AACd,MAAA,IAAI,CAAC,KAAA,IAAS,CAAC,SAAA,IAAa,CAAC,cAAA,EAAgB;AAC3C,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN;AAAA,SACF;AAAA,MACF;AAAA,IACF,CAAA,EAAG,CAAC,KAAA,EAAO,SAAA,EAAW,cAAc,CAAC,CAAA;AAErC,IAAA,MAAM,kBAAA,GACJ,cAAA,KAAmB,UAAA,GAAa,UAAA,GAAa,IAAA,CAAA;AAE/C,IAAA,uBACE,IAAA;AAAA,MAACA,QAAA;AAAA,MAAA;AAAA,QACC,WAAW,OAAA,CAAQ,IAAA;AAAA,QACnB,aAAA,EAAe,QAAA;AAAA,QACd,GAAG,cAAA;AAAA,QACJ,GAAA;AAAA,QACC,GAAG,SAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,KAAA;AAAA,cACA,cAAA,EAAgB,kBAAA;AAAA,cAChB,WAAA;AAAA,cACA,eAAA,EAAgB;AAAA;AAAA,WAClB;AAAA,0BACA,GAAA,CAAC,aAAA,EAAA,EAAc,IAAA,EAAY,WAAA,EAA0B,CAAA;AAAA,8BACpD,UAAA,EAAA,EAAW,CAAA;AAAA,0BACZ,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAW,OAAA,CAAQ,OAAA,EAAS,SAAA,EAAS,IAAA,EAAE,GAAG,cAAA,EACjD,QAAA,kBAAA,GAAA,CAAC,eAAA,EAAA,EAAgB,OAAA,EAAkB,CAAA,EACrC;AAAA;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA;;;;"}
1
+ {"version":3,"file":"Combobox.esm.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { forwardRef, useEffect } from 'react';\nimport { ComboBox as AriaComboBox } from 'react-aria-components';\nimport { useFilter } from 'react-aria';\nimport type {\n ComboboxAsyncItemsProps,\n ComboboxAsyncOptionsProps,\n ComboboxItemsProps,\n ComboboxListBoxOwnProps,\n ComboboxOptionsProps,\n ComboboxProps,\n ComboboxServerItem,\n ComboboxServerItemsProps,\n ComboboxServerOptionsProps,\n ComboboxStaticProps,\n} from './types';\nimport type { Key } from 'react-aria-components';\nimport type {\n AsyncListSource,\n CollectionItem,\n NormalizedOption,\n} from '../../types/selectableCollection';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { ComboboxDefinition } from './definition';\nimport { Popover } from '../Popover';\nimport { FieldLabel } from '../FieldLabel';\nimport { FieldError } from '../FieldError';\nimport { ComboboxInput } from './ComboboxInput';\nimport { ComboboxListBox } from './ComboboxListBox';\nimport {\n useCollectionAdapter,\n type CollectionAdapterResult,\n} from '../../hooks/useCollectionAdapter';\nimport {\n isAsyncListSource,\n resolveCollectionSource,\n} from '../../utils/selectableCollection';\nimport {\n getAsyncComboboxItemTextValue,\n useAsyncComboboxState,\n} from './useAsyncComboboxState';\n\ntype ComboboxRuntimeStateProps<T extends CollectionItem> = {\n value?: Key | T | null;\n defaultValue?: Key | T | null;\n onChange?: ((value: Key | null) => void) | ((value: T | null) => void);\n inputValue?: string;\n defaultInputValue?: string;\n onInputChange?: (value: string) => void;\n};\n\ntype ComboboxAriaStateProps = {\n value?: Key | null;\n defaultValue?: Key | null;\n onChange?: (value: Key | null) => void;\n inputValue?: string;\n defaultInputValue?: string;\n onInputChange?: (value: string) => void;\n};\n\ntype AsyncComboboxState = {\n value: Key | null;\n inputValue: string;\n onChange: (value: Key | null) => void;\n onInputChange: (value: string) => void;\n};\n\nfunction resolveComboboxStateProps<T extends CollectionItem>({\n runtimeState,\n asyncState,\n collection,\n hasSearch,\n}: {\n runtimeState: ComboboxRuntimeStateProps<T>;\n asyncState?: AsyncComboboxState;\n collection: CollectionAdapterResult<T>;\n hasSearch: boolean;\n}): ComboboxAriaStateProps {\n if (asyncState) {\n return asyncState;\n }\n\n const selectionProps = {\n value: runtimeState.value as Key | null | undefined,\n defaultValue: runtimeState.defaultValue as Key | null | undefined,\n onChange: runtimeState.onChange as\n | ((value: Key | null) => void)\n | undefined,\n };\n\n if (hasSearch) {\n return {\n ...selectionProps,\n inputValue: collection.inputValue,\n defaultInputValue: collection.defaultInputValue,\n onInputChange: collection.onInputChange,\n };\n }\n\n return {\n ...selectionProps,\n inputValue: runtimeState.inputValue,\n defaultInputValue: runtimeState.defaultInputValue,\n onInputChange: runtimeState.onInputChange,\n };\n}\n\n/**\n * A text input combined with a dropdown list of options. The user can type to filter\n * suggestions, navigate with the keyboard, and pick a value. With\n * `allowsCustomValue`, unmatched typed text can remain in the input without\n * selecting an option.\n *\n * @public\n */\nfunction ComboboxImpl<T extends CollectionItem = NormalizedOption>(\n props: ComboboxProps<T>,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const { contains } = useFilter({ sensitivity: 'base' });\n const { ownProps, restProps, dataAttributes } = useDefinition(\n ComboboxDefinition,\n props,\n );\n const {\n classes,\n label,\n description,\n options,\n items,\n children,\n dependencies,\n icon,\n placeholder,\n isRequired,\n secondaryLabel,\n search,\n loading,\n } = ownProps;\n\n const ariaLabel = restProps['aria-label'];\n const ariaLabelledBy = restProps['aria-labelledby'];\n\n useEffect(() => {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n 'Combobox requires either a visible label, aria-label, or aria-labelledby for accessibility',\n );\n }\n }, [label, ariaLabel, ariaLabelledBy]);\n\n const secondaryLabelText = secondaryLabel || (isRequired ? 'Required' : null);\n const collectionSource = resolveCollectionSource<T>({\n options,\n items: items as Iterable<T> | AsyncListSource<T> | undefined,\n });\n const collection = useCollectionAdapter({\n items: collectionSource.source,\n search,\n loading,\n retainSelectedItems: false,\n });\n const renderedItems = collectionSource.rendersItems\n ? collection.canonicalItems\n : undefined;\n const rootItems =\n renderedItems ??\n (collectionSource.options !== undefined && search !== undefined\n ? collection.canonicalItems\n : undefined);\n const searchProps = typeof search === 'object' ? search : undefined;\n const isDirectAsyncServer =\n searchProps?.mode === 'server' &&\n isAsyncListSource(collectionSource.source);\n const shouldDisableRootFilter =\n searchProps?.mode === 'server' || searchProps?.filter !== undefined;\n const {\n value,\n defaultValue,\n onChange,\n inputValue,\n defaultInputValue,\n onInputChange,\n ...ariaProps\n } = restProps as typeof restProps & ComboboxRuntimeStateProps<T>;\n const asyncComboboxProps = isDirectAsyncServer\n ? {\n source: collectionSource.source as AsyncListSource<T>,\n value: value as T | null | undefined,\n defaultValue: defaultValue as T | null | undefined,\n onChange: onChange as ((value: T | null) => void) | undefined,\n allowsCustomValue: restProps.allowsCustomValue,\n }\n : undefined;\n const asyncComboboxState = useAsyncComboboxState(asyncComboboxProps);\n const comboboxStateProps = resolveComboboxStateProps({\n runtimeState: {\n value,\n defaultValue,\n onChange,\n inputValue,\n defaultInputValue,\n onInputChange,\n },\n asyncState: asyncComboboxState,\n collection,\n hasSearch: search !== undefined,\n });\n const defaultFilter = shouldDisableRootFilter ? () => true : contains;\n const getItemTextValue =\n isDirectAsyncServer && items !== undefined\n ? getAsyncComboboxItemTextValue\n : undefined;\n\n return (\n <AriaComboBox<T>\n className={classes.root}\n defaultFilter={defaultFilter}\n items={rootItems}\n {...dataAttributes}\n ref={ref}\n {...ariaProps}\n {...comboboxStateProps}\n allowsEmptyCollection\n >\n <FieldLabel\n label={label}\n secondaryLabel={secondaryLabelText}\n description={description}\n descriptionSlot=\"description\"\n />\n <ComboboxInput icon={icon} placeholder={placeholder} />\n <FieldError />\n <Popover className={classes.popover} hideArrow {...dataAttributes}>\n <ComboboxListBox\n options={collectionSource.options}\n items={renderedItems}\n dependencies={dependencies}\n search={search as never}\n loading={collection.loading}\n isStale={collection.isStale}\n getItemTextValue={getItemTextValue}\n >\n {children as ComboboxListBoxOwnProps<T>['children']}\n </ComboboxListBox>\n </Popover>\n </AriaComboBox>\n );\n}\n\n/** @public */\nexport const Combobox = forwardRef(ComboboxImpl) as unknown as {\n (\n props: ComboboxOptionsProps & React.RefAttributes<HTMLDivElement>,\n ): React.ReactElement;\n (\n props: ComboboxAsyncOptionsProps & React.RefAttributes<HTMLDivElement>,\n ): React.ReactElement;\n <T extends { id: Key }>(\n props: ComboboxItemsProps<T> & React.RefAttributes<HTMLDivElement>,\n ): React.ReactElement;\n <T extends { id: Key }>(\n props: ComboboxAsyncItemsProps<T> & React.RefAttributes<HTMLDivElement>,\n ): React.ReactElement;\n (\n props: ComboboxStaticProps & React.RefAttributes<HTMLDivElement>,\n ): React.ReactElement;\n (\n props: ComboboxServerOptionsProps & React.RefAttributes<HTMLDivElement>,\n ): React.ReactElement;\n <T extends ComboboxServerItem>(\n props: ComboboxServerItemsProps<T> & React.RefAttributes<HTMLDivElement>,\n ): React.ReactElement;\n displayName?: string;\n};\n\nCombobox.displayName = 'Combobox';\n"],"names":["AriaComboBox"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import styleInject from '../../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
2
2
 
3
- var css_248z = "/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@layer tokens, base, components, utilities;\n\n@layer components {\n .Combobox_bui-Combobox__38e006d509,\n .Combobox_bui-ComboboxPopover__38e006d509 {\n &[data-size='small'] {\n --combobox-item-height: 2rem;\n }\n\n &[data-size='medium'] {\n --combobox-item-height: 2.5rem;\n }\n }\n\n .Combobox_bui-Combobox__38e006d509 {\n display: flex;\n flex-direction: column;\n width: 100%;\n flex: 1;\n }\n\n .Combobox_bui-ComboboxPopover__38e006d509 {\n min-width: var(--trigger-width);\n\n .bui-PopoverContent {\n padding: 0;\n }\n }\n\n .Combobox_bui-ComboboxInput__38e006d509 {\n box-sizing: border-box;\n border-radius: var(--bui-radius-3);\n border: none;\n outline: none;\n background-color: var(--bui-bg-neutral-1);\n transition: box-shadow 0.2s ease-in-out;\n\n &[data-on-bg='neutral-1'] {\n background-color: var(--bui-bg-neutral-2);\n }\n\n &[data-on-bg='neutral-2'] {\n background-color: var(--bui-bg-neutral-3);\n }\n\n &[data-on-bg='neutral-3'] {\n background-color: var(--bui-bg-neutral-4);\n }\n\n .Combobox_bui-Combobox__38e006d509[data-focus-within] & {\n box-shadow: inset 0 0 0 1px var(--bui-ring);\n }\n\n .Combobox_bui-Combobox__38e006d509[data-invalid] & {\n box-shadow: inset 0 0 0 1px var(--bui-border-danger);\n }\n\n display: flex;\n align-items: center;\n gap: var(--bui-space-2);\n width: 100%;\n height: var(--combobox-item-height);\n\n .Combobox_bui-Combobox__38e006d509[data-size='small'] & {\n padding-inline: var(--bui-space-3) 0;\n }\n\n .Combobox_bui-Combobox__38e006d509[data-size='medium'] & {\n padding-inline: var(--bui-space-4) 0;\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n }\n }\n\n .Combobox_bui-ComboboxInputIcon__38e006d509 {\n display: grid;\n place-content: center;\n flex-shrink: 0;\n color: var(--bui-fg-secondary);\n pointer-events: none;\n\n .Combobox_bui-Combobox__38e006d509[data-size='small'] & svg {\n width: 1rem;\n height: 1rem;\n }\n\n .Combobox_bui-Combobox__38e006d509[data-size='medium'] & svg {\n width: 1.25rem;\n height: 1.25rem;\n }\n }\n\n .Combobox_bui-ComboboxInputField__38e006d509 {\n flex: 1;\n min-width: 0;\n width: 100%;\n border: none;\n outline: none;\n background-color: transparent;\n padding: 0;\n color: var(--bui-fg-primary);\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n font-weight: var(--bui-font-weight-regular);\n line-height: var(--combobox-item-height);\n height: 100%;\n text-overflow: ellipsis;\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n\n &[disabled] {\n cursor: not-allowed;\n color: var(--bui-fg-disabled);\n }\n }\n\n .Combobox_bui-ComboboxInputChevron__38e006d509 {\n flex-shrink: 0;\n flex-grow: 0;\n display: grid;\n place-content: center;\n width: var(--combobox-item-height);\n height: var(--combobox-item-height);\n background-color: transparent;\n border: none;\n padding: 0;\n margin: 0;\n cursor: pointer;\n color: var(--bui-fg-secondary);\n outline: none;\n transition: color 0.2s ease-in-out;\n\n &:hover {\n color: var(--bui-fg-primary);\n }\n\n & svg {\n .Combobox_bui-Combobox__38e006d509[data-size='small'] & {\n width: 1rem;\n height: 1rem;\n }\n\n .Combobox_bui-Combobox__38e006d509[data-size='medium'] & {\n width: 1.25rem;\n height: 1.25rem;\n }\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: var(--bui-fg-disabled);\n }\n }\n\n .Combobox_bui-ComboboxList__38e006d509 {\n overflow: auto;\n min-height: 0;\n padding-block: var(--bui-space-1);\n padding-inline: var(--bui-space-1);\n\n &[data-focus-visible] {\n outline: none;\n }\n }\n\n .Combobox_bui-ComboboxItem__38e006d509 {\n box-sizing: border-box;\n position: relative;\n display: grid;\n grid-template-areas: 'icon text';\n grid-template-columns: 1rem 1fr;\n align-items: center;\n min-height: var(--combobox-item-height);\n padding-block: var(--bui-space-1);\n padding-left: var(--bui-space-3);\n padding-right: var(--bui-space-4);\n color: var(--bui-fg-primary);\n cursor: pointer;\n user-select: none;\n font-size: var(--bui-font-size-3);\n gap: var(--bui-space-2);\n outline: none;\n border-radius: var(--bui-radius-2);\n\n &[data-focused] {\n background-color: var(--bui-bg-neutral-2);\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: var(--bui-fg-disabled);\n }\n\n &[data-selected] .Combobox_bui-ComboboxItemIndicator__38e006d509 {\n opacity: 1;\n }\n }\n\n .Combobox_bui-ComboboxItemIndicator__38e006d509 {\n grid-area: icon;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.2s ease-in-out;\n }\n\n .Combobox_bui-ComboboxItemLabel__38e006d509 {\n flex: 1;\n grid-area: text;\n }\n\n .Combobox_bui-ComboboxSection__38e006d509 {\n &:first-child .Combobox_bui-ComboboxSectionHeader__38e006d509 {\n padding-top: 0;\n }\n }\n\n .Combobox_bui-ComboboxSectionHeader__38e006d509 {\n height: 2rem;\n display: flex;\n align-items: center;\n padding-top: var(--bui-space-3);\n padding-left: var(--bui-space-3);\n color: var(--bui-fg-primary);\n font-size: var(--bui-font-size-1);\n font-weight: bold;\n letter-spacing: 0.05rem;\n text-transform: uppercase;\n }\n\n .Combobox_bui-ComboboxNoResults__38e006d509 {\n padding-inline: var(--bui-space-3);\n padding-block: var(--bui-space-2);\n color: var(--bui-fg-secondary);\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n font-weight: var(--bui-font-weight-regular);\n }\n}\n";
4
- var styles = {"bui-Combobox":"Combobox_bui-Combobox__38e006d509","bui-ComboboxPopover":"Combobox_bui-ComboboxPopover__38e006d509","bui-ComboboxInput":"Combobox_bui-ComboboxInput__38e006d509","bui-ComboboxInputIcon":"Combobox_bui-ComboboxInputIcon__38e006d509","bui-ComboboxInputField":"Combobox_bui-ComboboxInputField__38e006d509","bui-ComboboxInputChevron":"Combobox_bui-ComboboxInputChevron__38e006d509","bui-ComboboxList":"Combobox_bui-ComboboxList__38e006d509","bui-ComboboxItem":"Combobox_bui-ComboboxItem__38e006d509","bui-ComboboxItemIndicator":"Combobox_bui-ComboboxItemIndicator__38e006d509","bui-ComboboxItemLabel":"Combobox_bui-ComboboxItemLabel__38e006d509","bui-ComboboxSection":"Combobox_bui-ComboboxSection__38e006d509","bui-ComboboxSectionHeader":"Combobox_bui-ComboboxSectionHeader__38e006d509","bui-ComboboxNoResults":"Combobox_bui-ComboboxNoResults__38e006d509"};
3
+ var css_248z = "/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@layer tokens, base, components, utilities;\n\n@layer components {\n .Combobox_bui-Combobox__1aa41a0b62,\n .Combobox_bui-ComboboxPopover__1aa41a0b62 {\n &[data-size='small'] {\n --combobox-item-height: 2rem;\n }\n\n &[data-size='medium'] {\n --combobox-item-height: 2.5rem;\n }\n }\n\n .Combobox_bui-Combobox__1aa41a0b62 {\n display: flex;\n flex-direction: column;\n width: 100%;\n flex: 1;\n }\n\n .Combobox_bui-ComboboxPopover__1aa41a0b62 {\n min-width: var(--trigger-width);\n\n .bui-PopoverContent {\n padding: 0;\n }\n }\n\n .Combobox_bui-ComboboxInput__1aa41a0b62 {\n box-sizing: border-box;\n border-radius: var(--bui-radius-3);\n border: none;\n outline: none;\n background-color: var(--bui-bg-neutral-1);\n transition: box-shadow 0.2s ease-in-out;\n\n &[data-on-bg='neutral-1'] {\n background-color: var(--bui-bg-neutral-2);\n }\n\n &[data-on-bg='neutral-2'] {\n background-color: var(--bui-bg-neutral-3);\n }\n\n &[data-on-bg='neutral-3'] {\n background-color: var(--bui-bg-neutral-4);\n }\n\n .Combobox_bui-Combobox__1aa41a0b62[data-focus-within] & {\n box-shadow: inset 0 0 0 1px var(--bui-ring);\n }\n\n .Combobox_bui-Combobox__1aa41a0b62[data-invalid] & {\n box-shadow: inset 0 0 0 1px var(--bui-border-danger);\n }\n\n display: flex;\n align-items: center;\n gap: var(--bui-space-2);\n width: 100%;\n height: var(--combobox-item-height);\n\n .Combobox_bui-Combobox__1aa41a0b62[data-size='small'] & {\n padding-inline: var(--bui-space-3) 0;\n }\n\n .Combobox_bui-Combobox__1aa41a0b62[data-size='medium'] & {\n padding-inline: var(--bui-space-4) 0;\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n }\n }\n\n .Combobox_bui-ComboboxInputIcon__1aa41a0b62 {\n display: grid;\n place-content: center;\n flex-shrink: 0;\n color: var(--bui-fg-secondary);\n pointer-events: none;\n\n .Combobox_bui-Combobox__1aa41a0b62[data-size='small'] & svg {\n width: 1rem;\n height: 1rem;\n }\n\n .Combobox_bui-Combobox__1aa41a0b62[data-size='medium'] & svg {\n width: 1.25rem;\n height: 1.25rem;\n }\n }\n\n .Combobox_bui-ComboboxInputField__1aa41a0b62 {\n flex: 1;\n min-width: 0;\n width: 100%;\n border: none;\n outline: none;\n background-color: transparent;\n padding: 0;\n color: var(--bui-fg-primary);\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n font-weight: var(--bui-font-weight-regular);\n line-height: var(--combobox-item-height);\n height: 100%;\n text-overflow: ellipsis;\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n\n &[disabled] {\n cursor: not-allowed;\n color: var(--bui-fg-disabled);\n }\n }\n\n .Combobox_bui-ComboboxInputChevron__1aa41a0b62 {\n flex-shrink: 0;\n flex-grow: 0;\n display: grid;\n place-content: center;\n width: var(--combobox-item-height);\n height: var(--combobox-item-height);\n background-color: transparent;\n border: none;\n padding: 0;\n margin: 0;\n cursor: pointer;\n color: var(--bui-fg-secondary);\n outline: none;\n transition: color 0.2s ease-in-out;\n\n &:hover {\n color: var(--bui-fg-primary);\n }\n\n & svg {\n .Combobox_bui-Combobox__1aa41a0b62[data-size='small'] & {\n width: 1rem;\n height: 1rem;\n }\n\n .Combobox_bui-Combobox__1aa41a0b62[data-size='medium'] & {\n width: 1.25rem;\n height: 1.25rem;\n }\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: var(--bui-fg-disabled);\n }\n }\n\n .Combobox_bui-ComboboxList__1aa41a0b62 {\n padding-block: var(--bui-space-1);\n padding-inline: var(--bui-space-1);\n transition: opacity 0.2s ease-in-out;\n\n &[data-stale] {\n opacity: 0.6;\n }\n\n &[data-focus-visible] {\n outline: none;\n }\n }\n\n .Combobox_bui-ComboboxItem__1aa41a0b62 {\n box-sizing: border-box;\n position: relative;\n display: block;\n min-height: var(--combobox-item-height);\n padding-block: var(--bui-space-1);\n padding-left: var(--bui-space-3);\n padding-right: var(--bui-space-4);\n color: var(--bui-fg-primary);\n cursor: pointer;\n user-select: none;\n font-size: var(--bui-font-size-3);\n outline: none;\n border-radius: var(--bui-radius-2);\n\n &:has(> .Combobox_bui-ComboboxItemIndicator__1aa41a0b62) {\n display: grid;\n grid-template-areas: 'icon text';\n grid-template-columns: 1rem 1fr;\n align-items: center;\n gap: var(--bui-space-2);\n }\n\n &[data-focused] {\n background-color: var(--bui-bg-neutral-2);\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: var(--bui-fg-disabled);\n }\n\n &[data-selected] .Combobox_bui-ComboboxItemIndicator__1aa41a0b62 {\n opacity: 1;\n }\n }\n\n .Combobox_bui-ComboboxItemIndicator__1aa41a0b62 {\n grid-area: icon;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.2s ease-in-out;\n }\n\n .Combobox_bui-ComboboxItemLabel__1aa41a0b62 {\n flex: 1;\n grid-area: text;\n }\n\n .Combobox_bui-ComboboxItemContent__1aa41a0b62 {\n display: flex;\n align-items: center;\n gap: var(--bui-space-2);\n grid-area: text;\n min-width: 0;\n }\n\n .Combobox_bui-ComboboxItemText__1aa41a0b62,\n .Combobox_bui-ComboboxItemProfile__1aa41a0b62 {\n min-width: 0;\n }\n\n .Combobox_bui-ComboboxItemTextLeadingIcon__1aa41a0b62 {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n\n & > svg {\n width: 1em;\n height: 1em;\n }\n }\n\n .Combobox_bui-ComboboxItemAvatar__1aa41a0b62 {\n flex-shrink: 0;\n }\n\n .Combobox_bui-ComboboxItemTextContent__1aa41a0b62 {\n display: flex;\n flex-direction: column;\n min-width: 0;\n }\n\n .Combobox_bui-ComboboxItemTitle__1aa41a0b62,\n .Combobox_bui-ComboboxItemDescription__1aa41a0b62 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .Combobox_bui-ComboboxItemDescription__1aa41a0b62 {\n font-size: var(--bui-font-size-2);\n color: var(--bui-fg-secondary);\n }\n\n .Combobox_bui-ComboboxSection__1aa41a0b62 {\n &:first-child .Combobox_bui-ComboboxSectionHeader__1aa41a0b62 {\n padding-top: 0;\n }\n }\n\n .Combobox_bui-ComboboxSectionHeader__1aa41a0b62 {\n height: 2rem;\n display: flex;\n align-items: center;\n padding-top: var(--bui-space-3);\n padding-left: var(--bui-space-3);\n color: var(--bui-fg-primary);\n font-size: var(--bui-font-size-1);\n font-weight: bold;\n letter-spacing: 0.05rem;\n text-transform: uppercase;\n }\n\n .Combobox_bui-ComboboxNoResults__1aa41a0b62 {\n padding-inline: var(--bui-space-3);\n padding-block: var(--bui-space-2);\n color: var(--bui-fg-secondary);\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n font-weight: var(--bui-font-weight-regular);\n }\n\n .Combobox_bui-ComboboxLoading__1aa41a0b62 {\n display: flex;\n flex-direction: column;\n width: 100%;\n }\n\n .Combobox_bui-ComboboxLoadingRow__1aa41a0b62 {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n min-height: var(--combobox-item-height);\n padding-block: var(--bui-space-1);\n padding-left: calc(var(--bui-space-3) + 1rem + var(--bui-space-2));\n padding-right: var(--bui-space-4);\n }\n}\n";
4
+ var styles = {"bui-Combobox":"Combobox_bui-Combobox__1aa41a0b62","bui-ComboboxPopover":"Combobox_bui-ComboboxPopover__1aa41a0b62","bui-ComboboxInput":"Combobox_bui-ComboboxInput__1aa41a0b62","bui-ComboboxInputIcon":"Combobox_bui-ComboboxInputIcon__1aa41a0b62","bui-ComboboxInputField":"Combobox_bui-ComboboxInputField__1aa41a0b62","bui-ComboboxInputChevron":"Combobox_bui-ComboboxInputChevron__1aa41a0b62","bui-ComboboxList":"Combobox_bui-ComboboxList__1aa41a0b62","bui-ComboboxItem":"Combobox_bui-ComboboxItem__1aa41a0b62","bui-ComboboxItemIndicator":"Combobox_bui-ComboboxItemIndicator__1aa41a0b62","bui-ComboboxItemLabel":"Combobox_bui-ComboboxItemLabel__1aa41a0b62","bui-ComboboxItemContent":"Combobox_bui-ComboboxItemContent__1aa41a0b62","bui-ComboboxItemText":"Combobox_bui-ComboboxItemText__1aa41a0b62","bui-ComboboxItemProfile":"Combobox_bui-ComboboxItemProfile__1aa41a0b62","bui-ComboboxItemTextLeadingIcon":"Combobox_bui-ComboboxItemTextLeadingIcon__1aa41a0b62","bui-ComboboxItemAvatar":"Combobox_bui-ComboboxItemAvatar__1aa41a0b62","bui-ComboboxItemTextContent":"Combobox_bui-ComboboxItemTextContent__1aa41a0b62","bui-ComboboxItemTitle":"Combobox_bui-ComboboxItemTitle__1aa41a0b62","bui-ComboboxItemDescription":"Combobox_bui-ComboboxItemDescription__1aa41a0b62","bui-ComboboxSection":"Combobox_bui-ComboboxSection__1aa41a0b62","bui-ComboboxSectionHeader":"Combobox_bui-ComboboxSectionHeader__1aa41a0b62","bui-ComboboxNoResults":"Combobox_bui-ComboboxNoResults__1aa41a0b62","bui-ComboboxLoading":"Combobox_bui-ComboboxLoading__1aa41a0b62","bui-ComboboxLoadingRow":"Combobox_bui-ComboboxLoadingRow__1aa41a0b62"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { styles as default };
@@ -0,0 +1,76 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { ListBoxItem, Text } from 'react-aria-components';
3
+ import { RiCheckLine } from '@remixicon/react';
4
+ import { Avatar } from '../Avatar/Avatar.esm.js';
5
+ import { useDefinition } from '../../hooks/useDefinition/useDefinition.esm.js';
6
+ import '../Avatar/Avatar.module.css.esm.js';
7
+ import { ComboboxItemDefinition, ComboboxItemProfileDefinition, ComboboxItemTextDefinition } from './definition.esm.js';
8
+
9
+ function ComboboxItem(props) {
10
+ const { ownProps, restProps } = useDefinition(ComboboxItemDefinition, props);
11
+ const { classes, children, textValue, showSelectionIndicator } = ownProps;
12
+ return /* @__PURE__ */ jsx(ListBoxItem, { ...restProps, className: classes.root, textValue, children: (values) => {
13
+ const content = typeof children === "function" ? children(values) : children;
14
+ if (!showSelectionIndicator) {
15
+ return content;
16
+ }
17
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
18
+ /* @__PURE__ */ jsx("div", { className: classes.indicator, children: /* @__PURE__ */ jsx(RiCheckLine, { "aria-hidden": "true" }) }),
19
+ /* @__PURE__ */ jsx("div", { className: classes.content, children: content })
20
+ ] });
21
+ } });
22
+ }
23
+ function ComboboxItemText(props) {
24
+ const { ownProps, restProps } = useDefinition(
25
+ ComboboxItemTextDefinition,
26
+ props
27
+ );
28
+ const { classes, title, description, leadingIcon, textValue } = ownProps;
29
+ return /* @__PURE__ */ jsxs(
30
+ ComboboxItem,
31
+ {
32
+ ...restProps,
33
+ className: classes.root,
34
+ textValue: textValue ?? title,
35
+ showSelectionIndicator: true,
36
+ children: [
37
+ leadingIcon && /* @__PURE__ */ jsx("div", { className: classes.leadingIcon, children: leadingIcon }),
38
+ /* @__PURE__ */ jsxs("div", { className: classes.text, children: [
39
+ /* @__PURE__ */ jsx(Text, { slot: "label", className: classes.title, children: title }),
40
+ description && /* @__PURE__ */ jsx(Text, { slot: "description", className: classes.description, children: description })
41
+ ] })
42
+ ]
43
+ }
44
+ );
45
+ }
46
+ function ComboboxItemProfile(props) {
47
+ const { ownProps, restProps } = useDefinition(
48
+ ComboboxItemProfileDefinition,
49
+ props
50
+ );
51
+ const { classes, name, src, textValue } = ownProps;
52
+ return /* @__PURE__ */ jsxs(
53
+ ComboboxItem,
54
+ {
55
+ ...restProps,
56
+ className: classes.root,
57
+ textValue: textValue ?? name,
58
+ showSelectionIndicator: true,
59
+ children: [
60
+ /* @__PURE__ */ jsx("div", { className: classes.avatar, children: /* @__PURE__ */ jsx(
61
+ Avatar,
62
+ {
63
+ src: src ?? "",
64
+ name,
65
+ size: "x-small",
66
+ purpose: "decoration"
67
+ }
68
+ ) }),
69
+ /* @__PURE__ */ jsx(Text, { slot: "label", className: classes.name, children: name })
70
+ ]
71
+ }
72
+ );
73
+ }
74
+
75
+ export { ComboboxItem, ComboboxItemProfile, ComboboxItemText };
76
+ //# sourceMappingURL=ComboboxItem.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComboboxItem.esm.js","sources":["../../../src/components/Combobox/ComboboxItem.tsx"],"sourcesContent":["/*\n * Copyright 2026 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ListBoxItem, Text } from 'react-aria-components';\nimport { RiCheckLine } from '@remixicon/react';\nimport { Avatar } from '../Avatar';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport {\n ComboboxItemDefinition,\n ComboboxItemProfileDefinition,\n ComboboxItemTextDefinition,\n} from './definition';\nimport type {\n ComboboxItemProfileProps,\n ComboboxItemProps,\n ComboboxItemTextProps,\n} from './types';\n\n/**\n * A combobox item wrapper for custom content.\n *\n * @public\n */\nexport function ComboboxItem<T extends object = object>(\n props: ComboboxItemProps<T>,\n) {\n const { ownProps, restProps } = useDefinition(ComboboxItemDefinition, props);\n const { classes, children, textValue, showSelectionIndicator } = ownProps;\n\n return (\n <ListBoxItem {...restProps} className={classes.root} textValue={textValue}>\n {values => {\n const content =\n typeof children === 'function' ? children(values) : children;\n\n if (!showSelectionIndicator) {\n return content;\n }\n\n return (\n <>\n <div className={classes.indicator}>\n <RiCheckLine aria-hidden=\"true\" />\n </div>\n <div className={classes.content}>{content}</div>\n </>\n );\n }}\n </ListBoxItem>\n );\n}\n\n/**\n * A combobox item that renders a title with an optional description and\n * leading icon.\n *\n * @public\n */\nexport function ComboboxItemText<T extends object = object>(\n props: ComboboxItemTextProps<T>,\n) {\n const { ownProps, restProps } = useDefinition(\n ComboboxItemTextDefinition,\n props,\n );\n const { classes, title, description, leadingIcon, textValue } = ownProps;\n\n return (\n <ComboboxItem\n {...restProps}\n className={classes.root}\n textValue={textValue ?? title}\n showSelectionIndicator\n >\n {leadingIcon && <div className={classes.leadingIcon}>{leadingIcon}</div>}\n <div className={classes.text}>\n <Text slot=\"label\" className={classes.title}>\n {title}\n </Text>\n {description && (\n <Text slot=\"description\" className={classes.description}>\n {description}\n </Text>\n )}\n </div>\n </ComboboxItem>\n );\n}\n\n/**\n * A combobox item that renders a profile name with an optional avatar.\n *\n * @public\n */\nexport function ComboboxItemProfile<T extends object = object>(\n props: ComboboxItemProfileProps<T>,\n) {\n const { ownProps, restProps } = useDefinition(\n ComboboxItemProfileDefinition,\n props,\n );\n const { classes, name, src, textValue } = ownProps;\n\n return (\n <ComboboxItem\n {...restProps}\n className={classes.root}\n textValue={textValue ?? name}\n showSelectionIndicator\n >\n <div className={classes.avatar}>\n <Avatar\n src={src ?? ''}\n name={name}\n size=\"x-small\"\n purpose=\"decoration\"\n />\n </div>\n <Text slot=\"label\" className={classes.name}>\n {name}\n </Text>\n </ComboboxItem>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAoCO,SAAS,aACd,KAAA,EACA;AACA,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,aAAA,CAAc,wBAAwB,KAAK,CAAA;AAC3E,EAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,SAAA,EAAW,wBAAuB,GAAI,QAAA;AAEjE,EAAA,uBACE,GAAA,CAAC,eAAa,GAAG,SAAA,EAAW,WAAW,OAAA,CAAQ,IAAA,EAAM,WAClD,QAAA,EAAA,CAAA,MAAA,KAAU;AACT,IAAA,MAAM,UACJ,OAAO,QAAA,KAAa,UAAA,GAAa,QAAA,CAAS,MAAM,CAAA,GAAI,QAAA;AAEtD,IAAA,IAAI,CAAC,sBAAA,EAAwB;AAC3B,MAAA,OAAO,OAAA;AAAA,IACT;AAEA,IAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAW,OAAA,CAAQ,SAAA,EACtB,8BAAC,WAAA,EAAA,EAAY,aAAA,EAAY,QAAO,CAAA,EAClC,CAAA;AAAA,sBACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,SAAU,QAAA,EAAA,OAAA,EAAQ;AAAA,KAAA,EAC5C,CAAA;AAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;AAQO,SAAS,iBACd,KAAA,EACA;AACA,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,aAAA;AAAA,IAC9B,0BAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,EAAE,OAAA,EAAS,KAAA,EAAO,WAAA,EAAa,WAAA,EAAa,WAAU,GAAI,QAAA;AAEhE,EAAA,uBACE,IAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACE,GAAG,SAAA;AAAA,MACJ,WAAW,OAAA,CAAQ,IAAA;AAAA,MACnB,WAAW,SAAA,IAAa,KAAA;AAAA,MACxB,sBAAA,EAAsB,IAAA;AAAA,MAErB,QAAA,EAAA;AAAA,QAAA,WAAA,oBAAe,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,aAAc,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,wBAClE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,IAAA,EACtB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,QAAK,IAAA,EAAK,OAAA,EAAQ,SAAA,EAAW,OAAA,CAAQ,OACnC,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UACC,WAAA,wBACE,IAAA,EAAA,EAAK,IAAA,EAAK,eAAc,SAAA,EAAW,OAAA,CAAQ,aACzC,QAAA,EAAA,WAAA,EACH;AAAA,SAAA,EAEJ;AAAA;AAAA;AAAA,GACF;AAEJ;AAOO,SAAS,oBACd,KAAA,EACA;AACA,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,aAAA;AAAA,IAC9B,6BAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,EAAE,OAAA,EAAS,IAAA,EAAM,GAAA,EAAK,WAAU,GAAI,QAAA;AAE1C,EAAA,uBACE,IAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACE,GAAG,SAAA;AAAA,MACJ,WAAW,OAAA,CAAQ,IAAA;AAAA,MACnB,WAAW,SAAA,IAAa,IAAA;AAAA,MACxB,sBAAA,EAAsB,IAAA;AAAA,MAEtB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,MAAA,EACtB,QAAA,kBAAA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,KAAK,GAAA,IAAO,EAAA;AAAA,YACZ,IAAA;AAAA,YACA,IAAA,EAAK,SAAA;AAAA,YACL,OAAA,EAAQ;AAAA;AAAA,SACV,EACF,CAAA;AAAA,4BACC,IAAA,EAAA,EAAK,IAAA,EAAK,SAAQ,SAAA,EAAW,OAAA,CAAQ,MACnC,QAAA,EAAA,IAAA,EACH;AAAA;AAAA;AAAA,GACF;AAEJ;;;;"}