@backstage/ui 0.13.0-next.2 → 0.13.1

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 (76) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/dist/components/Accordion/Accordion.module.css.esm.js +2 -2
  3. package/dist/components/Button/Button.module.css.esm.js +2 -2
  4. package/dist/components/ButtonIcon/ButtonIcon.module.css.esm.js +2 -2
  5. package/dist/components/ButtonLink/ButtonLink.esm.js +2 -3
  6. package/dist/components/ButtonLink/ButtonLink.esm.js.map +1 -1
  7. package/dist/components/ButtonLink/ButtonLink.module.css.esm.js +2 -2
  8. package/dist/components/Card/Card.esm.js +1 -1
  9. package/dist/components/Card/Card.esm.js.map +1 -1
  10. package/dist/components/Card/Card.module.css.esm.js +2 -2
  11. package/dist/components/Checkbox/Checkbox.esm.js +12 -3
  12. package/dist/components/Checkbox/Checkbox.esm.js.map +1 -1
  13. package/dist/components/Checkbox/Checkbox.module.css.esm.js +2 -2
  14. package/dist/components/Checkbox/definition.esm.js +0 -2
  15. package/dist/components/Checkbox/definition.esm.js.map +1 -1
  16. package/dist/components/Container/Container.module.css.esm.js +2 -2
  17. package/dist/components/Dialog/Dialog.esm.js +3 -1
  18. package/dist/components/Dialog/Dialog.esm.js.map +1 -1
  19. package/dist/components/Dialog/Dialog.module.css.esm.js +2 -2
  20. package/dist/components/Header/Header.module.css.esm.js +2 -2
  21. package/dist/components/Header/definition.esm.js +5 -5
  22. package/dist/components/Header/definition.esm.js.map +1 -1
  23. package/dist/components/Link/Link.esm.js +1 -2
  24. package/dist/components/Link/Link.esm.js.map +1 -1
  25. package/dist/components/List/List.esm.js +70 -0
  26. package/dist/components/List/List.esm.js.map +1 -0
  27. package/dist/components/List/List.module.css.esm.js +8 -0
  28. package/dist/components/List/List.module.css.esm.js.map +1 -0
  29. package/dist/components/List/definition.esm.js +44 -0
  30. package/dist/components/List/definition.esm.js.map +1 -0
  31. package/dist/components/Menu/Menu.esm.js +5 -7
  32. package/dist/components/Menu/Menu.esm.js.map +1 -1
  33. package/dist/components/Menu/Menu.module.css.esm.js +2 -2
  34. package/dist/components/PluginHeader/PluginHeader.esm.js +38 -8
  35. package/dist/components/PluginHeader/PluginHeader.esm.js.map +1 -1
  36. package/dist/components/SearchAutocomplete/SearchAutocomplete.esm.js +164 -0
  37. package/dist/components/SearchAutocomplete/SearchAutocomplete.esm.js.map +1 -0
  38. package/dist/components/SearchAutocomplete/SearchAutocomplete.module.css.esm.js +8 -0
  39. package/dist/components/SearchAutocomplete/SearchAutocomplete.module.css.esm.js.map +1 -0
  40. package/dist/components/SearchAutocomplete/definition.esm.js +53 -0
  41. package/dist/components/SearchAutocomplete/definition.esm.js.map +1 -0
  42. package/dist/components/Select/Select.module.css.esm.js +2 -2
  43. package/dist/components/Table/Table.module.css.esm.js +2 -2
  44. package/dist/components/Table/components/Row.esm.js +21 -9
  45. package/dist/components/Table/components/Row.esm.js.map +1 -1
  46. package/dist/components/Table/components/Table.esm.js +80 -68
  47. package/dist/components/Table/components/Table.esm.js.map +1 -1
  48. package/dist/components/Table/components/TableBodySkeleton.esm.js +33 -0
  49. package/dist/components/Table/components/TableBodySkeleton.esm.js.map +1 -0
  50. package/dist/components/Table/components/TableHeader.esm.js +2 -2
  51. package/dist/components/Table/components/TableHeader.esm.js.map +1 -1
  52. package/dist/components/Table/components/TableRoot.esm.js +1 -1
  53. package/dist/components/Table/components/TableRoot.esm.js.map +1 -1
  54. package/dist/components/Table/definition.esm.js +14 -2
  55. package/dist/components/Table/definition.esm.js.map +1 -1
  56. package/dist/components/Table/hooks/useCompletePagination.esm.js +14 -6
  57. package/dist/components/Table/hooks/useCompletePagination.esm.js.map +1 -1
  58. package/dist/components/Tabs/Tabs.esm.js +3 -5
  59. package/dist/components/Tabs/Tabs.esm.js.map +1 -1
  60. package/dist/components/TagGroup/TagGroup.esm.js +2 -5
  61. package/dist/components/TagGroup/TagGroup.esm.js.map +1 -1
  62. package/dist/components/ToggleButtonGroup/ToggleButtonGroup.module.css.esm.js +2 -2
  63. package/dist/css/styles.css +4 -3
  64. package/dist/index.d.ts +338 -41
  65. package/dist/index.esm.js +5 -1
  66. package/dist/index.esm.js.map +1 -1
  67. package/dist/provider/BUIProvider.esm.js +28 -0
  68. package/dist/provider/BUIProvider.esm.js.map +1 -0
  69. package/dist/utils/{isExternalLink.esm.js → linkUtils.esm.js} +5 -2
  70. package/dist/utils/linkUtils.esm.js.map +1 -0
  71. package/package.json +4 -4
  72. package/dist/analytics/BUIProvider.esm.js +0 -18
  73. package/dist/analytics/BUIProvider.esm.js.map +0 -1
  74. package/dist/components/InternalLinkProvider/InternalLinkProvider.esm.js +0 -55
  75. package/dist/components/InternalLinkProvider/InternalLinkProvider.esm.js.map +0 -1
  76. package/dist/utils/isExternalLink.esm.js.map +0 -1
@@ -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 .Menu_bui-MenuPopover__4a32956efb {\n --menu-border-radius: var(--bui-radius-2);\n display: flex;\n flex-direction: column;\n box-shadow: var(--bui-shadow);\n border: 1px solid var(--bui-border-1);\n border-radius: var(--menu-border-radius);\n background: var(--bui-bg-app);\n color: var(--bui-fg-primary);\n outline: none;\n transition: transform 200ms, opacity 200ms;\n /* Let React Aria handle height constraints naturally */\n min-height: 0;\n /* Remove overflow from popover since ScrollArea will handle it */\n overflow: hidden;\n\n &[data-entering],\n &[data-exiting] {\n transform: var(--origin);\n opacity: 0;\n }\n\n &[data-placement='top'] {\n --origin: translateY(8px);\n }\n\n &[data-placement='bottom'] {\n --origin: translateY(-8px);\n }\n\n &[data-placement='right'] {\n --origin: translateX(-8px);\n }\n\n &[data-placement='left'] {\n --origin: translateX(8px);\n }\n }\n\n .Menu_bui-MenuInner__4a32956efb {\n border-radius: var(--menu-border-radius);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n }\n\n .Menu_bui-MenuContent__4a32956efb {\n max-height: inherit;\n box-sizing: border-box;\n overflow: auto;\n min-width: 150px;\n box-sizing: border-box;\n outline: none;\n padding-block: var(--bui-space-1);\n }\n\n .Menu_bui-MenuItem__4a32956efb {\n padding-inline: var(--bui-space-1);\n display: block;\n\n &:focus-visible {\n outline: none;\n }\n\n &[data-focus-visible] {\n outline: 2px solid var(--bui-ring);\n outline-offset: -2px;\n }\n\n &[data-focused] .Menu_bui-MenuItemWrapper__4a32956efb {\n background: var(--bui-bg-neutral-2);\n color: var(--bui-fg-primary);\n }\n\n &[data-open] .Menu_bui-MenuItemWrapper__4a32956efb {\n background: var(--bui-bg-neutral-2);\n color: var(--bui-fg-primary);\n }\n\n &[data-color='danger'] .Menu_bui-MenuItemWrapper__4a32956efb {\n color: var(--bui-fg-danger);\n }\n\n &[data-color='danger'][data-focused] .Menu_bui-MenuItemWrapper__4a32956efb {\n background: var(--bui-bg-danger);\n color: var(--bui-fg-danger);\n }\n\n &[data-has-submenu] {\n & > .Menu_bui-MenuItemWrapper__4a32956efb > .Menu_bui-MenuItemArrow__4a32956efb {\n display: block;\n }\n }\n }\n\n .Menu_bui-MenuItemWrapper__4a32956efb {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 2rem;\n padding-inline: var(--bui-space-2);\n border-radius: var(--bui-radius-2);\n outline: none;\n cursor: default;\n color: var(--bui-fg-primary);\n font-size: var(--bui-font-size-3);\n gap: var(--bui-space-6);\n }\n\n .Menu_bui-MenuItemListBox__4a32956efb {\n padding-inline: var(--bui-space-1);\n display: block;\n\n &:hover .Menu_bui-MenuItemWrapper__4a32956efb {\n background: var(--bui-bg-neutral-2);\n color: var(--bui-fg-primary);\n }\n\n &[data-selected] .Menu_bui-MenuItemListBoxCheck__4a32956efb {\n & > svg {\n opacity: 1;\n color: var(--bui-fg-primary);\n }\n }\n }\n\n .Menu_bui-MenuItemListBoxCheck__4a32956efb {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n\n & > svg {\n opacity: 0;\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Menu_bui-MenuItemContent__4a32956efb {\n display: flex;\n align-items: center;\n gap: var(--bui-space-2);\n\n & > svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Menu_bui-MenuItemArrow__4a32956efb {\n display: none;\n width: 1rem;\n height: 1rem;\n\n & > svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Menu_bui-MenuSection__4a32956efb {\n &:first-child .Menu_bui-MenuSectionHeader__4a32956efb {\n padding-top: 0;\n }\n }\n\n .Menu_bui-MenuSectionHeader__4a32956efb {\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 .Menu_bui-MenuSeparator__4a32956efb {\n height: 1px;\n background: var(--bui-border-1);\n margin-inline: var(--bui-space-1_5);\n margin-block: var(--bui-space-1);\n }\n\n .Menu_bui-MenuSearchField__4a32956efb {\n font-family: var(--bui-font-regular);\n width: 100%;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n border-bottom: 1px solid var(--bui-border-1);\n background-color: var(--bui-bg-neutral-1);\n height: 2rem;\n\n &[data-empty] {\n .Menu_bui-MenuSearchFieldClear__4a32956efb {\n visibility: hidden;\n }\n }\n }\n\n .Menu_bui-MenuSearchFieldInput__4a32956efb {\n flex: 1;\n display: flex;\n align-items: center;\n padding: 0;\n border: none;\n background-color: transparent;\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 width: 100%;\n height: 100%;\n outline: none;\n cursor: inherit;\n\n &::-webkit-search-cancel-button,\n &::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n\n &:first-child {\n padding-inline: var(--bui-space-3) 0;\n }\n }\n\n .Menu_bui-MenuSearchFieldClear__4a32956efb {\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: 2rem;\n height: 2rem;\n\n &:hover {\n color: var(--bui-fg-primary);\n }\n\n & > svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Menu_bui-MenuEmptyState__4a32956efb {\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-MenuPopover":"Menu_bui-MenuPopover__4a32956efb","bui-MenuInner":"Menu_bui-MenuInner__4a32956efb","bui-MenuContent":"Menu_bui-MenuContent__4a32956efb","bui-MenuItem":"Menu_bui-MenuItem__4a32956efb","bui-MenuItemWrapper":"Menu_bui-MenuItemWrapper__4a32956efb","bui-MenuItemArrow":"Menu_bui-MenuItemArrow__4a32956efb","bui-MenuItemListBox":"Menu_bui-MenuItemListBox__4a32956efb","bui-MenuItemListBoxCheck":"Menu_bui-MenuItemListBoxCheck__4a32956efb","bui-MenuItemContent":"Menu_bui-MenuItemContent__4a32956efb","bui-MenuSection":"Menu_bui-MenuSection__4a32956efb","bui-MenuSectionHeader":"Menu_bui-MenuSectionHeader__4a32956efb","bui-MenuSeparator":"Menu_bui-MenuSeparator__4a32956efb","bui-MenuSearchField":"Menu_bui-MenuSearchField__4a32956efb","bui-MenuSearchFieldClear":"Menu_bui-MenuSearchFieldClear__4a32956efb","bui-MenuSearchFieldInput":"Menu_bui-MenuSearchFieldInput__4a32956efb","bui-MenuEmptyState":"Menu_bui-MenuEmptyState__4a32956efb"};
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 .Menu_bui-MenuPopover__1c7774ee5f {\n --menu-border-radius: var(--bui-radius-2);\n display: flex;\n flex-direction: column;\n box-shadow: var(--bui-shadow);\n border: 1px solid var(--bui-border-1);\n border-radius: var(--menu-border-radius);\n background: var(--bui-bg-app);\n color: var(--bui-fg-primary);\n outline: none;\n transition: transform 200ms, opacity 200ms;\n /* Let React Aria handle height constraints naturally */\n min-height: 0;\n /* Remove overflow from popover since ScrollArea will handle it */\n overflow: hidden;\n\n &[data-entering],\n &[data-exiting] {\n transform: var(--origin);\n opacity: 0;\n }\n\n &[data-placement='top'] {\n --origin: translateY(8px);\n }\n\n &[data-placement='bottom'] {\n --origin: translateY(-8px);\n }\n\n &[data-placement='right'] {\n --origin: translateX(-8px);\n }\n\n &[data-placement='left'] {\n --origin: translateX(8px);\n }\n }\n\n .Menu_bui-MenuInner__1c7774ee5f {\n border-radius: var(--menu-border-radius);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n }\n\n .Menu_bui-MenuContent__1c7774ee5f {\n max-height: inherit;\n box-sizing: border-box;\n overflow: auto;\n min-width: 150px;\n box-sizing: border-box;\n outline: none;\n padding-block: var(--bui-space-1);\n }\n\n .Menu_bui-MenuItem__1c7774ee5f {\n padding-inline: var(--bui-space-1);\n display: block;\n\n &[data-focus-visible] {\n outline: none;\n }\n\n &[data-focus-visible] {\n outline: 2px solid var(--bui-ring);\n outline-offset: -2px;\n }\n\n &[data-focused] .Menu_bui-MenuItemWrapper__1c7774ee5f {\n background: var(--bui-bg-neutral-2);\n color: var(--bui-fg-primary);\n }\n\n &[data-open] .Menu_bui-MenuItemWrapper__1c7774ee5f {\n background: var(--bui-bg-neutral-2);\n color: var(--bui-fg-primary);\n }\n\n &[data-color='danger'] .Menu_bui-MenuItemWrapper__1c7774ee5f {\n color: var(--bui-fg-danger);\n }\n\n &[data-color='danger'][data-focused] .Menu_bui-MenuItemWrapper__1c7774ee5f {\n background: var(--bui-bg-danger);\n color: var(--bui-fg-danger);\n }\n\n &[data-has-submenu] {\n & > .Menu_bui-MenuItemWrapper__1c7774ee5f > .Menu_bui-MenuItemArrow__1c7774ee5f {\n display: block;\n }\n }\n }\n\n .Menu_bui-MenuItemWrapper__1c7774ee5f {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 2rem;\n padding-inline: var(--bui-space-2);\n border-radius: var(--bui-radius-2);\n outline: none;\n cursor: default;\n color: var(--bui-fg-primary);\n font-size: var(--bui-font-size-3);\n gap: var(--bui-space-6);\n }\n\n .Menu_bui-MenuItemListBox__1c7774ee5f {\n padding-inline: var(--bui-space-1);\n display: block;\n\n &:hover .Menu_bui-MenuItemWrapper__1c7774ee5f {\n background: var(--bui-bg-neutral-2);\n color: var(--bui-fg-primary);\n }\n\n &[data-selected] .Menu_bui-MenuItemListBoxCheck__1c7774ee5f {\n & > svg {\n opacity: 1;\n color: var(--bui-fg-primary);\n }\n }\n }\n\n .Menu_bui-MenuItemListBoxCheck__1c7774ee5f {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n\n & > svg {\n opacity: 0;\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Menu_bui-MenuItemContent__1c7774ee5f {\n display: flex;\n align-items: center;\n gap: var(--bui-space-2);\n\n & > svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Menu_bui-MenuItemArrow__1c7774ee5f {\n display: none;\n width: 1rem;\n height: 1rem;\n\n & > svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Menu_bui-MenuSection__1c7774ee5f {\n &:first-child .Menu_bui-MenuSectionHeader__1c7774ee5f {\n padding-top: 0;\n }\n }\n\n .Menu_bui-MenuSectionHeader__1c7774ee5f {\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 .Menu_bui-MenuSeparator__1c7774ee5f {\n height: 1px;\n background: var(--bui-border-1);\n margin-inline: var(--bui-space-1_5);\n margin-block: var(--bui-space-1);\n }\n\n .Menu_bui-MenuSearchField__1c7774ee5f {\n font-family: var(--bui-font-regular);\n width: 100%;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n border-bottom: 1px solid var(--bui-border-1);\n background-color: var(--bui-bg-neutral-1);\n height: 2rem;\n\n &[data-empty] {\n .Menu_bui-MenuSearchFieldClear__1c7774ee5f {\n visibility: hidden;\n }\n }\n }\n\n .Menu_bui-MenuSearchFieldInput__1c7774ee5f {\n flex: 1;\n display: flex;\n align-items: center;\n padding: 0;\n border: none;\n background-color: transparent;\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 width: 100%;\n height: 100%;\n outline: none;\n cursor: inherit;\n\n &::-webkit-search-cancel-button,\n &::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n\n &:first-child {\n padding-inline: var(--bui-space-3) 0;\n }\n }\n\n .Menu_bui-MenuSearchFieldClear__1c7774ee5f {\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: 2rem;\n height: 2rem;\n\n &:hover {\n color: var(--bui-fg-primary);\n }\n\n & > svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .Menu_bui-MenuEmptyState__1c7774ee5f {\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-MenuPopover":"Menu_bui-MenuPopover__1c7774ee5f","bui-MenuInner":"Menu_bui-MenuInner__1c7774ee5f","bui-MenuContent":"Menu_bui-MenuContent__1c7774ee5f","bui-MenuItem":"Menu_bui-MenuItem__1c7774ee5f","bui-MenuItemWrapper":"Menu_bui-MenuItemWrapper__1c7774ee5f","bui-MenuItemArrow":"Menu_bui-MenuItemArrow__1c7774ee5f","bui-MenuItemListBox":"Menu_bui-MenuItemListBox__1c7774ee5f","bui-MenuItemListBoxCheck":"Menu_bui-MenuItemListBoxCheck__1c7774ee5f","bui-MenuItemContent":"Menu_bui-MenuItemContent__1c7774ee5f","bui-MenuSection":"Menu_bui-MenuSection__1c7774ee5f","bui-MenuSectionHeader":"Menu_bui-MenuSectionHeader__1c7774ee5f","bui-MenuSeparator":"Menu_bui-MenuSeparator__1c7774ee5f","bui-MenuSearchField":"Menu_bui-MenuSearchField__1c7774ee5f","bui-MenuSearchFieldClear":"Menu_bui-MenuSearchFieldClear__1c7774ee5f","bui-MenuSearchFieldInput":"Menu_bui-MenuSearchFieldInput__1c7774ee5f","bui-MenuEmptyState":"Menu_bui-MenuEmptyState__1c7774ee5f"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { styles as default };
@@ -3,7 +3,7 @@ import { Tabs, TabList, Tab } from '../Tabs/Tabs.esm.js';
3
3
  import { useDefinition } from '../../hooks/useDefinition/useDefinition.esm.js';
4
4
  import '../Tabs/Tabs.module.css.esm.js';
5
5
  import { PluginHeaderDefinition } from './definition.esm.js';
6
- import { useRef } from 'react';
6
+ import { useRef, useMemo, Children } from 'react';
7
7
  import { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect.esm.js';
8
8
  import { Box } from '../Box/Box.esm.js';
9
9
  import '../Box/Box.module.css.esm.js';
@@ -28,37 +28,67 @@ const PluginHeader = (props) => {
28
28
  const toolbarWrapperRef = useRef(null);
29
29
  const toolbarContentRef = useRef(null);
30
30
  const toolbarControlsRef = useRef(null);
31
+ const animationFrameRef = useRef(void 0);
32
+ const lastAppliedHeightRef = useRef(void 0);
33
+ const actionChildren = useMemo(() => {
34
+ return Children.toArray(customActions);
35
+ }, [customActions]);
31
36
  useIsomorphicLayoutEffect(() => {
32
37
  const el = headerRef.current;
33
- if (!el) return void 0;
34
- const updateHeight = () => {
35
- const height = el.offsetHeight;
38
+ if (!el) {
39
+ return void 0;
40
+ }
41
+ const cancelScheduledUpdate = () => {
42
+ if (animationFrameRef.current === void 0) {
43
+ return;
44
+ }
45
+ cancelAnimationFrame(animationFrameRef.current);
46
+ animationFrameRef.current = void 0;
47
+ };
48
+ const applyHeight = (height) => {
49
+ if (lastAppliedHeightRef.current === height) {
50
+ return;
51
+ }
52
+ lastAppliedHeightRef.current = height;
36
53
  document.documentElement.style.setProperty(
37
54
  "--bui-header-height",
38
55
  `${height}px`
39
56
  );
40
57
  };
41
- updateHeight();
58
+ const scheduleHeightUpdate = () => {
59
+ cancelScheduledUpdate();
60
+ animationFrameRef.current = requestAnimationFrame(() => {
61
+ animationFrameRef.current = void 0;
62
+ applyHeight(el.offsetHeight);
63
+ });
64
+ };
65
+ applyHeight(el.offsetHeight);
42
66
  if (typeof ResizeObserver === "undefined") {
43
67
  return () => {
68
+ cancelScheduledUpdate();
69
+ lastAppliedHeightRef.current = void 0;
44
70
  document.documentElement.style.removeProperty("--bui-header-height");
45
71
  };
46
72
  }
47
- const observer = new ResizeObserver(updateHeight);
73
+ const observer = new ResizeObserver(() => {
74
+ scheduleHeightUpdate();
75
+ });
48
76
  observer.observe(el);
49
77
  return () => {
50
78
  observer.disconnect();
79
+ cancelScheduledUpdate();
80
+ lastAppliedHeightRef.current = void 0;
51
81
  document.documentElement.style.removeProperty("--bui-header-height");
52
82
  };
53
83
  }, []);
54
84
  const titleContent = /* @__PURE__ */ jsxs(Fragment, { children: [
55
- /* @__PURE__ */ jsx("div", { className: classes.toolbarIcon, children: icon || /* @__PURE__ */ jsx(RiShapesLine, {}) }),
85
+ /* @__PURE__ */ jsx("div", { className: classes.toolbarIcon, "aria-hidden": "true", children: icon || /* @__PURE__ */ jsx(RiShapesLine, {}) }),
56
86
  /* @__PURE__ */ jsx(Text, { variant: "body-medium", children: title || "Your plugin" })
57
87
  ] });
58
88
  return /* @__PURE__ */ jsxs("header", { ref: headerRef, className: classes.root, children: [
59
89
  /* @__PURE__ */ jsx("div", { className: classes.toolbar, "data-has-tabs": hasTabs, children: /* @__PURE__ */ jsxs("div", { className: classes.toolbarWrapper, ref: toolbarWrapperRef, children: [
60
90
  /* @__PURE__ */ jsx("div", { className: classes.toolbarContent, ref: toolbarContentRef, children: /* @__PURE__ */ jsx(Text, { as: "h1", variant: "body-medium", children: titleLink ? /* @__PURE__ */ jsx(Link, { className: classes.toolbarName, href: titleLink, children: titleContent }) : /* @__PURE__ */ jsx("div", { className: classes.toolbarName, children: titleContent }) }) }),
61
- /* @__PURE__ */ jsx("div", { className: classes.toolbarControls, ref: toolbarControlsRef, children: customActions })
91
+ /* @__PURE__ */ jsx("div", { className: classes.toolbarControls, ref: toolbarControlsRef, children: actionChildren })
62
92
  ] }) }),
63
93
  tabs && /* @__PURE__ */ jsx(Box, { bg: "neutral", className: classes.tabs, children: /* @__PURE__ */ jsx(Tabs, { onSelectionChange: onTabSelectionChange, children: /* @__PURE__ */ jsx(TabList, { children: tabs?.map((tab) => /* @__PURE__ */ jsx(
64
94
  Tab,
@@ -1 +1 @@
1
- {"version":3,"file":"PluginHeader.esm.js","sources":["../../../src/components/PluginHeader/PluginHeader.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 type { PluginHeaderProps } from './types';\nimport { Tabs, TabList, Tab } from '../Tabs';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { PluginHeaderDefinition } from './definition';\nimport { type NavigateOptions } from 'react-router-dom';\nimport { useRef } from 'react';\nimport { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect';\nimport { Box } from '../Box';\nimport { Link } from 'react-aria-components';\nimport { RiShapesLine } from '@remixicon/react';\nimport { Text } from '../Text';\n\ndeclare module 'react-aria-components' {\n interface RouterConfig {\n routerOptions: NavigateOptions;\n }\n}\n\n/**\n * A component that renders a plugin header with icon, title, custom actions,\n * and navigation tabs.\n *\n * @public\n */\nexport const PluginHeader = (props: PluginHeaderProps) => {\n const { ownProps } = useDefinition(PluginHeaderDefinition, props);\n const {\n classes,\n tabs,\n icon,\n title,\n titleLink,\n customActions,\n onTabSelectionChange,\n } = ownProps;\n\n const hasTabs = tabs && tabs.length > 0;\n const headerRef = useRef<HTMLElement>(null);\n const toolbarWrapperRef = useRef<HTMLDivElement>(null);\n const toolbarContentRef = useRef<HTMLDivElement>(null);\n const toolbarControlsRef = useRef<HTMLDivElement>(null);\n\n useIsomorphicLayoutEffect(() => {\n const el = headerRef.current;\n if (!el) return undefined;\n\n const updateHeight = () => {\n const height = el.offsetHeight;\n document.documentElement.style.setProperty(\n '--bui-header-height',\n `${height}px`,\n );\n };\n\n // Set height once immediately\n updateHeight();\n\n // Observe for resize changes if ResizeObserver is available\n // (not present in Jest/jsdom by default)\n if (typeof ResizeObserver === 'undefined') {\n return () => {\n document.documentElement.style.removeProperty('--bui-header-height');\n };\n }\n\n const observer = new ResizeObserver(updateHeight);\n observer.observe(el);\n\n return () => {\n observer.disconnect();\n document.documentElement.style.removeProperty('--bui-header-height');\n };\n }, []);\n\n const titleContent = (\n <>\n <div className={classes.toolbarIcon}>{icon || <RiShapesLine />}</div>\n <Text variant=\"body-medium\">{title || 'Your plugin'}</Text>\n </>\n );\n\n return (\n <header ref={headerRef} className={classes.root}>\n <div className={classes.toolbar} data-has-tabs={hasTabs}>\n <div className={classes.toolbarWrapper} ref={toolbarWrapperRef}>\n <div className={classes.toolbarContent} ref={toolbarContentRef}>\n <Text as=\"h1\" variant=\"body-medium\">\n {titleLink ? (\n <Link className={classes.toolbarName} href={titleLink}>\n {titleContent}\n </Link>\n ) : (\n <div className={classes.toolbarName}>{titleContent}</div>\n )}\n </Text>\n </div>\n <div className={classes.toolbarControls} ref={toolbarControlsRef}>\n {customActions}\n </div>\n </div>\n </div>\n {tabs && (\n <Box bg=\"neutral\" className={classes.tabs}>\n <Tabs onSelectionChange={onTabSelectionChange}>\n <TabList>\n {tabs?.map(tab => (\n <Tab\n key={tab.id}\n id={tab.id}\n href={tab.href}\n matchStrategy={tab.matchStrategy}\n >\n {tab.label}\n </Tab>\n ))}\n </TabList>\n </Tabs>\n </Box>\n )}\n </header>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PluginHeader.esm.js","sources":["../../../src/components/PluginHeader/PluginHeader.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 type { PluginHeaderProps } from './types';\nimport { Tabs, TabList, Tab } from '../Tabs';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport { PluginHeaderDefinition } from './definition';\nimport { type NavigateOptions } from 'react-router-dom';\nimport { Children, useMemo, useRef } from 'react';\nimport { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect';\nimport { Box } from '../Box';\nimport { Link } from 'react-aria-components';\nimport { RiShapesLine } from '@remixicon/react';\nimport { Text } from '../Text';\n\ndeclare module 'react-aria-components' {\n interface RouterConfig {\n routerOptions: NavigateOptions;\n }\n}\n\n/**\n * A component that renders a plugin header with icon, title, custom actions,\n * and navigation tabs.\n *\n * @public\n */\nexport const PluginHeader = (props: PluginHeaderProps) => {\n const { ownProps } = useDefinition(PluginHeaderDefinition, props);\n const {\n classes,\n tabs,\n icon,\n title,\n titleLink,\n customActions,\n onTabSelectionChange,\n } = ownProps;\n\n const hasTabs = tabs && tabs.length > 0;\n const headerRef = useRef<HTMLElement>(null);\n const toolbarWrapperRef = useRef<HTMLDivElement>(null);\n const toolbarContentRef = useRef<HTMLDivElement>(null);\n const toolbarControlsRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | undefined>(undefined);\n const lastAppliedHeightRef = useRef<number | undefined>(undefined);\n\n const actionChildren = useMemo(() => {\n return Children.toArray(customActions);\n }, [customActions]);\n\n useIsomorphicLayoutEffect(() => {\n const el = headerRef.current;\n if (!el) {\n return undefined;\n }\n\n const cancelScheduledUpdate = () => {\n if (animationFrameRef.current === undefined) {\n return;\n }\n\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = undefined;\n };\n\n const applyHeight = (height: number) => {\n if (lastAppliedHeightRef.current === height) {\n return;\n }\n\n lastAppliedHeightRef.current = height;\n document.documentElement.style.setProperty(\n '--bui-header-height',\n `${height}px`,\n );\n };\n\n const scheduleHeightUpdate = () => {\n cancelScheduledUpdate();\n animationFrameRef.current = requestAnimationFrame(() => {\n animationFrameRef.current = undefined;\n applyHeight(el.offsetHeight);\n });\n };\n\n // Set height once immediately so the initial layout is correct.\n applyHeight(el.offsetHeight);\n\n // Observe for resize changes if ResizeObserver is available\n // (not present in Jest/jsdom by default)\n if (typeof ResizeObserver === 'undefined') {\n return () => {\n cancelScheduledUpdate();\n lastAppliedHeightRef.current = undefined;\n document.documentElement.style.removeProperty('--bui-header-height');\n };\n }\n\n const observer = new ResizeObserver(() => {\n scheduleHeightUpdate();\n });\n observer.observe(el);\n\n return () => {\n observer.disconnect();\n cancelScheduledUpdate();\n lastAppliedHeightRef.current = undefined;\n document.documentElement.style.removeProperty('--bui-header-height');\n };\n }, []);\n\n const titleContent = (\n <>\n <div className={classes.toolbarIcon} aria-hidden=\"true\">\n {icon || <RiShapesLine />}\n </div>\n <Text variant=\"body-medium\">{title || 'Your plugin'}</Text>\n </>\n );\n\n return (\n <header ref={headerRef} className={classes.root}>\n <div className={classes.toolbar} data-has-tabs={hasTabs}>\n <div className={classes.toolbarWrapper} ref={toolbarWrapperRef}>\n <div className={classes.toolbarContent} ref={toolbarContentRef}>\n <Text as=\"h1\" variant=\"body-medium\">\n {titleLink ? (\n <Link className={classes.toolbarName} href={titleLink}>\n {titleContent}\n </Link>\n ) : (\n <div className={classes.toolbarName}>{titleContent}</div>\n )}\n </Text>\n </div>\n <div className={classes.toolbarControls} ref={toolbarControlsRef}>\n {actionChildren}\n </div>\n </div>\n </div>\n {tabs && (\n <Box bg=\"neutral\" className={classes.tabs}>\n <Tabs onSelectionChange={onTabSelectionChange}>\n <TabList>\n {tabs?.map(tab => (\n <Tab\n key={tab.id}\n id={tab.id}\n href={tab.href}\n matchStrategy={tab.matchStrategy}\n >\n {tab.label}\n </Tab>\n ))}\n </TabList>\n </Tabs>\n </Box>\n )}\n </header>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAwCO,MAAM,YAAA,GAAe,CAAC,KAAA,KAA6B;AACxD,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,aAAA,CAAc,wBAAwB,KAAK,CAAA;AAChE,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF,GAAI,QAAA;AAEJ,EAAA,MAAM,OAAA,GAAU,IAAA,IAAQ,IAAA,CAAK,MAAA,GAAS,CAAA;AACtC,EAAA,MAAM,SAAA,GAAY,OAAoB,IAAI,CAAA;AAC1C,EAAA,MAAM,iBAAA,GAAoB,OAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,iBAAA,GAAoB,OAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,kBAAA,GAAqB,OAAuB,IAAI,CAAA;AACtD,EAAA,MAAM,iBAAA,GAAoB,OAA2B,MAAS,CAAA;AAC9D,EAAA,MAAM,oBAAA,GAAuB,OAA2B,MAAS,CAAA;AAEjE,EAAA,MAAM,cAAA,GAAiB,QAAQ,MAAM;AACnC,IAAA,OAAO,QAAA,CAAS,QAAQ,aAAa,CAAA;AAAA,EACvC,CAAA,EAAG,CAAC,aAAa,CAAC,CAAA;AAElB,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,MAAM,KAAK,SAAA,CAAU,OAAA;AACrB,IAAA,IAAI,CAAC,EAAA,EAAI;AACP,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,MAAM,wBAAwB,MAAM;AAClC,MAAA,IAAI,iBAAA,CAAkB,YAAY,MAAA,EAAW;AAC3C,QAAA;AAAA,MACF;AAEA,MAAA,oBAAA,CAAqB,kBAAkB,OAAO,CAAA;AAC9C,MAAA,iBAAA,CAAkB,OAAA,GAAU,MAAA;AAAA,IAC9B,CAAA;AAEA,IAAA,MAAM,WAAA,GAAc,CAAC,MAAA,KAAmB;AACtC,MAAA,IAAI,oBAAA,CAAqB,YAAY,MAAA,EAAQ;AAC3C,QAAA;AAAA,MACF;AAEA,MAAA,oBAAA,CAAqB,OAAA,GAAU,MAAA;AAC/B,MAAA,QAAA,CAAS,gBAAgB,KAAA,CAAM,WAAA;AAAA,QAC7B,qBAAA;AAAA,QACA,GAAG,MAAM,CAAA,EAAA;AAAA,OACX;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,uBAAuB,MAAM;AACjC,MAAA,qBAAA,EAAsB;AACtB,MAAA,iBAAA,CAAkB,OAAA,GAAU,sBAAsB,MAAM;AACtD,QAAA,iBAAA,CAAkB,OAAA,GAAU,MAAA;AAC5B,QAAA,WAAA,CAAY,GAAG,YAAY,CAAA;AAAA,MAC7B,CAAC,CAAA;AAAA,IACH,CAAA;AAGA,IAAA,WAAA,CAAY,GAAG,YAAY,CAAA;AAI3B,IAAA,IAAI,OAAO,mBAAmB,WAAA,EAAa;AACzC,MAAA,OAAO,MAAM;AACX,QAAA,qBAAA,EAAsB;AACtB,QAAA,oBAAA,CAAqB,OAAA,GAAU,MAAA;AAC/B,QAAA,QAAA,CAAS,eAAA,CAAgB,KAAA,CAAM,cAAA,CAAe,qBAAqB,CAAA;AAAA,MACrE,CAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,IAAI,cAAA,CAAe,MAAM;AACxC,MAAA,oBAAA,EAAqB;AAAA,IACvB,CAAC,CAAA;AACD,IAAA,QAAA,CAAS,QAAQ,EAAE,CAAA;AAEnB,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,UAAA,EAAW;AACpB,MAAA,qBAAA,EAAsB;AACtB,MAAA,oBAAA,CAAqB,OAAA,GAAU,MAAA;AAC/B,MAAA,QAAA,CAAS,eAAA,CAAgB,KAAA,CAAM,cAAA,CAAe,qBAAqB,CAAA;AAAA,IACrE,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,+BACJ,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAW,OAAA,CAAQ,WAAA,EAAa,eAAY,MAAA,EAC9C,QAAA,EAAA,IAAA,oBAAQ,GAAA,CAAC,YAAA,EAAA,EAAa,CAAA,EACzB,CAAA;AAAA,oBACA,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,aAAA,EAAe,mBAAS,aAAA,EAAc;AAAA,GAAA,EACtD,CAAA;AAGF,EAAA,4BACG,QAAA,EAAA,EAAO,GAAA,EAAK,SAAA,EAAW,SAAA,EAAW,QAAQ,IAAA,EACzC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,OAAA,EAAS,eAAA,EAAe,OAAA,EAC9C,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,cAAA,EAAgB,GAAA,EAAK,iBAAA,EAC3C,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,cAAA,EAAgB,GAAA,EAAK,iBAAA,EAC3C,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,EAAA,EAAG,IAAA,EAAK,OAAA,EAAQ,aAAA,EACnB,QAAA,EAAA,SAAA,mBACC,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAW,OAAA,CAAQ,WAAA,EAAa,IAAA,EAAM,SAAA,EACzC,QAAA,EAAA,YAAA,EACH,CAAA,mBAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,WAAA,EAAc,QAAA,EAAA,YAAA,EAAa,GAEvD,CAAA,EACF,CAAA;AAAA,0BACC,KAAA,EAAA,EAAI,SAAA,EAAW,QAAQ,eAAA,EAAiB,GAAA,EAAK,oBAC3C,QAAA,EAAA,cAAA,EACH;AAAA,KAAA,EACF,CAAA,EACF,CAAA;AAAA,IACC,wBACC,GAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAG,SAAA,EAAU,WAAW,OAAA,CAAQ,IAAA,EACnC,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,mBAAmB,oBAAA,EACvB,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EACE,QAAA,EAAA,IAAA,EAAM,IAAI,CAAA,GAAA,qBACT,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QAEC,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,eAAe,GAAA,CAAI,aAAA;AAAA,QAElB,QAAA,EAAA,GAAA,CAAI;AAAA,OAAA;AAAA,MALA,GAAA,CAAI;AAAA,KAOZ,CAAA,EACH,CAAA,EACF,CAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ;;;;"}
@@ -0,0 +1,164 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useRef, Children } from 'react';
3
+ import { useInteractOutside } from '@react-aria/interactions';
4
+ import { OverlayTriggerStateContext, Autocomplete, SearchField, Input, Button, Popover, ListBox, ListBoxItem } from 'react-aria-components';
5
+ import { useOverlayTriggerState } from '@react-stately/overlays';
6
+ import { RiSearch2Line, RiCloseCircleLine } from '@remixicon/react';
7
+ import { useDefinition } from '../../hooks/useDefinition/useDefinition.esm.js';
8
+ import { SearchAutocompleteDefinition, SearchAutocompleteItemDefinition } from './definition.esm.js';
9
+ import { Box } from '../Box/Box.esm.js';
10
+ import '../Box/Box.module.css.esm.js';
11
+ import { BgReset } from '../../hooks/useBg.esm.js';
12
+ import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden.esm.js';
13
+ import '../VisuallyHidden/VisuallyHidden.module.css.esm.js';
14
+
15
+ const SearchAutocompleteEmptyState = () => {
16
+ const { ownProps } = useDefinition(SearchAutocompleteDefinition, {});
17
+ return /* @__PURE__ */ jsx("div", { className: ownProps.classes.emptyState, children: "No results found." });
18
+ };
19
+ function SearchAutocomplete(props) {
20
+ const { ownProps, dataAttributes } = useDefinition(
21
+ SearchAutocompleteDefinition,
22
+ props
23
+ );
24
+ const {
25
+ classes,
26
+ "aria-label": ariaLabel,
27
+ "aria-labelledby": ariaLabelledBy,
28
+ inputValue,
29
+ onInputChange,
30
+ placeholder,
31
+ popoverWidth,
32
+ popoverPlacement = "bottom start",
33
+ children,
34
+ isLoading,
35
+ defaultOpen,
36
+ style
37
+ } = ownProps;
38
+ const triggerRef = useRef(null);
39
+ const popoverRef = useRef(null);
40
+ const hasValue = !!inputValue;
41
+ const hasChildren = Children.count(children) > 0;
42
+ let liveMessage = "";
43
+ if (isLoading) {
44
+ liveMessage = "Searching";
45
+ } else if (hasValue && !hasChildren) {
46
+ liveMessage = "No results found";
47
+ }
48
+ const overlayState = useOverlayTriggerState({ defaultOpen });
49
+ useInteractOutside({
50
+ ref: popoverRef,
51
+ onInteractOutside: (e) => {
52
+ const target = e.target;
53
+ if (triggerRef.current?.contains(target)) {
54
+ return;
55
+ }
56
+ overlayState.close();
57
+ },
58
+ isDisabled: !overlayState.isOpen
59
+ });
60
+ return /* @__PURE__ */ jsx(OverlayTriggerStateContext.Provider, { value: overlayState, children: /* @__PURE__ */ jsxs(
61
+ Autocomplete,
62
+ {
63
+ inputValue,
64
+ onInputChange: (value) => {
65
+ onInputChange?.(value);
66
+ if (value) {
67
+ overlayState.open();
68
+ } else {
69
+ overlayState.close();
70
+ }
71
+ },
72
+ children: [
73
+ /* @__PURE__ */ jsx(
74
+ SearchField,
75
+ {
76
+ className: classes.searchField,
77
+ "aria-label": ariaLabel ?? (ariaLabelledBy ? void 0 : placeholder),
78
+ "aria-labelledby": ariaLabelledBy,
79
+ "data-size": dataAttributes["data-size"],
80
+ onKeyDown: (e) => {
81
+ if (e.key === "Enter" && !overlayState.isOpen && hasValue) {
82
+ e.preventDefault();
83
+ overlayState.open();
84
+ }
85
+ },
86
+ children: /* @__PURE__ */ jsxs(
87
+ "div",
88
+ {
89
+ ref: triggerRef,
90
+ className: classes.root,
91
+ ...dataAttributes,
92
+ style,
93
+ children: [
94
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", children: /* @__PURE__ */ jsx(RiSearch2Line, {}) }),
95
+ /* @__PURE__ */ jsx(
96
+ Input,
97
+ {
98
+ className: classes.searchFieldInput,
99
+ placeholder
100
+ }
101
+ ),
102
+ /* @__PURE__ */ jsx(
103
+ Button,
104
+ {
105
+ className: classes.searchFieldClear,
106
+ style: { visibility: hasValue ? "visible" : "hidden" },
107
+ children: /* @__PURE__ */ jsx(RiCloseCircleLine, {})
108
+ }
109
+ )
110
+ ]
111
+ }
112
+ )
113
+ }
114
+ ),
115
+ /* @__PURE__ */ jsx(
116
+ Popover,
117
+ {
118
+ ref: popoverRef,
119
+ className: classes.popover,
120
+ triggerRef,
121
+ isNonModal: true,
122
+ placement: popoverPlacement,
123
+ ...popoverWidth ? { style: { width: popoverWidth } } : {},
124
+ children: /* @__PURE__ */ jsx(BgReset, { children: /* @__PURE__ */ jsx(Box, { bg: "neutral", className: classes.inner, children: /* @__PURE__ */ jsx(
125
+ ListBox,
126
+ {
127
+ className: classes.listBox,
128
+ autoFocus: "first",
129
+ shouldFocusOnHover: true,
130
+ "aria-busy": isLoading || void 0,
131
+ "data-stale": isLoading || void 0,
132
+ renderEmptyState: () => isLoading ? /* @__PURE__ */ jsx("div", { className: classes.loadingState, children: "Searching..." }) : /* @__PURE__ */ jsx(SearchAutocompleteEmptyState, {}),
133
+ onAction: () => {
134
+ overlayState.close();
135
+ },
136
+ children
137
+ }
138
+ ) }) })
139
+ }
140
+ ),
141
+ /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "polite", "aria-atomic": "true", children: liveMessage })
142
+ ]
143
+ }
144
+ ) });
145
+ }
146
+ function SearchAutocompleteItem(props) {
147
+ const { ownProps, restProps } = useDefinition(
148
+ SearchAutocompleteItemDefinition,
149
+ props
150
+ );
151
+ const { classes, children } = ownProps;
152
+ return /* @__PURE__ */ jsx(
153
+ ListBoxItem,
154
+ {
155
+ textValue: typeof children === "string" ? children : void 0,
156
+ className: classes.root,
157
+ ...restProps,
158
+ children: /* @__PURE__ */ jsx("div", { className: classes.itemContent, children })
159
+ }
160
+ );
161
+ }
162
+
163
+ export { SearchAutocomplete, SearchAutocompleteItem };
164
+ //# sourceMappingURL=SearchAutocomplete.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchAutocomplete.esm.js","sources":["../../../src/components/SearchAutocomplete/SearchAutocomplete.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 { Children, useRef } from 'react';\nimport { useInteractOutside } from '@react-aria/interactions';\nimport {\n Autocomplete,\n SearchField as RASearchField,\n Input,\n Button as RAButton,\n Popover as RAPopover,\n ListBox,\n ListBoxItem,\n OverlayTriggerStateContext,\n} from 'react-aria-components';\nimport { useOverlayTriggerState } from '@react-stately/overlays';\nimport { RiSearch2Line, RiCloseCircleLine } from '@remixicon/react';\nimport { useDefinition } from '../../hooks/useDefinition';\nimport {\n SearchAutocompleteDefinition,\n SearchAutocompleteItemDefinition,\n} from './definition';\nimport { Box } from '../Box';\nimport { BgReset } from '../../hooks/useBg';\nimport { VisuallyHidden } from '../VisuallyHidden';\n\nimport type {\n SearchAutocompleteProps,\n SearchAutocompleteItemProps,\n} from './types';\n\nconst SearchAutocompleteEmptyState = () => {\n const { ownProps } = useDefinition(SearchAutocompleteDefinition, {});\n return <div className={ownProps.classes.emptyState}>No results found.</div>;\n};\n\n/** @public */\nexport function SearchAutocomplete(props: SearchAutocompleteProps) {\n const { ownProps, dataAttributes } = useDefinition(\n SearchAutocompleteDefinition,\n props,\n );\n const {\n classes,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n inputValue,\n onInputChange,\n placeholder,\n popoverWidth,\n popoverPlacement = 'bottom start',\n children,\n isLoading,\n defaultOpen,\n style,\n } = ownProps;\n\n const triggerRef = useRef<HTMLDivElement | null>(null);\n const popoverRef = useRef<HTMLElement | null>(null);\n const hasValue = !!inputValue;\n const hasChildren = Children.count(children) > 0;\n\n let liveMessage = '';\n if (isLoading) {\n liveMessage = 'Searching';\n } else if (hasValue && !hasChildren) {\n liveMessage = 'No results found';\n }\n const overlayState = useOverlayTriggerState({ defaultOpen });\n\n // Close on interact outside — same pattern as ComboBox.\n // isNonModal disables useOverlay's built-in useInteractOutside,\n // so we add our own that filters out clicks on the trigger.\n useInteractOutside({\n ref: popoverRef,\n onInteractOutside: e => {\n const target = e.target as Element;\n if (triggerRef.current?.contains(target)) {\n return;\n }\n overlayState.close();\n },\n isDisabled: !overlayState.isOpen,\n });\n\n return (\n <OverlayTriggerStateContext.Provider value={overlayState}>\n <Autocomplete\n inputValue={inputValue}\n onInputChange={value => {\n onInputChange?.(value);\n if (value) {\n overlayState.open();\n } else {\n overlayState.close();\n }\n }}\n >\n <RASearchField\n className={classes.searchField}\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : placeholder)}\n aria-labelledby={ariaLabelledBy}\n data-size={dataAttributes['data-size']}\n onKeyDown={e => {\n if (e.key === 'Enter' && !overlayState.isOpen && hasValue) {\n e.preventDefault();\n overlayState.open();\n }\n }}\n >\n <div\n ref={triggerRef}\n className={classes.root}\n {...dataAttributes}\n style={style}\n >\n <div aria-hidden=\"true\">\n <RiSearch2Line />\n </div>\n <Input\n className={classes.searchFieldInput}\n placeholder={placeholder}\n />\n <RAButton\n className={classes.searchFieldClear}\n style={{ visibility: hasValue ? 'visible' : 'hidden' }}\n >\n <RiCloseCircleLine />\n </RAButton>\n </div>\n </RASearchField>\n {/* isNonModal keeps the page interactive while the popover is open,\n required for virtual focus (aria-activedescendant) to work correctly */}\n <RAPopover\n ref={popoverRef}\n className={classes.popover}\n triggerRef={triggerRef}\n isNonModal\n placement={popoverPlacement}\n {...(popoverWidth ? { style: { width: popoverWidth } } : {})}\n >\n <BgReset>\n <Box bg=\"neutral\" className={classes.inner}>\n <ListBox\n className={classes.listBox}\n autoFocus=\"first\"\n shouldFocusOnHover\n aria-busy={isLoading || undefined}\n data-stale={isLoading || undefined}\n renderEmptyState={() =>\n isLoading ? (\n <div className={classes.loadingState}>Searching...</div>\n ) : (\n <SearchAutocompleteEmptyState />\n )\n }\n onAction={() => {\n overlayState.close();\n }}\n >\n {children}\n </ListBox>\n </Box>\n </BgReset>\n </RAPopover>\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {liveMessage}\n </VisuallyHidden>\n </Autocomplete>\n </OverlayTriggerStateContext.Provider>\n );\n}\n\n/** @public */\nexport function SearchAutocompleteItem(props: SearchAutocompleteItemProps) {\n const { ownProps, restProps } = useDefinition(\n SearchAutocompleteItemDefinition,\n props,\n );\n const { classes, children } = ownProps;\n\n return (\n <ListBoxItem\n textValue={typeof children === 'string' ? children : undefined}\n className={classes.root}\n {...restProps}\n >\n <div className={classes.itemContent}>{children}</div>\n </ListBoxItem>\n );\n}\n"],"names":["RASearchField","RAButton","RAPopover"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import styleInject from '../../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
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 .SearchAutocomplete_bui-SearchAutocomplete__579de55517 {\n display: flex;\n align-items: center;\n border-radius: var(--bui-radius-2);\n background-color: var(--bui-bg-neutral-1);\n transition: box-shadow 0.2s ease-in-out;\n font-family: var(--bui-font-regular);\n\n &:has([data-focused]) {\n box-shadow: inset 0 0 0 1px var(--bui-ring);\n }\n\n &[data-size='small'] {\n --search-autocomplete-item-height: 2rem;\n height: 2rem;\n }\n\n &[data-size='medium'] {\n --search-autocomplete-item-height: 2.5rem;\n height: 2.5rem;\n }\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\n .SearchAutocomplete_bui-SearchAutocompleteSearchField__579de55517 {\n display: flex;\n align-items: center;\n flex: 1;\n\n & > div {\n display: flex;\n align-items: center;\n flex: 1;\n }\n\n & svg {\n flex: 0 0 auto;\n color: var(--bui-fg-primary);\n margin-inline-start: var(--bui-space-2);\n\n .SearchAutocomplete_bui-SearchAutocomplete__579de55517[data-size='small'] & {\n width: 1rem;\n height: 1rem;\n }\n\n .SearchAutocomplete_bui-SearchAutocomplete__579de55517[data-size='medium'] & {\n width: 1.25rem;\n height: 1.25rem;\n }\n }\n }\n\n .SearchAutocomplete_bui-SearchAutocompleteInput__579de55517 {\n flex: 1;\n display: flex;\n align-items: center;\n padding: 0;\n padding-inline: var(--bui-space-2);\n border: none;\n background-color: transparent;\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 width: 100%;\n height: 100%;\n outline: none;\n\n &::-webkit-search-cancel-button,\n &::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n\n &::placeholder {\n color: var(--bui-fg-secondary);\n }\n }\n\n .SearchAutocomplete_bui-SearchAutocompleteClear__579de55517 {\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(--search-autocomplete-item-height);\n height: var(--search-autocomplete-item-height);\n\n &:hover {\n color: var(--bui-fg-primary);\n }\n\n & svg {\n width: 1rem;\n height: 1rem;\n }\n }\n\n .SearchAutocomplete_bui-SearchAutocompletePopover__579de55517 {\n --menu-border-radius: var(--bui-radius-2);\n display: flex;\n flex-direction: column;\n box-shadow: var(--bui-shadow);\n border: 1px solid var(--bui-border-1);\n border-radius: var(--menu-border-radius);\n background: var(--bui-bg-app);\n color: var(--bui-fg-primary);\n outline: none;\n transition: transform 200ms, opacity 200ms;\n min-height: 0;\n overflow: hidden;\n\n &[data-entering],\n &[data-exiting] {\n transform: var(--origin);\n opacity: 0;\n }\n\n &[data-placement='top'] {\n --origin: translateY(8px);\n }\n\n &[data-placement='bottom'] {\n --origin: translateY(-8px);\n }\n }\n\n .SearchAutocomplete_bui-SearchAutocompleteInner__579de55517 {\n border-radius: var(--menu-border-radius);\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow: hidden;\n }\n\n .SearchAutocomplete_bui-SearchAutocompleteListBox__579de55517 {\n max-height: inherit;\n box-sizing: border-box;\n overflow: auto;\n min-width: 150px;\n outline: none;\n padding-block: var(--bui-space-1);\n\n &[data-stale] {\n opacity: 0.6;\n }\n }\n\n .SearchAutocomplete_bui-SearchAutocompleteItem__579de55517 {\n padding-inline: var(--bui-space-1);\n display: block;\n\n &:focus-visible {\n outline: none;\n }\n\n &[data-focus-visible] {\n outline: 2px solid var(--bui-ring);\n outline-offset: -2px;\n }\n\n &[data-focused] .SearchAutocomplete_bui-SearchAutocompleteItemContent__579de55517,\n &[data-hovered] .SearchAutocomplete_bui-SearchAutocompleteItemContent__579de55517 {\n background: var(--bui-bg-neutral-2);\n color: var(--bui-fg-primary);\n }\n }\n\n .SearchAutocomplete_bui-SearchAutocompleteItemContent__579de55517 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-1);\n min-height: 2rem;\n padding-inline: var(--bui-space-2);\n padding-block: var(--bui-space-2);\n border-radius: var(--bui-radius-2);\n outline: none;\n cursor: default;\n color: var(--bui-fg-primary);\n font-size: var(--bui-font-size-3);\n }\n\n .SearchAutocomplete_bui-SearchAutocompleteLoadingState__579de55517,\n .SearchAutocomplete_bui-SearchAutocompleteEmptyState__579de55517 {\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-SearchAutocomplete":"SearchAutocomplete_bui-SearchAutocomplete__579de55517","bui-SearchAutocompleteSearchField":"SearchAutocomplete_bui-SearchAutocompleteSearchField__579de55517","bui-SearchAutocompleteInput":"SearchAutocomplete_bui-SearchAutocompleteInput__579de55517","bui-SearchAutocompleteClear":"SearchAutocomplete_bui-SearchAutocompleteClear__579de55517","bui-SearchAutocompletePopover":"SearchAutocomplete_bui-SearchAutocompletePopover__579de55517","bui-SearchAutocompleteInner":"SearchAutocomplete_bui-SearchAutocompleteInner__579de55517","bui-SearchAutocompleteListBox":"SearchAutocomplete_bui-SearchAutocompleteListBox__579de55517","bui-SearchAutocompleteItem":"SearchAutocomplete_bui-SearchAutocompleteItem__579de55517","bui-SearchAutocompleteItemContent":"SearchAutocomplete_bui-SearchAutocompleteItemContent__579de55517","bui-SearchAutocompleteLoadingState":"SearchAutocomplete_bui-SearchAutocompleteLoadingState__579de55517","bui-SearchAutocompleteEmptyState":"SearchAutocomplete_bui-SearchAutocompleteEmptyState__579de55517"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=SearchAutocomplete.module.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchAutocomplete.module.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,53 @@
1
+ import 'react/jsx-runtime';
2
+ import 'clsx';
3
+ import '../../hooks/useBreakpoint.esm.js';
4
+ import '../../hooks/useBg.esm.js';
5
+ import '../../hooks/useDefinition/helpers.esm.js';
6
+ import '../../analytics/useAnalytics.esm.js';
7
+ import { defineComponent } from '../../hooks/useDefinition/defineComponent.esm.js';
8
+ import styles from './SearchAutocomplete.module.css.esm.js';
9
+
10
+ const SearchAutocompleteDefinition = defineComponent()({
11
+ styles,
12
+ bg: "consumer",
13
+ classNames: {
14
+ root: "bui-SearchAutocomplete",
15
+ searchField: "bui-SearchAutocompleteSearchField",
16
+ searchFieldInput: "bui-SearchAutocompleteInput",
17
+ searchFieldClear: "bui-SearchAutocompleteClear",
18
+ popover: "bui-SearchAutocompletePopover",
19
+ inner: "bui-SearchAutocompleteInner",
20
+ listBox: "bui-SearchAutocompleteListBox",
21
+ loadingState: "bui-SearchAutocompleteLoadingState",
22
+ emptyState: "bui-SearchAutocompleteEmptyState"
23
+ },
24
+ propDefs: {
25
+ "aria-label": {},
26
+ "aria-labelledby": {},
27
+ size: { dataAttribute: true, default: "small" },
28
+ placeholder: { default: "Search" },
29
+ inputValue: {},
30
+ onInputChange: {},
31
+ popoverWidth: {},
32
+ popoverPlacement: {},
33
+ children: {},
34
+ isLoading: {},
35
+ defaultOpen: {},
36
+ className: {},
37
+ style: {}
38
+ }
39
+ });
40
+ const SearchAutocompleteItemDefinition = defineComponent()({
41
+ styles,
42
+ classNames: {
43
+ root: "bui-SearchAutocompleteItem",
44
+ itemContent: "bui-SearchAutocompleteItemContent"
45
+ },
46
+ propDefs: {
47
+ children: {},
48
+ className: {}
49
+ }
50
+ });
51
+
52
+ export { SearchAutocompleteDefinition, SearchAutocompleteItemDefinition };
53
+ //# sourceMappingURL=definition.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definition.esm.js","sources":["../../../src/components/SearchAutocomplete/definition.ts"],"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 { defineComponent } from '../../hooks/useDefinition';\nimport type {\n SearchAutocompleteOwnProps,\n SearchAutocompleteItemOwnProps,\n} from './types';\nimport styles from './SearchAutocomplete.module.css';\n\n/**\n * Component definition for SearchAutocomplete.\n * @public\n */\nexport const SearchAutocompleteDefinition =\n defineComponent<SearchAutocompleteOwnProps>()({\n styles,\n bg: 'consumer',\n classNames: {\n root: 'bui-SearchAutocomplete',\n searchField: 'bui-SearchAutocompleteSearchField',\n searchFieldInput: 'bui-SearchAutocompleteInput',\n searchFieldClear: 'bui-SearchAutocompleteClear',\n popover: 'bui-SearchAutocompletePopover',\n inner: 'bui-SearchAutocompleteInner',\n listBox: 'bui-SearchAutocompleteListBox',\n loadingState: 'bui-SearchAutocompleteLoadingState',\n emptyState: 'bui-SearchAutocompleteEmptyState',\n },\n propDefs: {\n 'aria-label': {},\n 'aria-labelledby': {},\n size: { dataAttribute: true, default: 'small' },\n placeholder: { default: 'Search' },\n inputValue: {},\n onInputChange: {},\n popoverWidth: {},\n popoverPlacement: {},\n children: {},\n isLoading: {},\n defaultOpen: {},\n className: {},\n style: {},\n },\n });\n\n/** @internal */\nexport const SearchAutocompleteItemDefinition =\n defineComponent<SearchAutocompleteItemOwnProps>()({\n styles,\n classNames: {\n root: 'bui-SearchAutocompleteItem',\n itemContent: 'bui-SearchAutocompleteItemContent',\n },\n propDefs: {\n children: {},\n className: {},\n },\n });\n"],"names":[],"mappings":";;;;;;;;;AA2BO,MAAM,4BAAA,GACX,iBAA4C,CAAE;AAAA,EAC5C,MAAA;AAAA,EACA,EAAA,EAAI,UAAA;AAAA,EACJ,UAAA,EAAY;AAAA,IACV,IAAA,EAAM,wBAAA;AAAA,IACN,WAAA,EAAa,mCAAA;AAAA,IACb,gBAAA,EAAkB,6BAAA;AAAA,IAClB,gBAAA,EAAkB,6BAAA;AAAA,IAClB,OAAA,EAAS,+BAAA;AAAA,IACT,KAAA,EAAO,6BAAA;AAAA,IACP,OAAA,EAAS,+BAAA;AAAA,IACT,YAAA,EAAc,oCAAA;AAAA,IACd,UAAA,EAAY;AAAA,GACd;AAAA,EACA,QAAA,EAAU;AAAA,IACR,cAAc,EAAC;AAAA,IACf,mBAAmB,EAAC;AAAA,IACpB,IAAA,EAAM,EAAE,aAAA,EAAe,IAAA,EAAM,SAAS,OAAA,EAAQ;AAAA,IAC9C,WAAA,EAAa,EAAE,OAAA,EAAS,QAAA,EAAS;AAAA,IACjC,YAAY,EAAC;AAAA,IACb,eAAe,EAAC;AAAA,IAChB,cAAc,EAAC;AAAA,IACf,kBAAkB,EAAC;AAAA,IACnB,UAAU,EAAC;AAAA,IACX,WAAW,EAAC;AAAA,IACZ,aAAa,EAAC;AAAA,IACd,WAAW,EAAC;AAAA,IACZ,OAAO;AAAC;AAEZ,CAAC;AAGI,MAAM,gCAAA,GACX,iBAAgD,CAAE;AAAA,EAChD,MAAA;AAAA,EACA,UAAA,EAAY;AAAA,IACV,IAAA,EAAM,4BAAA;AAAA,IACN,WAAA,EAAa;AAAA,GACf;AAAA,EACA,QAAA,EAAU;AAAA,IACR,UAAU,EAAC;AAAA,IACX,WAAW;AAAC;AAEhB,CAAC;;;;"}
@@ -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__277142c2b3,\n .Select_bui-SelectPopover__277142c2b3 {\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-SelectPopover__277142c2b3 {\n min-width: var(--trigger-width);\n }\n\n .Select_bui-SelectTrigger__277142c2b3 {\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__277142c2b3[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__277142c2b3[data-size='small'] & {\n padding-inline: var(--bui-space-3) 0;\n }\n\n .Select_bui-Select__277142c2b3[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__277142c2b3[data-size='small'] & {\n width: 1rem;\n height: 1rem;\n }\n\n .Select_bui-Select__277142c2b3[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__277142c2b3[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__277142c2b3 {\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__277142c2b3 {\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__277142c2b3 {\n display: none;\n }\n\n &[disabled] {\n color: var(--bui-fg-disabled);\n }\n }\n\n .Select_bui-SelectList__277142c2b3 {\n overflow: auto;\n min-height: 0;\n padding-block: var(--bui-space-1);\n padding-inline: var(--bui-space-1);\n\n &: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__277142c2b3 {\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__277142c2b3 {\n opacity: 1;\n }\n }\n\n .Select_bui-SelectItemIndicator__277142c2b3 {\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__277142c2b3 {\n flex: 1;\n grid-area: text;\n }\n\n .Select_bui-SelectSearchWrapper__277142c2b3 {\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__277142c2b3 {\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__277142c2b3 {\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-SelectNoResults__277142c2b3 {\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__277142c2b3","bui-SelectPopover":"Select_bui-SelectPopover__277142c2b3","bui-SelectTrigger":"Select_bui-SelectTrigger__277142c2b3","bui-SelectTriggerChevron":"Select_bui-SelectTriggerChevron__277142c2b3","bui-SelectValue":"Select_bui-SelectValue__277142c2b3","bui-SelectItemIndicator":"Select_bui-SelectItemIndicator__277142c2b3","bui-SelectList":"Select_bui-SelectList__277142c2b3","bui-SelectItem":"Select_bui-SelectItem__277142c2b3","bui-SelectItemLabel":"Select_bui-SelectItemLabel__277142c2b3","bui-SelectSearchWrapper":"Select_bui-SelectSearchWrapper__277142c2b3","bui-SelectSearch":"Select_bui-SelectSearch__277142c2b3","bui-SelectSearchClear":"Select_bui-SelectSearchClear__277142c2b3","bui-SelectNoResults":"Select_bui-SelectNoResults__277142c2b3"};
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__b6322df3ac,\n .Select_bui-SelectPopover__b6322df3ac {\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-SelectPopover__b6322df3ac {\n min-width: var(--trigger-width);\n }\n\n .Select_bui-SelectTrigger__b6322df3ac {\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__b6322df3ac[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__b6322df3ac[data-size='small'] & {\n padding-inline: var(--bui-space-3) 0;\n }\n\n .Select_bui-Select__b6322df3ac[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__b6322df3ac[data-size='small'] & {\n width: 1rem;\n height: 1rem;\n }\n\n .Select_bui-Select__b6322df3ac[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__b6322df3ac[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__b6322df3ac {\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__b6322df3ac {\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__b6322df3ac {\n display: none;\n }\n\n &[disabled] {\n color: var(--bui-fg-disabled);\n }\n }\n\n .Select_bui-SelectList__b6322df3ac {\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__b6322df3ac {\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__b6322df3ac {\n opacity: 1;\n }\n }\n\n .Select_bui-SelectItemIndicator__b6322df3ac {\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__b6322df3ac {\n flex: 1;\n grid-area: text;\n }\n\n .Select_bui-SelectSearchWrapper__b6322df3ac {\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__b6322df3ac {\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__b6322df3ac {\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-SelectNoResults__b6322df3ac {\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__b6322df3ac","bui-SelectPopover":"Select_bui-SelectPopover__b6322df3ac","bui-SelectTrigger":"Select_bui-SelectTrigger__b6322df3ac","bui-SelectTriggerChevron":"Select_bui-SelectTriggerChevron__b6322df3ac","bui-SelectValue":"Select_bui-SelectValue__b6322df3ac","bui-SelectItemIndicator":"Select_bui-SelectItemIndicator__b6322df3ac","bui-SelectList":"Select_bui-SelectList__b6322df3ac","bui-SelectItem":"Select_bui-SelectItem__b6322df3ac","bui-SelectItemLabel":"Select_bui-SelectItemLabel__b6322df3ac","bui-SelectSearchWrapper":"Select_bui-SelectSearchWrapper__b6322df3ac","bui-SelectSearch":"Select_bui-SelectSearch__b6322df3ac","bui-SelectSearchClear":"Select_bui-SelectSearchClear__b6322df3ac","bui-SelectNoResults":"Select_bui-SelectNoResults__b6322df3ac"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { styles as default };
@@ -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 .Table_bui-Table__b0fbf5f399 {\n width: 100%;\n caption-side: bottom;\n border-collapse: collapse;\n table-layout: fixed;\n transition: opacity 0.2s ease-in-out;\n\n &[data-stale='true'] {\n opacity: 0.6;\n }\n }\n\n .Table_bui-TableHeader__b0fbf5f399 {\n border-bottom: 1px solid var(--bui-border-2);\n transition: color 0.2s ease-in-out;\n }\n\n .Table_bui-TableHead__b0fbf5f399 {\n text-align: left;\n padding: var(--bui-space-3);\n font-size: var(--bui-font-size-3);\n color: var(--bui-fg-primary);\n }\n\n .Table_bui-TableHeadSelection__b0fbf5f399 {\n width: 40px;\n }\n\n .Table_bui-TableHeadContent__b0fbf5f399 {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--bui-space-1);\n }\n\n .Table_bui-TableHeadLabel__b0fbf5f399 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n }\n\n .Table_bui-TableHeadSortButton__b0fbf5f399 {\n cursor: pointer;\n user-select: none;\n display: inline-flex;\n align-items: center;\n gap: var(--bui-space-1);\n opacity: 0;\n transition: opacity 0.1s ease-in-out;\n color: var(--bui-fg-secondary);\n\n .Table_bui-TableHead__b0fbf5f399:hover &,\n [data-sort-direction='ascending'] &,\n [data-sort-direction='descending'] & {\n opacity: 1;\n }\n\n & svg {\n transition: transform 0.1s ease-in-out;\n }\n [data-sort-direction='descending'] & svg {\n transform: rotate(180deg);\n }\n }\n\n .Table_bui-TableBody__b0fbf5f399 {\n color: var(--bui-fg-primary);\n }\n\n .Table_bui-TableRow__b0fbf5f399 {\n border-bottom: 1px solid var(--bui-border-2);\n transition: color 0.2s ease-in-out;\n cursor: default;\n\n &:hover {\n background-color: var(--bui-bg-tint-hover);\n }\n\n &[data-selected] {\n background-color: var(--bui-bg-tint-pressed);\n }\n\n &[data-pressed] {\n background-color: var(--bui-bg-tint-pressed);\n }\n\n &[data-href],\n &[data-selection-mode],\n &[data-react-aria-pressable='true'] {\n cursor: pointer;\n }\n\n &[data-disabled] {\n background-color: var(--bui-bg-tint-disabled);\n cursor: not-allowed;\n }\n }\n\n .Table_bui-TableCell__b0fbf5f399 {\n padding: var(--bui-space-3);\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n font-weight: var(--bui-font-weight-regular);\n min-width: 0;\n overflow: hidden;\n }\n\n .Table_bui-TableCellSelection__b0fbf5f399 {\n width: 40px;\n }\n\n .Table_bui-TableCellContentWrapper__b0fbf5f399 {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--bui-space-2);\n min-width: 0;\n width: 100%;\n max-width: 100%;\n }\n\n .Table_bui-TableCellIcon__b0fbf5f399,\n .Table_bui-TableCellIcon__b0fbf5f399 svg {\n display: inline-flex;\n align-items: center;\n color: var(--bui-fg-primary);\n }\n\n .Table_bui-TableCellContent__b0fbf5f399 {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-0_5);\n min-width: 0;\n flex: 1;\n overflow: hidden;\n max-width: 100%;\n }\n\n .Table_bui-TableCellContent__b0fbf5f399 > * {\n min-width: 0;\n max-width: 100%;\n }\n\n .Table_bui-TableCellProfile__b0fbf5f399 {\n display: flex;\n flex-direction: row;\n gap: var(--bui-space-2);\n align-items: center;\n }\n}\n";
4
- var styles = {"bui-Table":"Table_bui-Table__b0fbf5f399","bui-TableHeader":"Table_bui-TableHeader__b0fbf5f399","bui-TableHead":"Table_bui-TableHead__b0fbf5f399","bui-TableHeadSelection":"Table_bui-TableHeadSelection__b0fbf5f399","bui-TableHeadContent":"Table_bui-TableHeadContent__b0fbf5f399","bui-TableHeadLabel":"Table_bui-TableHeadLabel__b0fbf5f399","bui-TableHeadSortButton":"Table_bui-TableHeadSortButton__b0fbf5f399","bui-TableBody":"Table_bui-TableBody__b0fbf5f399","bui-TableRow":"Table_bui-TableRow__b0fbf5f399","bui-TableCell":"Table_bui-TableCell__b0fbf5f399","bui-TableCellSelection":"Table_bui-TableCellSelection__b0fbf5f399","bui-TableCellContentWrapper":"Table_bui-TableCellContentWrapper__b0fbf5f399","bui-TableCellIcon":"Table_bui-TableCellIcon__b0fbf5f399","bui-TableCellContent":"Table_bui-TableCellContent__b0fbf5f399","bui-TableCellProfile":"Table_bui-TableCellProfile__b0fbf5f399"};
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 .Table_bui-TableWrapper__b7a883a8dd {\n display: flex;\n flex-direction: column;\n }\n\n .Table_bui-TableResizableContainer__b7a883a8dd {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }\n\n .Table_bui-Table__b7a883a8dd {\n width: 100%;\n caption-side: bottom;\n border-collapse: collapse;\n table-layout: fixed;\n transition: opacity 0.2s ease-in-out;\n overflow: auto;\n flex: 1;\n min-height: 0;\n\n &[data-stale='true'],\n &[data-loading='true'] {\n opacity: 0.6;\n }\n }\n\n .Table_bui-TableHeader__b7a883a8dd {\n border-bottom: 1px solid var(--bui-border-2);\n transition: color 0.2s ease-in-out;\n }\n\n .Table_bui-TableHead__b7a883a8dd {\n text-align: left;\n padding: var(--bui-space-3);\n font-size: var(--bui-font-size-3);\n color: var(--bui-fg-primary);\n }\n\n .Table_bui-TableHeadSelection__b7a883a8dd {\n width: 40px;\n }\n\n .Table_bui-TableHeadContent__b7a883a8dd {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--bui-space-1);\n }\n\n .Table_bui-TableHeadLabel__b7a883a8dd {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n }\n\n .Table_bui-TableHeadSortButton__b7a883a8dd {\n cursor: pointer;\n user-select: none;\n display: inline-flex;\n align-items: center;\n gap: var(--bui-space-1);\n opacity: 0;\n transition: opacity 0.1s ease-in-out;\n color: var(--bui-fg-secondary);\n\n .Table_bui-TableHead__b7a883a8dd:hover &,\n [data-sort-direction='ascending'] &,\n [data-sort-direction='descending'] & {\n opacity: 1;\n }\n\n & svg {\n transition: transform 0.1s ease-in-out;\n }\n [data-sort-direction='descending'] & svg {\n transform: rotate(180deg);\n }\n }\n\n .Table_bui-TableBody__b7a883a8dd {\n color: var(--bui-fg-primary);\n }\n\n .Table_bui-TableRow__b7a883a8dd {\n border-bottom: 1px solid var(--bui-border-2);\n transition: color 0.2s ease-in-out;\n cursor: default;\n\n &:hover {\n background-color: var(--bui-bg-neutral-1-hover);\n }\n\n &[data-selected] {\n background-color: var(--bui-bg-neutral-1-pressed);\n }\n\n &[data-pressed] {\n background-color: var(--bui-bg-neutral-1-pressed);\n }\n\n &[data-on-bg='neutral-1'] {\n &:hover {\n background-color: var(--bui-bg-neutral-2-hover);\n }\n\n &[data-selected] {\n background-color: var(--bui-bg-neutral-2-pressed);\n }\n\n &[data-pressed] {\n background-color: var(--bui-bg-neutral-2-pressed);\n }\n\n &[data-disabled] {\n background-color: var(--bui-bg-neutral-2-disabled);\n }\n }\n\n &[data-on-bg='neutral-2'] {\n &:hover {\n background-color: var(--bui-bg-neutral-3-hover);\n }\n\n &[data-selected] {\n background-color: var(--bui-bg-neutral-3-pressed);\n }\n\n &[data-pressed] {\n background-color: var(--bui-bg-neutral-3-pressed);\n }\n\n &[data-disabled] {\n background-color: var(--bui-bg-neutral-3-disabled);\n }\n }\n\n &[data-on-bg='neutral-3'] {\n &:hover {\n background-color: var(--bui-bg-neutral-4-hover);\n }\n\n &[data-selected] {\n background-color: var(--bui-bg-neutral-4-pressed);\n }\n\n &[data-pressed] {\n background-color: var(--bui-bg-neutral-4-pressed);\n }\n\n &[data-disabled] {\n background-color: var(--bui-bg-neutral-4-disabled);\n }\n }\n\n &[data-href],\n &[data-selection-mode],\n &[data-react-aria-pressable='true'] {\n cursor: pointer;\n }\n\n &[data-disabled] {\n background-color: var(--bui-bg-neutral-1-disabled);\n cursor: not-allowed;\n }\n }\n\n .Table_bui-TableCell__b7a883a8dd {\n padding: var(--bui-space-3);\n font-size: var(--bui-font-size-3);\n font-family: var(--bui-font-regular);\n font-weight: var(--bui-font-weight-regular);\n min-width: 0;\n overflow: hidden;\n }\n\n .Table_bui-TableCellSelection__b7a883a8dd {\n width: 40px;\n }\n\n .Table_bui-TableCellContentWrapper__b7a883a8dd {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--bui-space-2);\n min-width: 0;\n width: 100%;\n max-width: 100%;\n }\n\n .Table_bui-TableCellIcon__b7a883a8dd,\n .Table_bui-TableCellIcon__b7a883a8dd svg {\n display: inline-flex;\n align-items: center;\n color: var(--bui-fg-primary);\n }\n\n .Table_bui-TableCellContent__b7a883a8dd {\n display: flex;\n flex-direction: column;\n gap: var(--bui-space-0_5);\n min-width: 0;\n flex: 1;\n overflow: hidden;\n max-width: 100%;\n }\n\n .Table_bui-TableCellContent__b7a883a8dd > * {\n min-width: 0;\n max-width: 100%;\n }\n\n .Table_bui-TableCellProfile__b7a883a8dd {\n display: flex;\n flex-direction: row;\n gap: var(--bui-space-2);\n align-items: center;\n }\n}\n";
4
+ var styles = {"bui-TableWrapper":"Table_bui-TableWrapper__b7a883a8dd","bui-TableResizableContainer":"Table_bui-TableResizableContainer__b7a883a8dd","bui-Table":"Table_bui-Table__b7a883a8dd","bui-TableHeader":"Table_bui-TableHeader__b7a883a8dd","bui-TableHead":"Table_bui-TableHead__b7a883a8dd","bui-TableHeadSelection":"Table_bui-TableHeadSelection__b7a883a8dd","bui-TableHeadContent":"Table_bui-TableHeadContent__b7a883a8dd","bui-TableHeadLabel":"Table_bui-TableHeadLabel__b7a883a8dd","bui-TableHeadSortButton":"Table_bui-TableHeadSortButton__b7a883a8dd","bui-TableBody":"Table_bui-TableBody__b7a883a8dd","bui-TableRow":"Table_bui-TableRow__b7a883a8dd","bui-TableCell":"Table_bui-TableCell__b7a883a8dd","bui-TableCellSelection":"Table_bui-TableCellSelection__b7a883a8dd","bui-TableCellContentWrapper":"Table_bui-TableCellContentWrapper__b7a883a8dd","bui-TableCellIcon":"Table_bui-TableCellIcon__b7a883a8dd","bui-TableCellContent":"Table_bui-TableCellContent__b7a883a8dd","bui-TableCellProfile":"Table_bui-TableCellProfile__b7a883a8dd"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { styles as default };
@@ -4,20 +4,29 @@ import { Checkbox } from '../../Checkbox/Checkbox.esm.js';
4
4
  import { useDefinition } from '../../../hooks/useDefinition/useDefinition.esm.js';
5
5
  import '../../Checkbox/Checkbox.module.css.esm.js';
6
6
  import { RowDefinition } from '../definition.esm.js';
7
- import { isExternalLink } from '../../../utils/isExternalLink.esm.js';
8
- import { InternalLinkProvider } from '../../InternalLinkProvider/InternalLinkProvider.esm.js';
7
+ import { isExternalLink } from '../../../utils/linkUtils.esm.js';
9
8
  import clsx from 'clsx';
10
9
  import { Flex } from '../../Flex/Flex.esm.js';
11
10
  import '../../Flex/Flex.module.css.esm.js';
12
11
 
13
12
  function Row(props) {
14
- const { ownProps, restProps, analytics } = useDefinition(
13
+ const { ownProps, restProps, dataAttributes, analytics } = useDefinition(
15
14
  RowDefinition,
16
15
  props
17
16
  );
18
17
  const { classes, columns, children, href } = ownProps;
19
- const hasInternalHref = !!href && !isExternalLink(href);
18
+ const isExternal = isExternalLink(href);
19
+ const hasInternalHref = !!href && !isExternal;
20
+ const hasExternalHref = !!href && isExternal;
20
21
  const hasInteraction = !!restProps.onAction || !!href;
22
+ const effectiveTarget = hasExternalHref ? "_blank" : restProps.target;
23
+ const effectiveRel = effectiveTarget === "_blank" ? [
24
+ .../* @__PURE__ */ new Set([
25
+ "noopener",
26
+ "noreferrer",
27
+ ...restProps.rel?.split(/\s+/).filter(Boolean) ?? []
28
+ ])
29
+ ].join(" ") : restProps.rel;
21
30
  const handlePress = hasInteraction ? () => {
22
31
  restProps.onAction?.();
23
32
  if (href) {
@@ -28,20 +37,23 @@ function Row(props) {
28
37
  } : void 0;
29
38
  let { selectionBehavior, selectionMode } = useTableOptions();
30
39
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
31
- selectionBehavior === "toggle" && selectionMode === "multiple" && /* @__PURE__ */ jsx(Cell, { className: clsx(classes.cell, classes.cellSelection), children: /* @__PURE__ */ jsx(Flex, { justify: "center", align: "center", children: /* @__PURE__ */ jsx(Checkbox, { slot: "selection", children: /* @__PURE__ */ jsx(Fragment, {}) }) }) }),
40
+ selectionBehavior === "toggle" && selectionMode === "multiple" && /* @__PURE__ */ jsx(Cell, { className: clsx(classes.cell, classes.cellSelection), children: /* @__PURE__ */ jsx(Flex, { justify: "center", align: "center", children: /* @__PURE__ */ jsx(Checkbox, { slot: "selection", "aria-label": "Select row" }) }) }),
32
41
  /* @__PURE__ */ jsx(Collection, { items: columns, children })
33
42
  ] });
34
- return /* @__PURE__ */ jsx(InternalLinkProvider, { href, children: /* @__PURE__ */ jsx(
43
+ return /* @__PURE__ */ jsx(
35
44
  Row$1,
36
45
  {
37
46
  href,
38
- className: classes.root,
39
- "data-react-aria-pressable": hasInternalHref ? "true" : void 0,
40
47
  ...restProps,
48
+ ...dataAttributes,
49
+ target: effectiveTarget,
50
+ rel: effectiveRel,
51
+ className: clsx(classes.root, restProps.className),
52
+ "data-react-aria-pressable": hasInternalHref ? "true" : void 0,
41
53
  onAction: handlePress,
42
54
  children: content
43
55
  }
44
- ) });
56
+ );
45
57
  }
46
58
 
47
59
  export { Row };