@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
@@ -1 +1 @@
1
- {"version":3,"file":"HeaderNav.esm.js","sources":["../../../src/components/Header/HeaderNav.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 { useCallback, useMemo, useRef, useState } from 'react';\nimport { useFocusVisible, useHover, useLink } from 'react-aria';\nimport {\n matchRoutes,\n resolvePath,\n useInRouterContext,\n useLocation,\n useResolvedPath,\n} from 'react-router-dom';\nimport { Button as RAButton } from 'react-aria-components';\nimport { RiArrowDownSLine } from '@remixicon/react';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport {\n HeaderNavDefinition,\n HeaderNavItemDefinition,\n HeaderNavGroupDefinition,\n} from './HeaderNavDefinition';\nimport { HeaderNavIndicators } from './HeaderNavIndicators';\nimport { MenuTrigger, Menu, MenuItem } from '../Menu';\nimport type {\n HeaderNavLinkProps,\n HeaderNavTabGroup,\n HeaderNavTabItem,\n} from './types';\n\nfunction isTabGroup(tab: HeaderNavTabItem): tab is HeaderNavTabGroup {\n return 'items' in tab;\n}\n\nfunction HeaderNavLink(props: HeaderNavLinkProps) {\n const { ownProps, analytics } = useDefinition(HeaderNavItemDefinition, props);\n const { id, label, href, active, registerRef, onHighlight } = ownProps;\n\n const linkRef = useRef<HTMLAnchorElement>(null);\n const { linkProps } = useLink({ href }, linkRef);\n const { hoverProps } = useHover({\n onHoverStart: () => onHighlight(id),\n onHoverEnd: () => onHighlight(null),\n });\n\n const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\n linkProps.onClick?.(e);\n analytics.captureEvent('click', label, {\n attributes: { to: href },\n });\n };\n\n return (\n <li>\n <a\n {...linkProps}\n {...hoverProps}\n ref={el => {\n (\n linkRef as React.MutableRefObject<HTMLAnchorElement | null>\n ).current = el;\n registerRef(id, el);\n }}\n href={href}\n className={ownProps.classes.root}\n aria-current={active ? 'page' : undefined}\n onClick={handleClick}\n onFocus={() => onHighlight(id)}\n onBlur={() => onHighlight(null)}\n >\n {label}\n </a>\n </li>\n );\n}\n\ninterface HeaderNavGroupItemProps {\n group: HeaderNavTabGroup;\n active: boolean;\n activeChildId?: string;\n registerRef: (key: string, el: HTMLElement | null) => void;\n onHighlight: (key: string | null) => void;\n}\n\nfunction HeaderNavGroupItem(props: HeaderNavGroupItemProps) {\n const { group, active, activeChildId, registerRef, onHighlight } = props;\n const { ownProps } = useDefinition(HeaderNavGroupDefinition, {});\n const { hoverProps } = useHover({\n onHoverStart: () => onHighlight(group.id),\n onHoverEnd: () => onHighlight(null),\n });\n\n return (\n <li>\n <MenuTrigger>\n <RAButton\n ref={el => {\n registerRef(group.id, el);\n }}\n className={ownProps.classes.root}\n aria-current={active ? 'page' : undefined}\n {...hoverProps}\n onFocus={() => onHighlight(group.id)}\n onBlur={() => onHighlight(null)}\n >\n {group.label}\n <RiArrowDownSLine size={16} />\n </RAButton>\n <Menu\n selectionMode=\"single\"\n selectedKeys={new Set(activeChildId ? [activeChildId] : [])}\n >\n {group.items.map(item => (\n <MenuItem key={item.id} id={item.id} href={item.href}>\n {item.label}\n </MenuItem>\n ))}\n </Menu>\n </MenuTrigger>\n </li>\n );\n}\n\ninterface HeaderNavProps {\n tabs: HeaderNavTabItem[];\n activeTabId?: string | null;\n}\n\nfunction useAutoActiveTabId(tabs: HeaderNavTabItem[]): string | undefined {\n const basePath = useResolvedPath('.').pathname;\n const { pathname } = useLocation();\n\n return useMemo(() => {\n const allTabs = tabs.flatMap(tab => (isTabGroup(tab) ? tab.items : [tab]));\n const routeObjects = allTabs.map(tab => ({\n path: `${resolvePath(tab.href, basePath).pathname}/*`,\n id: tab.id,\n }));\n const matches = matchRoutes(routeObjects, pathname);\n return matches?.[0]?.route.id;\n }, [tabs, basePath, pathname]);\n}\n\nfunction HeaderNavAutoDetect(props: { tabs: HeaderNavTabItem[] }) {\n const activeTabId = useAutoActiveTabId(props.tabs);\n return <HeaderNavInner tabs={props.tabs} activeTabId={activeTabId} />;\n}\n\nfunction HeaderNavInner(props: HeaderNavProps) {\n const { tabs, activeTabId } = props;\n const { ownProps } = useDefinition(HeaderNavDefinition, {\n tabs,\n activeTabId,\n });\n const { classes } = ownProps;\n\n const { isFocusVisible } = useFocusVisible();\n const navRef = useRef<HTMLElement>(null);\n const itemRefs = useRef<Map<string, HTMLElement>>(new Map());\n\n const [highlightedKey, setHighlightedKey] = useState<string | null>(null);\n\n // Resolve activeTabId to a top-level key (groups own their children's active state)\n const { activeKey, activeChildId } = useMemo(() => {\n if (!activeTabId) return { activeKey: undefined, activeChildId: undefined };\n for (const item of tabs) {\n if (isTabGroup(item)) {\n const child = item.items.find(c => c.id === activeTabId);\n if (child) {\n return { activeKey: item.id, activeChildId: child.id };\n }\n } else if (item.id === activeTabId) {\n return { activeKey: item.id, activeChildId: undefined };\n }\n }\n return { activeKey: undefined, activeChildId: undefined };\n }, [activeTabId, tabs]);\n\n const registerRef = useCallback((key: string, el: HTMLElement | null) => {\n if (el) {\n itemRefs.current.set(key, el);\n } else {\n itemRefs.current.delete(key);\n }\n }, []);\n\n return (\n <nav\n ref={navRef}\n aria-label=\"Content navigation\"\n className={classes.root}\n data-focus-visible={isFocusVisible || undefined}\n >\n <ul role=\"list\" className={classes.list}>\n {tabs.map(item =>\n isTabGroup(item) ? (\n <HeaderNavGroupItem\n key={item.id}\n group={item}\n active={activeKey === item.id}\n activeChildId={activeChildId}\n registerRef={registerRef}\n onHighlight={setHighlightedKey}\n />\n ) : (\n <HeaderNavLink\n key={item.id}\n id={item.id}\n label={item.label}\n href={item.href}\n active={activeKey === item.id}\n registerRef={registerRef}\n onHighlight={setHighlightedKey}\n />\n ),\n )}\n </ul>\n <HeaderNavIndicators\n navRef={navRef}\n itemRefs={itemRefs}\n activeKey={activeKey}\n highlightedKey={highlightedKey}\n classes={{ active: classes.active, hovered: classes.hovered }}\n />\n </nav>\n );\n}\n\n/** @internal */\nexport function HeaderNav(props: HeaderNavProps) {\n const inRouter = useInRouterContext();\n\n if (props.activeTabId === undefined && inRouter) {\n return <HeaderNavAutoDetect tabs={props.tabs} />;\n }\n\n return <HeaderNavInner tabs={props.tabs} activeTabId={props.activeTabId} />;\n}\n"],"names":["RAButton"],"mappings":"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"}
1
+ {"version":3,"file":"HeaderNav.esm.js","sources":["../../../src/components/Header/HeaderNav.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 { useCallback, useMemo, useRef, useState } from 'react';\nimport { useFocusVisible, useHover, useLink } from 'react-aria';\nimport {\n matchRoutes,\n resolvePath,\n useInRouterContext,\n useLocation,\n useResolvedPath,\n} from 'react-router-dom';\nimport { Button as RAButton } from 'react-aria-components';\nimport { RiArrowDownSLine } from '@remixicon/react';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport {\n HeaderNavDefinition,\n HeaderNavItemDefinition,\n HeaderNavGroupDefinition,\n} from './HeaderNavDefinition';\nimport { HeaderNavIndicators } from './HeaderNavIndicators';\nimport { MenuTrigger, Menu, MenuItem } from '../Menu';\nimport type {\n HeaderNavLinkProps,\n HeaderNavTabGroup,\n HeaderNavTabItem,\n} from './types';\n\nfunction isTabGroup(tab: HeaderNavTabItem): tab is HeaderNavTabGroup {\n return 'items' in tab;\n}\n\nfunction HeaderNavLink(props: HeaderNavLinkProps) {\n const { ownProps, analytics } = useDefinition(HeaderNavItemDefinition, props);\n const { id, label, href, active, registerRef, onHighlight } = ownProps;\n\n const linkRef = useRef<HTMLAnchorElement>(null);\n const { linkProps } = useLink({ href }, linkRef);\n const { hoverProps } = useHover({\n onHoverStart: () => onHighlight(id),\n onHoverEnd: () => onHighlight(null),\n });\n\n const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\n linkProps.onClick?.(e);\n analytics.captureEvent('click', label, {\n attributes: { to: href },\n });\n };\n\n return (\n <li>\n <a\n {...linkProps}\n {...hoverProps}\n ref={el => {\n (\n linkRef as React.MutableRefObject<HTMLAnchorElement | null>\n ).current = el;\n registerRef(id, el);\n }}\n className={ownProps.classes.root}\n aria-current={active ? 'page' : undefined}\n onClick={handleClick}\n onFocus={() => onHighlight(id)}\n onBlur={() => onHighlight(null)}\n >\n {label}\n </a>\n </li>\n );\n}\n\ninterface HeaderNavGroupItemProps {\n group: HeaderNavTabGroup;\n active: boolean;\n activeChildId?: string;\n registerRef: (key: string, el: HTMLElement | null) => void;\n onHighlight: (key: string | null) => void;\n}\n\nfunction HeaderNavGroupItem(props: HeaderNavGroupItemProps) {\n const { group, active, activeChildId, registerRef, onHighlight } = props;\n const { ownProps } = useDefinition(HeaderNavGroupDefinition, {});\n const { hoverProps } = useHover({\n onHoverStart: () => onHighlight(group.id),\n onHoverEnd: () => onHighlight(null),\n });\n\n return (\n <li>\n <MenuTrigger>\n <RAButton\n ref={el => {\n registerRef(group.id, el);\n }}\n className={ownProps.classes.root}\n aria-current={active ? 'page' : undefined}\n {...hoverProps}\n onFocus={() => onHighlight(group.id)}\n onBlur={() => onHighlight(null)}\n >\n {group.label}\n <RiArrowDownSLine size={16} />\n </RAButton>\n <Menu\n selectionMode=\"single\"\n selectedKeys={new Set(activeChildId ? [activeChildId] : [])}\n >\n {group.items.map(item => (\n <MenuItem key={item.id} id={item.id} href={item.href}>\n {item.label}\n </MenuItem>\n ))}\n </Menu>\n </MenuTrigger>\n </li>\n );\n}\n\ninterface HeaderNavProps {\n tabs: HeaderNavTabItem[];\n activeTabId?: string | null;\n}\n\nfunction useAutoActiveTabId(tabs: HeaderNavTabItem[]): string | undefined {\n const basePath = useResolvedPath('.').pathname;\n const { pathname } = useLocation();\n\n return useMemo(() => {\n const allTabs = tabs.flatMap(tab => (isTabGroup(tab) ? tab.items : [tab]));\n const routeObjects = allTabs.map(tab => ({\n path: `${resolvePath(tab.href, basePath).pathname}/*`,\n id: tab.id,\n }));\n const matches = matchRoutes(routeObjects, pathname);\n return matches?.[0]?.route.id;\n }, [tabs, basePath, pathname]);\n}\n\nfunction HeaderNavAutoDetect(props: { tabs: HeaderNavTabItem[] }) {\n const activeTabId = useAutoActiveTabId(props.tabs);\n return <HeaderNavInner tabs={props.tabs} activeTabId={activeTabId} />;\n}\n\nfunction HeaderNavInner(props: HeaderNavProps) {\n const { tabs, activeTabId } = props;\n const { ownProps } = useDefinition(HeaderNavDefinition, {\n tabs,\n activeTabId,\n });\n const { classes } = ownProps;\n\n const { isFocusVisible } = useFocusVisible();\n const navRef = useRef<HTMLElement>(null);\n const itemRefs = useRef<Map<string, HTMLElement>>(new Map());\n\n const [highlightedKey, setHighlightedKey] = useState<string | null>(null);\n\n // Resolve activeTabId to a top-level key (groups own their children's active state)\n const { activeKey, activeChildId } = useMemo(() => {\n if (!activeTabId) return { activeKey: undefined, activeChildId: undefined };\n for (const item of tabs) {\n if (isTabGroup(item)) {\n const child = item.items.find(c => c.id === activeTabId);\n if (child) {\n return { activeKey: item.id, activeChildId: child.id };\n }\n } else if (item.id === activeTabId) {\n return { activeKey: item.id, activeChildId: undefined };\n }\n }\n return { activeKey: undefined, activeChildId: undefined };\n }, [activeTabId, tabs]);\n\n const registerRef = useCallback((key: string, el: HTMLElement | null) => {\n if (el) {\n itemRefs.current.set(key, el);\n } else {\n itemRefs.current.delete(key);\n }\n }, []);\n\n return (\n <nav\n ref={navRef}\n aria-label=\"Content navigation\"\n className={classes.root}\n data-focus-visible={isFocusVisible || undefined}\n >\n <ul role=\"list\" className={classes.list}>\n {tabs.map(item =>\n isTabGroup(item) ? (\n <HeaderNavGroupItem\n key={item.id}\n group={item}\n active={activeKey === item.id}\n activeChildId={activeChildId}\n registerRef={registerRef}\n onHighlight={setHighlightedKey}\n />\n ) : (\n <HeaderNavLink\n key={item.id}\n id={item.id}\n label={item.label}\n href={item.href}\n active={activeKey === item.id}\n registerRef={registerRef}\n onHighlight={setHighlightedKey}\n />\n ),\n )}\n </ul>\n <HeaderNavIndicators\n navRef={navRef}\n itemRefs={itemRefs}\n activeKey={activeKey}\n highlightedKey={highlightedKey}\n classes={{ active: classes.active, hovered: classes.hovered }}\n />\n </nav>\n );\n}\n\n/** @internal */\nexport function HeaderNav(props: HeaderNavProps) {\n const inRouter = useInRouterContext();\n\n if (props.activeTabId === undefined && inRouter) {\n return <HeaderNavAutoDetect tabs={props.tabs} />;\n }\n\n return <HeaderNavInner tabs={props.tabs} activeTabId={props.activeTabId} />;\n}\n"],"names":["RAButton"],"mappings":"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"}
@@ -1,18 +1,52 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { forwardRef, useEffect } from 'react';
3
- import { Select as Select$1, Popover } from 'react-aria-components';
3
+ import { Select as Select$1 } from 'react-aria-components';
4
4
  import { useDefinition } from '../../hooks/useDefinition/useDefinition.esm.js';
5
5
  import { SelectDefinition } from './definition.esm.js';
6
- import { PopoverDefinition } from '../Popover/definition.esm.js';
7
- import clsx from 'clsx';
8
6
  import { FieldLabel } from '../FieldLabel/FieldLabel.esm.js';
9
7
  import '../FieldLabel/FieldLabel.module.css.esm.js';
10
8
  import { FieldError } from '../FieldError/FieldError.esm.js';
11
9
  import '../FieldError/FieldError.module.css.esm.js';
10
+ import { Popover } from '../Popover/Popover.esm.js';
11
+ import '../Popover/Popover.module.css.esm.js';
12
12
  import { SelectTrigger } from './SelectTrigger.esm.js';
13
13
  import { SelectContent } from './SelectContent.esm.js';
14
+ import { useCollectionAdapter } from '../../hooks/useCollectionAdapter.esm.js';
15
+ import { useTrackedSelectionKeys } from '../../hooks/useTrackedSelectionKeys.esm.js';
16
+ import { resolveCollectionSource, toSelection, getItemKeys } from '../../utils/selectableCollection.esm.js';
14
17
 
15
- const Select = forwardRef((props, ref) => {
18
+ function resolveSelectSearch({
19
+ search,
20
+ searchable,
21
+ searchPlaceholder
22
+ }) {
23
+ if (search !== void 0) {
24
+ return search;
25
+ }
26
+ if (searchable) {
27
+ return { placeholder: searchPlaceholder };
28
+ }
29
+ return void 0;
30
+ }
31
+ function resolveContentSearch(search, collection) {
32
+ if (typeof search !== "object") {
33
+ return search;
34
+ }
35
+ return {
36
+ ...search,
37
+ inputValue: collection.inputValue,
38
+ defaultInputValue: collection.defaultInputValue,
39
+ onInputChange: collection.onInputChange
40
+ };
41
+ }
42
+ function getRetainedOptions(flatOptions, canonicalItems) {
43
+ if (!flatOptions) {
44
+ return void 0;
45
+ }
46
+ const sourceIds = getItemKeys(flatOptions);
47
+ return canonicalItems.filter((item) => !sourceIds.has(item.id));
48
+ }
49
+ function SelectImpl(props, ref) {
16
50
  const { ownProps, restProps, dataAttributes } = useDefinition(
17
51
  SelectDefinition,
18
52
  {
@@ -20,7 +54,6 @@ const Select = forwardRef((props, ref) => {
20
54
  ...props
21
55
  }
22
56
  );
23
- const { ownProps: popoverOwnProps } = useDefinition(PopoverDefinition, {});
24
57
  const {
25
58
  classes,
26
59
  label,
@@ -29,6 +62,11 @@ const Select = forwardRef((props, ref) => {
29
62
  icon,
30
63
  searchable,
31
64
  searchPlaceholder,
65
+ search,
66
+ loading,
67
+ items,
68
+ children,
69
+ dependencies,
32
70
  isRequired,
33
71
  secondaryLabel
34
72
  } = ownProps;
@@ -42,6 +80,34 @@ const Select = forwardRef((props, ref) => {
42
80
  }
43
81
  }, [label, ariaLabel, ariaLabelledBy]);
44
82
  const secondaryLabelText = secondaryLabel || (isRequired ? "Required" : null);
83
+ const resolvedSearch = resolveSelectSearch({
84
+ search,
85
+ searchable,
86
+ searchPlaceholder
87
+ });
88
+ const collectionSource = resolveCollectionSource({ options, items });
89
+ const controlledValue = restProps.value !== void 0 ? restProps.value : restProps.selectedKey;
90
+ const defaultValue = restProps.defaultValue !== void 0 ? restProps.defaultValue : restProps.defaultSelectedKey;
91
+ const trackedSelection = useTrackedSelectionKeys({
92
+ selectedKeys: controlledValue === void 0 ? void 0 : toSelection(controlledValue),
93
+ defaultSelectedKeys: toSelection(defaultValue)
94
+ });
95
+ const collection = useCollectionAdapter({
96
+ items: collectionSource.source,
97
+ selectedKeys: trackedSelection.selectedKeys,
98
+ search: resolvedSearch,
99
+ loading
100
+ });
101
+ const retainedOptions = getRetainedOptions(
102
+ collectionSource.flatOptions,
103
+ collection.canonicalItems
104
+ );
105
+ const renderedItems = collectionSource.rendersItems ? collection.canonicalItems : void 0;
106
+ const contentSearch = resolveContentSearch(resolvedSearch, collection);
107
+ const handleChange = (value) => {
108
+ trackedSelection.onSelectionChange(toSelection(value));
109
+ restProps.onChange?.(value);
110
+ };
45
111
  return /* @__PURE__ */ jsxs(
46
112
  Select$1,
47
113
  {
@@ -49,6 +115,8 @@ const Select = forwardRef((props, ref) => {
49
115
  ...dataAttributes,
50
116
  ref,
51
117
  ...restProps,
118
+ onChange: handleChange,
119
+ allowsEmptyCollection: true,
52
120
  children: [
53
121
  /* @__PURE__ */ jsx(
54
122
  FieldLabel,
@@ -61,25 +129,25 @@ const Select = forwardRef((props, ref) => {
61
129
  ),
62
130
  /* @__PURE__ */ jsx(SelectTrigger, { icon }),
63
131
  /* @__PURE__ */ jsx(FieldError, {}),
64
- /* @__PURE__ */ jsx(
65
- Popover,
132
+ /* @__PURE__ */ jsx(Popover, { className: classes.popover, hideArrow: true, ...dataAttributes, children: /* @__PURE__ */ jsx(
133
+ SelectContent,
66
134
  {
67
- className: clsx(popoverOwnProps.classes.root, classes.popover),
68
- ...dataAttributes,
69
- children: /* @__PURE__ */ jsx(
70
- SelectContent,
71
- {
72
- searchable,
73
- searchPlaceholder,
74
- options
75
- }
76
- )
135
+ search: contentSearch,
136
+ options: collectionSource.options,
137
+ items: renderedItems,
138
+ dependencies,
139
+ loading: collection.loading,
140
+ isStale: collection.isStale,
141
+ visibleIds: collection.visibleIds,
142
+ retainedOptions,
143
+ children
77
144
  }
78
- )
145
+ ) })
79
146
  ]
80
147
  }
81
148
  );
82
- });
149
+ }
150
+ const Select = forwardRef(SelectImpl);
83
151
  Select.displayName = "Select";
84
152
 
85
153
  export { Select };
@@ -1 +1 @@
1
- {"version":3,"file":"Select.esm.js","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { Select as AriaSelect, Popover } from 'react-aria-components';\nimport { SelectProps } from './types';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { SelectDefinition } from './definition';\nimport { PopoverDefinition } from '../Popover/definition';\nimport clsx from 'clsx';\nimport { FieldLabel } from '../FieldLabel';\nimport { FieldError } from '../FieldError';\nimport { SelectTrigger } from './SelectTrigger';\nimport { SelectContent } from './SelectContent';\n\n/**\n * A dropdown picker for selecting one or multiple options from a list, with optional search filtering and inline error display.\n *\n * @public\n */\nexport const Select = forwardRef<\n HTMLDivElement,\n SelectProps<'single' | 'multiple'>\n>((props, ref) => {\n const { ownProps, restProps, dataAttributes } = useDefinition(\n SelectDefinition,\n {\n placeholder: 'Select an option',\n ...props,\n },\n );\n const { ownProps: popoverOwnProps } = useDefinition(PopoverDefinition, {});\n\n const {\n classes,\n label,\n description,\n options,\n icon,\n searchable,\n searchPlaceholder,\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 'Select 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\n return (\n <AriaSelect\n className={classes.root}\n {...dataAttributes}\n ref={ref}\n {...restProps}\n >\n <FieldLabel\n label={label}\n secondaryLabel={secondaryLabelText}\n description={description}\n descriptionSlot=\"description\"\n />\n <SelectTrigger icon={icon} />\n <FieldError />\n <Popover\n className={clsx(popoverOwnProps.classes.root, classes.popover)}\n {...dataAttributes}\n >\n <SelectContent\n searchable={searchable}\n searchPlaceholder={searchPlaceholder}\n options={options}\n />\n </Popover>\n </AriaSelect>\n );\n});\n\nSelect.displayName = 'Select';\n"],"names":["AriaSelect"],"mappings":";;;;;;;;;;;;;;AAiCO,MAAM,MAAA,GAAS,UAAA,CAGpB,CAAC,KAAA,EAAO,GAAA,KAAQ;AAChB,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,cAAA,EAAe,GAAI,aAAA;AAAA,IAC9C,gBAAA;AAAA,IACA;AAAA,MACE,WAAA,EAAa,kBAAA;AAAA,MACb,GAAG;AAAA;AACL,GACF;AACA,EAAA,MAAM,EAAE,QAAA,EAAU,eAAA,KAAoB,aAAA,CAAc,iBAAA,EAAmB,EAAE,CAAA;AAEzE,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,IAAA;AAAA,IACA,UAAA;AAAA,IACA,iBAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF,GAAI,QAAA;AAEJ,EAAA,MAAM,SAAA,GAAY,UAAU,YAAY,CAAA;AACxC,EAAA,MAAM,cAAA,GAAiB,UAAU,iBAAiB,CAAA;AAElD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,SAAA,IAAa,CAAC,cAAA,EAAgB;AAC3C,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,KAAA,EAAO,SAAA,EAAW,cAAc,CAAC,CAAA;AAErC,EAAA,MAAM,kBAAA,GAAqB,cAAA,KAAmB,UAAA,GAAa,UAAA,GAAa,IAAA,CAAA;AAExE,EAAA,uBACE,IAAA;AAAA,IAACA,QAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAA,CAAQ,IAAA;AAAA,MAClB,GAAG,cAAA;AAAA,MACJ,GAAA;AAAA,MACC,GAAG,SAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,UAAA;AAAA,UAAA;AAAA,YACC,KAAA;AAAA,YACA,cAAA,EAAgB,kBAAA;AAAA,YAChB,WAAA;AAAA,YACA,eAAA,EAAgB;AAAA;AAAA,SAClB;AAAA,wBACA,GAAA,CAAC,iBAAc,IAAA,EAAY,CAAA;AAAA,4BAC1B,UAAA,EAAA,EAAW,CAAA;AAAA,wBACZ,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,WAAW,IAAA,CAAK,eAAA,CAAgB,OAAA,CAAQ,IAAA,EAAM,QAAQ,OAAO,CAAA;AAAA,YAC5D,GAAG,cAAA;AAAA,YAEJ,QAAA,kBAAA,GAAA;AAAA,cAAC,aAAA;AAAA,cAAA;AAAA,gBACC,UAAA;AAAA,gBACA,iBAAA;AAAA,gBACA;AAAA;AAAA;AACF;AAAA;AACF;AAAA;AAAA,GACF;AAEJ,CAAC;AAED,MAAA,CAAO,WAAA,GAAc,QAAA;;;;"}
1
+ {"version":3,"file":"Select.esm.js","sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { Select as AriaSelect } from 'react-aria-components';\nimport type {\n CollectionItem,\n NormalizedOption,\n} from '../../types/selectableCollection';\nimport type { Key } from 'react-aria-components';\nimport type { ChangeValueType } from 'react-stately/useSelectState';\nimport type { SelectContentOwnProps, SelectProps } from './types';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { SelectDefinition } from './definition';\nimport { FieldLabel } from '../FieldLabel';\nimport { FieldError } from '../FieldError';\nimport { Popover } from '../Popover';\nimport { SelectTrigger } from './SelectTrigger';\nimport { SelectContent } from './SelectContent';\nimport {\n useCollectionAdapter,\n type CollectionAdapterResult,\n} from '../../hooks/useCollectionAdapter';\nimport { useTrackedSelectionKeys } from '../../hooks/useTrackedSelectionKeys';\nimport {\n getItemKeys,\n resolveCollectionSource,\n toSelection,\n} from '../../utils/selectableCollection';\n\nfunction resolveSelectSearch<T extends CollectionItem>({\n search,\n searchable,\n searchPlaceholder,\n}: {\n search?: SelectContentOwnProps<T>['search'];\n searchable?: boolean;\n searchPlaceholder?: string;\n}): SelectContentOwnProps<T>['search'] {\n if (search !== undefined) {\n return search;\n }\n\n if (searchable) {\n return { placeholder: searchPlaceholder };\n }\n\n return undefined;\n}\n\nfunction resolveContentSearch<T extends CollectionItem>(\n search: SelectContentOwnProps<T>['search'],\n collection: CollectionAdapterResult<T>,\n): SelectContentOwnProps<T>['search'] {\n if (typeof search !== 'object') {\n return search;\n }\n\n return {\n ...search,\n inputValue: collection.inputValue,\n defaultInputValue: collection.defaultInputValue,\n onInputChange: collection.onInputChange,\n } as SelectContentOwnProps<T>['search'];\n}\n\nfunction getRetainedOptions<T extends CollectionItem>(\n flatOptions: NormalizedOption[] | undefined,\n canonicalItems: T[],\n) {\n if (!flatOptions) {\n return undefined;\n }\n\n const sourceIds = getItemKeys(flatOptions);\n return canonicalItems.filter(item => !sourceIds.has(item.id));\n}\n\n/**\n * A dropdown picker for selecting one or multiple options from a list, with optional search filtering and inline error display.\n *\n * @public\n */\nfunction SelectImpl<\n M extends 'single' | 'multiple' = 'single' | 'multiple',\n T extends CollectionItem = NormalizedOption,\n>(props: SelectProps<M, T>, ref: React.ForwardedRef<HTMLDivElement>) {\n const { ownProps, restProps, dataAttributes } = useDefinition(\n SelectDefinition,\n {\n placeholder: 'Select an option',\n ...props,\n },\n );\n\n const {\n classes,\n label,\n description,\n options,\n icon,\n searchable,\n searchPlaceholder,\n search,\n loading,\n items,\n children,\n dependencies,\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 'Select 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 resolvedSearch = resolveSelectSearch<T>({\n search: search as SelectContentOwnProps<T>['search'],\n searchable,\n searchPlaceholder,\n });\n const collectionSource = resolveCollectionSource<T>({ options, items });\n const controlledValue =\n restProps.value !== undefined ? restProps.value : restProps.selectedKey;\n const defaultValue =\n restProps.defaultValue !== undefined\n ? restProps.defaultValue\n : restProps.defaultSelectedKey;\n const trackedSelection = useTrackedSelectionKeys({\n selectedKeys:\n controlledValue === undefined ? undefined : toSelection(controlledValue),\n defaultSelectedKeys: toSelection(defaultValue),\n });\n const collection = useCollectionAdapter({\n items: collectionSource.source,\n selectedKeys: trackedSelection.selectedKeys,\n search: resolvedSearch,\n loading,\n });\n const retainedOptions = getRetainedOptions(\n collectionSource.flatOptions,\n collection.canonicalItems,\n );\n const renderedItems = collectionSource.rendersItems\n ? collection.canonicalItems\n : undefined;\n const contentSearch = resolveContentSearch(resolvedSearch, collection);\n const handleChange = (value: ChangeValueType<M>) => {\n trackedSelection.onSelectionChange(toSelection(value));\n restProps.onChange?.(value);\n };\n\n return (\n <AriaSelect\n className={classes.root}\n {...dataAttributes}\n ref={ref}\n {...restProps}\n onChange={handleChange}\n allowsEmptyCollection\n >\n <FieldLabel\n label={label}\n secondaryLabel={secondaryLabelText}\n description={description}\n descriptionSlot=\"description\"\n />\n <SelectTrigger icon={icon} />\n <FieldError />\n <Popover className={classes.popover} hideArrow {...dataAttributes}>\n <SelectContent\n search={contentSearch}\n options={collectionSource.options}\n items={renderedItems}\n dependencies={dependencies}\n loading={collection.loading}\n isStale={collection.isStale}\n visibleIds={collection.visibleIds}\n retainedOptions={\n retainedOptions as unknown as ReadonlyArray<NormalizedOption>\n }\n >\n {children}\n </SelectContent>\n </Popover>\n </AriaSelect>\n );\n}\n\n/** @public */\nexport const Select = forwardRef(SelectImpl) as {\n <\n M extends 'single' | 'multiple' = 'single' | 'multiple',\n T extends { id: Key } = NormalizedOption,\n >(\n props: SelectProps<M, T> & React.RefAttributes<HTMLDivElement>,\n ): React.ReactElement | null;\n displayName?: string;\n};\n\nSelect.displayName = 'Select';\n"],"names":["AriaSelect"],"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 2025 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 .Select_bui-Select__2bfd6c12b2,\n .Select_bui-SelectPopover__2bfd6c12b2 {\n &[data-size='small'] {\n --select-item-height: 2rem;\n }\n\n &[data-size='medium'] {\n --select-item-height: 2.5rem;\n }\n }\n\n .Select_bui-Select__2bfd6c12b2 {\n display: flex;\n flex-direction: column;\n width: 100%;\n flex: 1;\n }\n\n .Select_bui-SelectPopover__2bfd6c12b2 {\n min-width: var(--trigger-width);\n }\n\n .Select_bui-SelectTrigger__2bfd6c12b2 {\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 .Select_bui-Select__2bfd6c12b2[data-focused] & {\n box-shadow: inset 0 0 0 1px var(--bui-ring);\n }\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n gap: var(--bui-space-2);\n width: 100%;\n height: var(--select-item-height);\n\n .Select_bui-Select__2bfd6c12b2[data-size='small'] & {\n padding-inline: var(--bui-space-3) 0;\n }\n\n .Select_bui-Select__2bfd6c12b2[data-size='medium'] & {\n padding-inline: var(--bui-space-4) 0;\n }\n\n & svg {\n flex-shrink: 0;\n color: var(--bui-fg-secondary);\n\n .Select_bui-Select__2bfd6c12b2[data-size='small'] & {\n width: 1rem;\n height: 1rem;\n }\n\n .Select_bui-Select__2bfd6c12b2[data-size='medium'] & {\n width: 1.25rem;\n height: 1.25rem;\n }\n }\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n\n .Select_bui-Select__2bfd6c12b2[data-invalid] & {\n box-shadow: inset 0 0 0 1px var(--bui-border-danger);\n }\n\n &[disabled] {\n cursor: not-allowed;\n color: var(--bui-fg-disabled);\n }\n }\n\n .Select_bui-SelectTriggerChevron__2bfd6c12b2 {\n display: grid;\n place-content: center;\n width: var(--select-item-height);\n height: var(--select-item-height);\n flex-shrink: 0;\n flex-grow: 0;\n }\n\n .Select_bui-SelectValue__2bfd6c12b2 {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n width: 100%;\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n font-weight: var(--bui-font-weight-regular);\n color: var(--bui-fg-primary);\n text-align: left;\n\n & .Select_bui-SelectItemIndicator__2bfd6c12b2 {\n display: none;\n }\n\n &[disabled] {\n color: var(--bui-fg-disabled);\n }\n }\n\n .Select_bui-SelectList__2bfd6c12b2 {\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 /* Remove default focus-visible outline because React Aria\n * triggers it on mouse click open of the list for some reason.\n * On keyboard use, the top item receives the focus style,\n * so it's not needed anyway. */\n outline: none;\n }\n }\n\n .Select_bui-SelectItem__2bfd6c12b2 {\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(--select-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] .Select_bui-SelectItemIndicator__2bfd6c12b2 {\n opacity: 1;\n }\n }\n\n .Select_bui-SelectItemIndicator__2bfd6c12b2 {\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 .Select_bui-SelectItemLabel__2bfd6c12b2 {\n flex: 1;\n grid-area: text;\n }\n\n .Select_bui-SelectSearchWrapper__2bfd6c12b2 {\n flex-shrink: 0;\n margin-bottom: var(--bui-space-1);\n display: flex;\n align-items: center;\n padding-inline: var(--bui-space-3) 0;\n border-bottom: 1px solid var(--bui-border-2);\n }\n\n .Select_bui-SelectSearch__2bfd6c12b2 {\n border: none;\n background-color: transparent;\n padding: 0;\n color: var(--bui-fg-primary);\n flex: 1;\n outline: none;\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n height: var(--select-item-height);\n line-height: var(--select-item-height);\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n\n /* Hide native browser clear button */\n &::-webkit-search-cancel-button,\n &::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n }\n\n .Select_bui-SelectSearchClear__2bfd6c12b2 {\n flex: 0 0 auto;\n display: grid;\n place-content: center;\n background-color: transparent;\n border: none;\n padding: 0;\n margin: 0;\n cursor: pointer;\n color: var(--bui-fg-secondary);\n transition: color 0.2s ease-in-out;\n width: var(--select-item-height);\n height: var(--select-item-height);\n\n input:placeholder-shown + & {\n display: none;\n }\n\n &:hover {\n color: var(--bui-fg-primary);\n }\n\n & svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Select_bui-SelectSection__2bfd6c12b2 {\n &:first-child .Select_bui-SelectSectionHeader__2bfd6c12b2 {\n padding-top: 0;\n }\n }\n\n .Select_bui-SelectSectionHeader__2bfd6c12b2 {\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 .Select_bui-SelectNoResults__2bfd6c12b2 {\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-Select":"Select_bui-Select__2bfd6c12b2","bui-SelectPopover":"Select_bui-SelectPopover__2bfd6c12b2","bui-SelectTrigger":"Select_bui-SelectTrigger__2bfd6c12b2","bui-SelectTriggerChevron":"Select_bui-SelectTriggerChevron__2bfd6c12b2","bui-SelectValue":"Select_bui-SelectValue__2bfd6c12b2","bui-SelectItemIndicator":"Select_bui-SelectItemIndicator__2bfd6c12b2","bui-SelectList":"Select_bui-SelectList__2bfd6c12b2","bui-SelectItem":"Select_bui-SelectItem__2bfd6c12b2","bui-SelectItemLabel":"Select_bui-SelectItemLabel__2bfd6c12b2","bui-SelectSearchWrapper":"Select_bui-SelectSearchWrapper__2bfd6c12b2","bui-SelectSearch":"Select_bui-SelectSearch__2bfd6c12b2","bui-SelectSearchClear":"Select_bui-SelectSearchClear__2bfd6c12b2","bui-SelectSection":"Select_bui-SelectSection__2bfd6c12b2","bui-SelectSectionHeader":"Select_bui-SelectSectionHeader__2bfd6c12b2","bui-SelectNoResults":"Select_bui-SelectNoResults__2bfd6c12b2"};
3
+ var css_248z = "/*\n * Copyright 2025 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 .Select_bui-Select__68de3fad8b,\n .Select_bui-SelectPopover__68de3fad8b {\n &[data-size='small'] {\n --select-item-height: 2rem;\n }\n\n &[data-size='medium'] {\n --select-item-height: 2.5rem;\n }\n }\n\n .Select_bui-Select__68de3fad8b {\n display: flex;\n flex-direction: column;\n width: 100%;\n flex: 1;\n }\n\n .Select_bui-SelectPopover__68de3fad8b {\n min-width: var(--trigger-width);\n\n .bui-PopoverContent {\n padding: 0;\n display: grid;\n grid-template-rows: minmax(0, 1fr);\n overflow: hidden;\n }\n }\n\n .Select_bui-SelectTrigger__68de3fad8b {\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 .Select_bui-Select__68de3fad8b[data-focused] & {\n box-shadow: inset 0 0 0 1px var(--bui-ring);\n }\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n gap: var(--bui-space-2);\n width: 100%;\n height: var(--select-item-height);\n\n .Select_bui-Select__68de3fad8b[data-size='small'] & {\n padding-inline: var(--bui-space-3) 0;\n }\n\n .Select_bui-Select__68de3fad8b[data-size='medium'] & {\n padding-inline: var(--bui-space-4) 0;\n }\n\n & svg {\n flex-shrink: 0;\n color: var(--bui-fg-secondary);\n\n .Select_bui-Select__68de3fad8b[data-size='small'] & {\n width: 1rem;\n height: 1rem;\n }\n\n .Select_bui-Select__68de3fad8b[data-size='medium'] & {\n width: 1.25rem;\n height: 1.25rem;\n }\n }\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n\n .Select_bui-Select__68de3fad8b[data-invalid] & {\n box-shadow: inset 0 0 0 1px var(--bui-border-danger);\n }\n\n &[disabled] {\n cursor: not-allowed;\n color: var(--bui-fg-disabled);\n }\n }\n\n .Select_bui-SelectTriggerChevron__68de3fad8b {\n display: grid;\n place-content: center;\n width: var(--select-item-height);\n height: var(--select-item-height);\n flex-shrink: 0;\n flex-grow: 0;\n }\n\n .Select_bui-SelectValue__68de3fad8b {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n width: 100%;\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n font-weight: var(--bui-font-weight-regular);\n color: var(--bui-fg-primary);\n text-align: left;\n\n & .Select_bui-SelectItemIndicator__68de3fad8b {\n display: none;\n }\n\n &[disabled] {\n color: var(--bui-fg-disabled);\n }\n }\n\n .Select_bui-SelectList__68de3fad8b {\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 /* Remove default focus-visible outline because React Aria\n * triggers it on mouse click open of the list for some reason.\n * On keyboard use, the top item receives the focus style,\n * so it's not needed anyway. */\n outline: none;\n }\n }\n\n .Select_bui-SelectItem__68de3fad8b {\n box-sizing: border-box;\n position: relative;\n display: block;\n min-height: var(--select-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(> .Select_bui-SelectItemIndicator__68de3fad8b) {\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] .Select_bui-SelectItemIndicator__68de3fad8b {\n opacity: 1;\n }\n }\n\n .Select_bui-SelectItemIndicator__68de3fad8b {\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 .Select_bui-SelectItemLabel__68de3fad8b {\n flex: 1;\n grid-area: text;\n }\n\n .Select_bui-SelectItemContent__68de3fad8b {\n grid-area: text;\n display: flex;\n align-items: center;\n gap: var(--bui-space-2);\n min-width: 0;\n }\n\n .Select_bui-SelectItemLeadingIcon__68de3fad8b {\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 .Select_bui-SelectItemAvatar__68de3fad8b {\n flex-shrink: 0;\n }\n\n .Select_bui-SelectItemTextContent__68de3fad8b {\n display: flex;\n flex-direction: column;\n min-width: 0;\n }\n\n .Select_bui-SelectItemTitle__68de3fad8b,\n .Select_bui-SelectItemDescription__68de3fad8b {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .Select_bui-SelectItemDescription__68de3fad8b {\n font-size: var(--bui-font-size-2);\n color: var(--bui-fg-secondary);\n }\n\n .Select_bui-SelectSearchWrapper__68de3fad8b {\n flex-shrink: 0;\n margin-bottom: var(--bui-space-1);\n display: flex;\n align-items: center;\n padding-inline: var(--bui-space-3) 0;\n border-bottom: 1px solid var(--bui-border-2);\n }\n\n .Select_bui-SelectContent__68de3fad8b {\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n min-height: 0;\n }\n\n .Select_bui-SelectResults__68de3fad8b {\n grid-row: 2;\n min-height: 0;\n overflow: auto;\n }\n\n .Select_bui-SelectSearch__68de3fad8b {\n border: none;\n background-color: transparent;\n padding: 0;\n color: var(--bui-fg-primary);\n flex: 1;\n outline: none;\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n height: var(--select-item-height);\n line-height: var(--select-item-height);\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n\n /* Hide native browser clear button */\n &::-webkit-search-cancel-button,\n &::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n }\n\n .Select_bui-SelectSearchClear__68de3fad8b {\n flex: 0 0 auto;\n display: grid;\n place-content: center;\n background-color: transparent;\n border: none;\n padding: 0;\n margin: 0;\n cursor: pointer;\n color: var(--bui-fg-secondary);\n transition: color 0.2s ease-in-out;\n width: var(--select-item-height);\n height: var(--select-item-height);\n\n input:placeholder-shown + & {\n display: none;\n }\n\n &:hover {\n color: var(--bui-fg-primary);\n }\n\n & svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Select_bui-SelectSection__68de3fad8b {\n &:first-child .Select_bui-SelectSectionHeader__68de3fad8b {\n padding-top: 0;\n }\n }\n\n .Select_bui-SelectSectionHeader__68de3fad8b {\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 .Select_bui-SelectNoResults__68de3fad8b {\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 .Select_bui-SelectLoading__68de3fad8b {\n display: flex;\n flex-direction: column;\n width: 100%;\n }\n\n .Select_bui-SelectLoadingRow__68de3fad8b {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n min-height: var(--select-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-Select":"Select_bui-Select__68de3fad8b","bui-SelectPopover":"Select_bui-SelectPopover__68de3fad8b","bui-SelectTrigger":"Select_bui-SelectTrigger__68de3fad8b","bui-SelectTriggerChevron":"Select_bui-SelectTriggerChevron__68de3fad8b","bui-SelectValue":"Select_bui-SelectValue__68de3fad8b","bui-SelectItemIndicator":"Select_bui-SelectItemIndicator__68de3fad8b","bui-SelectList":"Select_bui-SelectList__68de3fad8b","bui-SelectItem":"Select_bui-SelectItem__68de3fad8b","bui-SelectItemLabel":"Select_bui-SelectItemLabel__68de3fad8b","bui-SelectItemContent":"Select_bui-SelectItemContent__68de3fad8b","bui-SelectItemLeadingIcon":"Select_bui-SelectItemLeadingIcon__68de3fad8b","bui-SelectItemAvatar":"Select_bui-SelectItemAvatar__68de3fad8b","bui-SelectItemTextContent":"Select_bui-SelectItemTextContent__68de3fad8b","bui-SelectItemTitle":"Select_bui-SelectItemTitle__68de3fad8b","bui-SelectItemDescription":"Select_bui-SelectItemDescription__68de3fad8b","bui-SelectSearchWrapper":"Select_bui-SelectSearchWrapper__68de3fad8b","bui-SelectContent":"Select_bui-SelectContent__68de3fad8b","bui-SelectResults":"Select_bui-SelectResults__68de3fad8b","bui-SelectSearch":"Select_bui-SelectSearch__68de3fad8b","bui-SelectSearchClear":"Select_bui-SelectSearchClear__68de3fad8b","bui-SelectSection":"Select_bui-SelectSection__68de3fad8b","bui-SelectSectionHeader":"Select_bui-SelectSectionHeader__68de3fad8b","bui-SelectNoResults":"Select_bui-SelectNoResults__68de3fad8b","bui-SelectLoading":"Select_bui-SelectLoading__68de3fad8b","bui-SelectLoadingRow":"Select_bui-SelectLoadingRow__68de3fad8b"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { styles as default };
@@ -6,28 +6,80 @@ import { useDefinition } from '../../hooks/useDefinition/useDefinition.esm.js';
6
6
  import { SelectContentDefinition } from './definition.esm.js';
7
7
  import { SelectListBox } from './SelectListBox.esm.js';
8
8
 
9
+ function getSearchFilter({
10
+ visibleIds,
11
+ filter,
12
+ contains
13
+ }) {
14
+ if (visibleIds) {
15
+ return (_textValue, _inputValue, node) => visibleIds.has(node.key);
16
+ }
17
+ if (filter) {
18
+ return (_textValue, inputValue, node) => filter(node.value, inputValue);
19
+ }
20
+ return (textValue, inputValue) => contains(textValue, inputValue);
21
+ }
9
22
  function SelectContent(props) {
10
23
  const { contains } = useFilter({ sensitivity: "base" });
11
24
  const { ownProps } = useDefinition(SelectContentDefinition, props);
12
- const { classes, searchable, searchPlaceholder, options } = ownProps;
13
- if (!searchable) {
14
- return /* @__PURE__ */ jsx(SelectListBox, { options });
25
+ const {
26
+ classes,
27
+ search,
28
+ options,
29
+ items,
30
+ children,
31
+ dependencies,
32
+ loading,
33
+ isStale,
34
+ visibleIds,
35
+ retainedOptions
36
+ } = ownProps;
37
+ const listBox = /* @__PURE__ */ jsx("div", { className: classes.results, children: /* @__PURE__ */ jsx(
38
+ SelectListBox,
39
+ {
40
+ options,
41
+ items,
42
+ dependencies,
43
+ loading,
44
+ isStale,
45
+ retainedOptions,
46
+ children
47
+ }
48
+ ) });
49
+ if (!search) {
50
+ return /* @__PURE__ */ jsx("div", { className: classes.root, children: listBox });
15
51
  }
16
- return /* @__PURE__ */ jsxs(Autocomplete, { filter: contains, children: [
17
- /* @__PURE__ */ jsxs(
18
- SearchField,
19
- {
20
- autoFocus: true,
21
- className: classes.root,
22
- "aria-label": searchPlaceholder,
23
- children: [
24
- /* @__PURE__ */ jsx(Input, { placeholder: searchPlaceholder, className: classes.search }),
25
- /* @__PURE__ */ jsx(Button, { className: classes.searchClear, children: /* @__PURE__ */ jsx(RiCloseCircleLine, {}) })
26
- ]
27
- }
28
- ),
29
- /* @__PURE__ */ jsx(SelectListBox, { options })
30
- ] });
52
+ const searchProps = typeof search === "object" ? search : void 0;
53
+ const placeholder = searchProps?.placeholder ?? "Search...";
54
+ const filter = getSearchFilter({
55
+ visibleIds,
56
+ filter: searchProps?.filter,
57
+ contains
58
+ });
59
+ return /* @__PURE__ */ jsx(
60
+ Autocomplete,
61
+ {
62
+ inputValue: searchProps?.inputValue,
63
+ defaultInputValue: searchProps?.defaultInputValue,
64
+ onInputChange: searchProps?.onInputChange,
65
+ filter,
66
+ children: /* @__PURE__ */ jsxs("div", { className: classes.root, children: [
67
+ /* @__PURE__ */ jsxs(
68
+ SearchField,
69
+ {
70
+ autoFocus: true,
71
+ className: classes.searchWrapper,
72
+ "aria-label": placeholder,
73
+ children: [
74
+ /* @__PURE__ */ jsx(Input, { placeholder, className: classes.search }),
75
+ /* @__PURE__ */ jsx(Button, { className: classes.searchClear, children: /* @__PURE__ */ jsx(RiCloseCircleLine, {}) })
76
+ ]
77
+ }
78
+ ),
79
+ listBox
80
+ ] })
81
+ }
82
+ );
31
83
  }
32
84
 
33
85
  export { SelectContent };
@@ -1 +1 @@
1
- {"version":3,"file":"SelectContent.esm.js","sources":["../../../src/components/Select/SelectContent.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 {\n Input,\n SearchField,\n Autocomplete,\n Button,\n} from 'react-aria-components';\nimport { useFilter } from 'react-aria';\nimport { RiCloseCircleLine } from '@remixicon/react';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { SelectContentDefinition } from './definition';\nimport { SelectListBox } from './SelectListBox';\nimport type { SelectOwnProps } from './types';\n\ninterface SelectContentProps {\n searchable?: boolean;\n searchPlaceholder?: string;\n options?: SelectOwnProps['options'];\n}\n\nexport function SelectContent(props: SelectContentProps) {\n const { contains } = useFilter({ sensitivity: 'base' });\n const { ownProps } = useDefinition(SelectContentDefinition, props);\n const { classes, searchable, searchPlaceholder, options } = ownProps;\n\n if (!searchable) {\n return <SelectListBox options={options} />;\n }\n\n return (\n <Autocomplete filter={contains}>\n <SearchField\n autoFocus\n className={classes.root}\n aria-label={searchPlaceholder}\n >\n <Input placeholder={searchPlaceholder} className={classes.search} />\n <Button className={classes.searchClear}>\n <RiCloseCircleLine />\n </Button>\n </SearchField>\n <SelectListBox options={options} />\n </Autocomplete>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAmCO,SAAS,cAAc,KAAA,EAA2B;AACvD,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,UAAU,EAAE,WAAA,EAAa,QAAQ,CAAA;AACtD,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,aAAA,CAAc,yBAAyB,KAAK,CAAA;AACjE,EAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,iBAAA,EAAmB,SAAQ,GAAI,QAAA;AAE5D,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,uBAAO,GAAA,CAAC,iBAAc,OAAA,EAAkB,CAAA;AAAA,EAC1C;AAEA,EAAA,uBACE,IAAA,CAAC,YAAA,EAAA,EAAa,MAAA,EAAQ,QAAA,EACpB,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAS,IAAA;AAAA,QACT,WAAW,OAAA,CAAQ,IAAA;AAAA,QACnB,YAAA,EAAY,iBAAA;AAAA,QAEZ,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,EAAA,EAAM,WAAA,EAAa,iBAAA,EAAmB,SAAA,EAAW,QAAQ,MAAA,EAAQ,CAAA;AAAA,8BACjE,MAAA,EAAA,EAAO,SAAA,EAAW,QAAQ,WAAA,EACzB,QAAA,kBAAA,GAAA,CAAC,qBAAkB,CAAA,EACrB;AAAA;AAAA;AAAA,KACF;AAAA,oBACA,GAAA,CAAC,iBAAc,OAAA,EAAkB;AAAA,GAAA,EACnC,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"SelectContent.esm.js","sources":["../../../src/components/Select/SelectContent.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 {\n Input,\n SearchField,\n Autocomplete,\n Button,\n type Key,\n} from 'react-aria-components';\nimport { useFilter } from 'react-aria';\nimport { RiCloseCircleLine } from '@remixicon/react';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { SelectContentDefinition } from './definition';\nimport { SelectListBox } from './SelectListBox';\nimport type {\n CollectionItem,\n NormalizedOption,\n} from '../../types/selectableCollection';\nimport type { SelectContentOwnProps } from './types';\nimport type { Node } from '@react-types/shared';\n\ntype SearchFilter<T extends CollectionItem> = (\n textValue: string,\n inputValue: string,\n node: Node<T>,\n) => boolean;\n\nfunction getSearchFilter<T extends CollectionItem>({\n visibleIds,\n filter,\n contains,\n}: {\n visibleIds?: Set<Key>;\n filter?: (item: T, query: string) => boolean;\n contains: (textValue: string, inputValue: string) => boolean;\n}): SearchFilter<T> {\n if (visibleIds) {\n return (_textValue, _inputValue, node) => visibleIds.has(node.key);\n }\n\n if (filter) {\n return (_textValue, inputValue, node) =>\n filter(node.value as T, inputValue);\n }\n\n return (textValue, inputValue) => contains(textValue, inputValue);\n}\n\nexport function SelectContent<T extends CollectionItem = NormalizedOption>(\n props: SelectContentOwnProps<T>,\n) {\n const { contains } = useFilter({ sensitivity: 'base' });\n const { ownProps } = useDefinition(SelectContentDefinition, props);\n const {\n classes,\n search,\n options,\n items,\n children,\n dependencies,\n loading,\n isStale,\n visibleIds,\n retainedOptions,\n } = ownProps;\n\n const listBox = (\n <div className={classes.results}>\n <SelectListBox\n options={options}\n items={items}\n dependencies={dependencies}\n loading={loading}\n isStale={isStale}\n retainedOptions={retainedOptions}\n >\n {children}\n </SelectListBox>\n </div>\n );\n\n if (!search) {\n return <div className={classes.root}>{listBox}</div>;\n }\n\n const searchProps = typeof search === 'object' ? search : undefined;\n const placeholder = searchProps?.placeholder ?? 'Search...';\n const filter = getSearchFilter({\n visibleIds,\n filter: searchProps?.filter,\n contains,\n });\n\n return (\n <Autocomplete\n inputValue={searchProps?.inputValue}\n defaultInputValue={searchProps?.defaultInputValue}\n onInputChange={searchProps?.onInputChange}\n filter={filter}\n >\n <div className={classes.root}>\n <SearchField\n autoFocus\n className={classes.searchWrapper}\n aria-label={placeholder}\n >\n <Input placeholder={placeholder} className={classes.search} />\n <Button className={classes.searchClear}>\n <RiCloseCircleLine />\n </Button>\n </SearchField>\n {listBox}\n </div>\n </Autocomplete>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAyCA,SAAS,eAAA,CAA0C;AAAA,EACjD,UAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAIoB;AAClB,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAO,CAAC,UAAA,EAAY,WAAA,EAAa,SAAS,UAAA,CAAW,GAAA,CAAI,KAAK,GAAG,CAAA;AAAA,EACnE;AAEA,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,OAAO,CAAC,UAAA,EAAY,UAAA,EAAY,SAC9B,MAAA,CAAO,IAAA,CAAK,OAAY,UAAU,CAAA;AAAA,EACtC;AAEA,EAAA,OAAO,CAAC,SAAA,EAAW,UAAA,KAAe,QAAA,CAAS,WAAW,UAAU,CAAA;AAClE;AAEO,SAAS,cACd,KAAA,EACA;AACA,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,UAAU,EAAE,WAAA,EAAa,QAAQ,CAAA;AACtD,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,aAAA,CAAc,yBAAyB,KAAK,CAAA;AACjE,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,YAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF,GAAI,QAAA;AAEJ,EAAA,MAAM,OAAA,mBACJ,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,QAAQ,OAAA,EACtB,QAAA,kBAAA,GAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,KAAA;AAAA,MACA,YAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,eAAA;AAAA,MAEC;AAAA;AAAA,GACH,EACF,CAAA;AAGF,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,MAAO,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,EAChD;AAEA,EAAA,MAAM,WAAA,GAAc,OAAO,MAAA,KAAW,QAAA,GAAW,MAAA,GAAS,MAAA;AAC1D,EAAA,MAAM,WAAA,GAAc,aAAa,WAAA,IAAe,WAAA;AAChD,EAAA,MAAM,SAAS,eAAA,CAAgB;AAAA,IAC7B,UAAA;AAAA,IACA,QAAQ,WAAA,EAAa,MAAA;AAAA,IACrB;AAAA,GACD,CAAA;AAED,EAAA,uBACE,GAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,YAAY,WAAA,EAAa,UAAA;AAAA,MACzB,mBAAmB,WAAA,EAAa,iBAAA;AAAA,MAChC,eAAe,WAAA,EAAa,aAAA;AAAA,MAC5B,MAAA;AAAA,MAEA,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,IAAA,EACtB,QAAA,EAAA;AAAA,wBAAA,IAAA;AAAA,UAAC,WAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAS,IAAA;AAAA,YACT,WAAW,OAAA,CAAQ,aAAA;AAAA,YACnB,YAAA,EAAY,WAAA;AAAA,YAEZ,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,KAAA,EAAA,EAAM,WAAA,EAA0B,SAAA,EAAW,OAAA,CAAQ,MAAA,EAAQ,CAAA;AAAA,kCAC3D,MAAA,EAAA,EAAO,SAAA,EAAW,QAAQ,WAAA,EACzB,QAAA,kBAAA,GAAA,CAAC,qBAAkB,CAAA,EACrB;AAAA;AAAA;AAAA,SACF;AAAA,QACC;AAAA,OAAA,EACH;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -0,0 +1,76 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { RiCheckLine } from '@remixicon/react';
3
+ import { ListBoxItem, Text } from 'react-aria-components';
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 { SelectItemDefinition, SelectItemProfileDefinition, SelectItemTextDefinition } from './definition.esm.js';
8
+
9
+ function SelectItem(props) {
10
+ const { ownProps, restProps } = useDefinition(SelectItemDefinition, props);
11
+ const { classes, children, showSelectionIndicator } = ownProps;
12
+ return /* @__PURE__ */ jsx(ListBoxItem, { className: classes.root, ...restProps, 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 SelectItemText(props) {
24
+ const { ownProps, restProps } = useDefinition(
25
+ SelectItemTextDefinition,
26
+ props
27
+ );
28
+ const { classes, title, description, leadingIcon } = ownProps;
29
+ return /* @__PURE__ */ jsx(
30
+ SelectItem,
31
+ {
32
+ className: classes.root,
33
+ textValue: title,
34
+ showSelectionIndicator: true,
35
+ ...restProps,
36
+ children: /* @__PURE__ */ jsxs("div", { className: classes.content, 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 SelectItemProfile(props) {
47
+ const { ownProps, restProps } = useDefinition(
48
+ SelectItemProfileDefinition,
49
+ props
50
+ );
51
+ const { classes, name, src } = ownProps;
52
+ return /* @__PURE__ */ jsx(
53
+ SelectItem,
54
+ {
55
+ className: classes.root,
56
+ textValue: name,
57
+ showSelectionIndicator: true,
58
+ ...restProps,
59
+ children: /* @__PURE__ */ jsxs("div", { className: classes.content, 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 { SelectItem, SelectItemProfile, SelectItemText };
76
+ //# sourceMappingURL=SelectItem.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectItem.esm.js","sources":["../../../src/components/Select/SelectItem.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 { RiCheckLine } from '@remixicon/react';\nimport { ListBoxItem, Text } from 'react-aria-components';\nimport { Avatar } from '../Avatar';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport {\n SelectItemDefinition,\n SelectItemProfileDefinition,\n SelectItemTextDefinition,\n} from './definition';\nimport type {\n SelectItemProfileProps,\n SelectItemProps,\n SelectItemTextProps,\n} from './types';\n\n/**\n * A low-level Select item wrapper for custom item content.\n *\n * @public\n */\nexport function SelectItem<T extends object = object>(\n props: SelectItemProps<T>,\n) {\n const { ownProps, restProps } = useDefinition(SelectItemDefinition, props);\n const { classes, children, showSelectionIndicator } = ownProps;\n\n return (\n <ListBoxItem className={classes.root} {...restProps}>\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 Select item preset with a title and optional supporting content.\n *\n * @public\n */\nexport function SelectItemText<T extends object = object>(\n props: SelectItemTextProps<T>,\n) {\n const { ownProps, restProps } = useDefinition(\n SelectItemTextDefinition,\n props,\n );\n const { classes, title, description, leadingIcon } = ownProps;\n\n return (\n <SelectItem\n className={classes.root}\n textValue={title}\n showSelectionIndicator\n {...restProps}\n >\n <div className={classes.content}>\n {leadingIcon && (\n <div className={classes.leadingIcon}>{leadingIcon}</div>\n )}\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 </div>\n </SelectItem>\n );\n}\n\n/**\n * A Select item preset for a person or other named profile.\n *\n * @public\n */\nexport function SelectItemProfile<T extends object = object>(\n props: SelectItemProfileProps<T>,\n) {\n const { ownProps, restProps } = useDefinition(\n SelectItemProfileDefinition,\n props,\n );\n const { classes, name, src } = ownProps;\n\n return (\n <SelectItem\n className={classes.root}\n textValue={name}\n showSelectionIndicator\n {...restProps}\n >\n <div className={classes.content}>\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 </div>\n </SelectItem>\n );\n}\n"],"names":[],"mappings":"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"}