@backstage/ui 0.15.1-next.0 → 0.17.0-next.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.
- package/CHANGELOG.md +186 -0
- package/dist/components/Combobox/Combobox.esm.js +150 -52
- package/dist/components/Combobox/Combobox.esm.js.map +1 -1
- package/dist/components/Combobox/Combobox.module.css.esm.js +2 -2
- package/dist/components/Combobox/ComboboxItem.esm.js +76 -0
- package/dist/components/Combobox/ComboboxItem.esm.js.map +1 -0
- package/dist/components/Combobox/ComboboxListBox.esm.js +215 -17
- package/dist/components/Combobox/ComboboxListBox.esm.js.map +1 -1
- package/dist/components/Combobox/definition.esm.js +62 -3
- package/dist/components/Combobox/definition.esm.js.map +1 -1
- package/dist/components/Combobox/useAsyncComboboxState.esm.js +133 -0
- package/dist/components/Combobox/useAsyncComboboxState.esm.js.map +1 -0
- package/dist/components/Header/HeaderNav.esm.js +0 -1
- package/dist/components/Header/HeaderNav.esm.js.map +1 -1
- package/dist/components/PluginHeader/PluginHeader.esm.js +16 -1
- package/dist/components/PluginHeader/PluginHeader.esm.js.map +1 -1
- package/dist/components/PluginHeader/PluginHeader.module.css.esm.js +2 -2
- package/dist/components/PluginHeader/PluginHeaderBreadcrumbs.esm.js +106 -0
- package/dist/components/PluginHeader/PluginHeaderBreadcrumbs.esm.js.map +1 -0
- package/dist/components/PluginHeader/definition.esm.js +3 -0
- package/dist/components/PluginHeader/definition.esm.js.map +1 -1
- package/dist/components/PluginHeader/useIsTruncated.esm.js +36 -0
- package/dist/components/PluginHeader/useIsTruncated.esm.js.map +1 -0
- package/dist/components/Select/Select.esm.js +87 -19
- package/dist/components/Select/Select.esm.js.map +1 -1
- package/dist/components/Select/Select.module.css.esm.js +2 -2
- package/dist/components/Select/SelectContent.esm.js +70 -18
- package/dist/components/Select/SelectContent.esm.js.map +1 -1
- package/dist/components/Select/SelectItem.esm.js +76 -0
- package/dist/components/Select/SelectItem.esm.js.map +1 -0
- package/dist/components/Select/SelectListBox.esm.js +175 -19
- package/dist/components/Select/SelectListBox.esm.js.map +1 -1
- package/dist/components/Select/SelectTrigger.esm.js +1 -1
- package/dist/components/Select/SelectTrigger.esm.js.map +1 -1
- package/dist/components/Select/definition.esm.js +72 -9
- package/dist/components/Select/definition.esm.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.module.css.esm.js +2 -2
- package/dist/components/Skeleton/definition.esm.js +1 -0
- package/dist/components/Skeleton/definition.esm.js.map +1 -1
- package/dist/components/Table/Table.module.css.esm.js +2 -2
- package/dist/components/Table/components/Table.esm.js +60 -57
- package/dist/components/Table/components/Table.esm.js.map +1 -1
- package/dist/components/Table/definition.esm.js +2 -1
- package/dist/components/Table/definition.esm.js.map +1 -1
- package/dist/components/TablePagination/TablePagination.esm.js +4 -1
- package/dist/components/TablePagination/TablePagination.esm.js.map +1 -1
- package/dist/components/Tabs/TabsIndicators.esm.js +155 -108
- package/dist/components/Tabs/TabsIndicators.esm.js.map +1 -1
- package/dist/components/TextAreaField/TextAreaField.esm.js +61 -0
- package/dist/components/TextAreaField/TextAreaField.esm.js.map +1 -0
- package/dist/components/TextAreaField/TextAreaField.module.css.esm.js +8 -0
- package/dist/components/TextAreaField/TextAreaField.module.css.esm.js.map +1 -0
- package/dist/components/TextAreaField/definition.esm.js +32 -0
- package/dist/components/TextAreaField/definition.esm.js.map +1 -0
- package/dist/css/styles.css +4 -4
- package/dist/hooks/useCollectionAdapter.esm.js +67 -0
- package/dist/hooks/useCollectionAdapter.esm.js.map +1 -0
- package/dist/hooks/useDelayedVisibility.esm.js +17 -0
- package/dist/hooks/useDelayedVisibility.esm.js.map +1 -0
- package/dist/hooks/useTrackedSelectionKeys.esm.js +23 -0
- package/dist/hooks/useTrackedSelectionKeys.esm.js.map +1 -0
- package/dist/index.d.ts +817 -77
- package/dist/index.esm.js +8 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/utils/selectableCollection.esm.js +75 -0
- package/dist/utils/selectableCollection.esm.js.map +1 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,191 @@
|
|
|
1
1
|
# @backstage/ui
|
|
2
2
|
|
|
3
|
+
## 0.17.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 503ba32: Added re-exports from `react-aria-components`. The types `Selection`, `SortDirection`, and `Key` are available as type-only exports (use `import type`), while `Focusable` is a runtime export. Consumers can now import these directly from `@backstage/ui` instead of depending on `react-aria-components`, avoiding version mismatches.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 791703e: Add `breadcrumbs` prop & breadcrumbs to `PluginHeader`. When passed `breadcrumbs`, `PluginHeader` renders a `nav` with breadcrumbs & visually hides the plugin title.
|
|
12
|
+
|
|
13
|
+
These breadcrumbs:
|
|
14
|
+
|
|
15
|
+
- Collapses middle segments if 5 or more segments
|
|
16
|
+
- Shows tooltip if text is truncated
|
|
17
|
+
|
|
18
|
+
**Affected components:** PluginHeader
|
|
19
|
+
|
|
20
|
+
- 066c7ac: Added a new `TextAreaField` component for multi-line text input, following the same conventions as `TextField` with support for a label, secondary label, and description.
|
|
21
|
+
|
|
22
|
+
## 0.16.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- 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`.
|
|
27
|
+
|
|
28
|
+
**BREAKING**: The public `ComboboxProps` interface is now a union type.
|
|
29
|
+
|
|
30
|
+
**Migration:**
|
|
31
|
+
|
|
32
|
+
**Required on upgrade:**
|
|
33
|
+
|
|
34
|
+
Replace interfaces that extend `ComboboxProps` with type intersections.
|
|
35
|
+
|
|
36
|
+
```diff
|
|
37
|
+
- interface MyComboboxProps extends ComboboxProps {
|
|
38
|
+
- trackingId: string;
|
|
39
|
+
- }
|
|
40
|
+
+ type MyComboboxProps = ComboboxProps & {
|
|
41
|
+
+ trackingId: string;
|
|
42
|
+
+ };
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Optional migration away from deprecated APIs:**
|
|
46
|
+
|
|
47
|
+
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`.
|
|
48
|
+
|
|
49
|
+
Move input state and custom filtering into the nested `search` configuration:
|
|
50
|
+
|
|
51
|
+
```diff
|
|
52
|
+
- <Combobox inputValue={query} onInputChange={setQuery} />
|
|
53
|
+
+ <Combobox search={{ inputValue: query, onInputChange: setQuery }} />
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The existing top-level input state props remain supported as a deprecated compatibility path for plain-array `options`.
|
|
57
|
+
|
|
58
|
+
**Affected components:** Combobox
|
|
59
|
+
|
|
60
|
+
- 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`.
|
|
61
|
+
|
|
62
|
+
**BREAKING**: The public `SelectProps` interface is now a union type, and Select popover list content is no longer a direct child of `.bui-SelectPopover`.
|
|
63
|
+
|
|
64
|
+
**Migration:**
|
|
65
|
+
|
|
66
|
+
**Required on upgrade:**
|
|
67
|
+
|
|
68
|
+
Replace interfaces that extend `SelectProps` with type intersections.
|
|
69
|
+
|
|
70
|
+
```diff
|
|
71
|
+
- interface MySelectProps extends SelectProps {
|
|
72
|
+
- trackingId: string;
|
|
73
|
+
- }
|
|
74
|
+
+ type MySelectProps = SelectProps & {
|
|
75
|
+
+ trackingId: string;
|
|
76
|
+
+ };
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
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.
|
|
80
|
+
|
|
81
|
+
**Optional migration away from deprecated APIs:**
|
|
82
|
+
|
|
83
|
+
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`.
|
|
84
|
+
|
|
85
|
+
Replace `searchable` and `searchPlaceholder` with nested `search` configuration:
|
|
86
|
+
|
|
87
|
+
```diff
|
|
88
|
+
- <Select searchable searchPlaceholder="Search owners" />
|
|
89
|
+
+ <Select search={{ placeholder: 'Search owners' }} />
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Affected components:** Select
|
|
93
|
+
|
|
94
|
+
### Patch Changes
|
|
95
|
+
|
|
96
|
+
- 3d6c2e4: Updated the dark theme neutral background tokens to provide clearer contrast between neutral surfaces.
|
|
97
|
+
- 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.
|
|
98
|
+
- adf94f5: Make Skeleton component background aware, automatically adjusting its color to maintain visible contrast against neutral parent surfaces.
|
|
99
|
+
|
|
100
|
+
**Affected components:** Skeleton
|
|
101
|
+
|
|
102
|
+
- b06b3c7: Fixed header tab links to respect the configured router `basename`.
|
|
103
|
+
|
|
104
|
+
**Affected components:** Header
|
|
105
|
+
|
|
106
|
+
- 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.
|
|
107
|
+
|
|
108
|
+
**Affected components:** Switch
|
|
109
|
+
|
|
110
|
+
- 66c4e55: Fixed tab indicator not updating position when tab content changes width dynamically.
|
|
111
|
+
- b33bb24: Added a new `NumberField` component for numeric input with support for min, max, step, and keyboard increment/decrement.
|
|
112
|
+
|
|
113
|
+
**Affected components:** NumberField
|
|
114
|
+
|
|
115
|
+
- 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.
|
|
116
|
+
|
|
117
|
+
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.
|
|
118
|
+
|
|
119
|
+
**Affected components:** Combobox, Select
|
|
120
|
+
|
|
121
|
+
- e989f95: Fixed `Combobox` client search crashing when used with plain options.
|
|
122
|
+
|
|
123
|
+
**Affected components:** Combobox
|
|
124
|
+
|
|
125
|
+
- 1f709a3: Fixed Header breadcrumb typography so it remains consistent when component styles are loaded in different orders.
|
|
126
|
+
|
|
127
|
+
**Affected components:** Header
|
|
128
|
+
|
|
129
|
+
- 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.
|
|
130
|
+
|
|
131
|
+
The previous tokens remain in place for backward compatibility but are now deprecated and will be removed in a future release.
|
|
132
|
+
|
|
133
|
+
**Migration:**
|
|
134
|
+
|
|
135
|
+
**Neutral backgrounds**
|
|
136
|
+
|
|
137
|
+
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.
|
|
138
|
+
|
|
139
|
+
**Foreground**
|
|
140
|
+
|
|
141
|
+
| Deprecated | Replacement |
|
|
142
|
+
| ------------------ | ----------------------- |
|
|
143
|
+
| `--bui-fg-danger` | `--bui-fg-negative` |
|
|
144
|
+
| `--bui-fg-success` | `--bui-fg-positive` |
|
|
145
|
+
| `--bui-fg-info` | `--bui-fg-announcement` |
|
|
146
|
+
|
|
147
|
+
**Accent**
|
|
148
|
+
|
|
149
|
+
| Deprecated | Replacement |
|
|
150
|
+
| ------------------------- | -------------------------- |
|
|
151
|
+
| `--bui-bg-solid` | `--bui-accent-bg` |
|
|
152
|
+
| `--bui-bg-solid-hover` | `--bui-accent-bg-hover` |
|
|
153
|
+
| `--bui-bg-solid-disabled` | `--bui-accent-bg-disabled` |
|
|
154
|
+
| `--bui-fg-solid` | `--bui-accent-fg` |
|
|
155
|
+
| `--bui-fg-solid-disabled` | `--bui-accent-fg-disabled` |
|
|
156
|
+
|
|
157
|
+
**Positive**
|
|
158
|
+
|
|
159
|
+
| Deprecated | Replacement |
|
|
160
|
+
| ------------------------ | --------------------------- |
|
|
161
|
+
| `--bui-bg-success` | `--bui-positive-bg-subdued` |
|
|
162
|
+
| `--bui-fg-success-on-bg` | `--bui-positive-fg-subdued` |
|
|
163
|
+
| `--bui-border-success` | `--bui-positive-border` |
|
|
164
|
+
|
|
165
|
+
**Negative**
|
|
166
|
+
|
|
167
|
+
| Deprecated | Replacement |
|
|
168
|
+
| ----------------------- | --------------------------- |
|
|
169
|
+
| `--bui-bg-danger` | `--bui-negative-bg-subdued` |
|
|
170
|
+
| `--bui-fg-danger-on-bg` | `--bui-negative-fg-subdued` |
|
|
171
|
+
| `--bui-border-danger` | `--bui-negative-border` |
|
|
172
|
+
|
|
173
|
+
**Warning**
|
|
174
|
+
|
|
175
|
+
| Deprecated | Replacement |
|
|
176
|
+
| ------------------------ | -------------------------- |
|
|
177
|
+
| `--bui-bg-warning` | `--bui-warning-bg-subdued` |
|
|
178
|
+
| `--bui-fg-warning-on-bg` | `--bui-warning-fg-subdued` |
|
|
179
|
+
| `--bui-border-warning` | `--bui-warning-border` |
|
|
180
|
+
|
|
181
|
+
**Announcement**
|
|
182
|
+
|
|
183
|
+
| Deprecated | Replacement |
|
|
184
|
+
| --------------------- | ------------------------------- |
|
|
185
|
+
| `--bui-bg-info` | `--bui-announcement-bg-subdued` |
|
|
186
|
+
| `--bui-fg-info-on-bg` | `--bui-announcement-fg-subdued` |
|
|
187
|
+
| `--bui-border-info` | `--bui-announcement-border` |
|
|
188
|
+
|
|
3
189
|
## 0.15.1-next.0
|
|
4
190
|
|
|
5
191
|
### 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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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-
|
|
4
|
-
var styles = {"bui-Combobox":"Combobox_bui-
|
|
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":"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"}
|