@bluevolt-tech/lumen 2.3.1 → 2.6.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 (50) hide show
  1. package/README.md +1 -1
  2. package/dist/components/_shared/attribute-dispatch.d.ts +44 -0
  3. package/dist/components/_shared/tree-selection.d.ts +67 -0
  4. package/dist/components/bv-alert-banner/bv-alert-banner.js +1 -1
  5. package/dist/components/bv-avatar/bv-avatar.js +1 -1
  6. package/dist/components/bv-badge/bv-badge.js +1 -1
  7. package/dist/components/bv-button/bv-button.js +8 -6
  8. package/dist/components/bv-category-pill/bv-category-pill.js +1 -1
  9. package/dist/components/bv-checkbox/bv-checkbox.d.ts +15 -1
  10. package/dist/components/bv-checkbox/bv-checkbox.js +50 -5
  11. package/dist/components/bv-chip/bv-chip.js +1 -1
  12. package/dist/components/bv-course-detail/bv-course-detail.js +2 -2
  13. package/dist/components/bv-course-detail-modal/bv-course-detail-modal.js +26 -22
  14. package/dist/components/bv-course-grid-card/bv-course-grid-card.js +28 -21
  15. package/dist/components/bv-course-list-card/bv-course-list-card.js +28 -21
  16. package/dist/components/bv-course-outline/bv-course-outline.js +14 -12
  17. package/dist/components/bv-date-range-input/bv-date-range-input.js +3 -3
  18. package/dist/components/bv-date-range-picker/bv-date-range-picker.js +2 -2
  19. package/dist/components/bv-empty-state/bv-empty-state.js +21 -15
  20. package/dist/components/bv-filter-dropdown/bv-filter-dropdown.js +1 -1
  21. package/dist/components/bv-filter-panel/bv-filter-panel.d.ts +14 -0
  22. package/dist/components/bv-filter-panel/bv-filter-panel.js +87 -6
  23. package/dist/components/bv-icon/bv-icon.js +9 -7
  24. package/dist/components/bv-input/bv-input.js +1 -1
  25. package/dist/components/bv-input-dropdown/bv-input-dropdown.d.ts +123 -1
  26. package/dist/components/bv-input-dropdown/bv-input-dropdown.js +418 -14
  27. package/dist/components/bv-modal/bv-modal.js +1 -1
  28. package/dist/components/bv-page-title/bv-page-title.js +1 -1
  29. package/dist/components/bv-pagination/bv-pagination.js +1 -1
  30. package/dist/components/bv-portal-header/bv-portal-header.js +43 -37
  31. package/dist/components/bv-portal-layout/bv-portal-layout.js +1 -1
  32. package/dist/components/bv-progress-bar/bv-progress-bar.js +1 -1
  33. package/dist/components/bv-promo-banner/bv-promo-banner.js +1 -1
  34. package/dist/components/bv-radio/bv-radio.js +1 -1
  35. package/dist/components/bv-search-picker/bv-search-picker.d.ts +59 -0
  36. package/dist/components/bv-search-picker/bv-search-picker.js +175 -23
  37. package/dist/components/bv-segmented-control/bv-segmented-control.d.ts +13 -0
  38. package/dist/components/bv-segmented-control/bv-segmented-control.js +1 -1
  39. package/dist/components/bv-select/bv-select.js +1 -1
  40. package/dist/components/bv-split-button/bv-split-button.js +8 -6
  41. package/dist/components/bv-star-rating/bv-star-rating.js +1 -1
  42. package/dist/components/bv-table/bv-table.d.ts +50 -0
  43. package/dist/components/bv-table/bv-table.js +275 -34
  44. package/dist/components/bv-toggle/bv-toggle.d.ts +15 -0
  45. package/dist/components/bv-toggle/bv-toggle.js +40 -3
  46. package/dist/components/bv-user-row/bv-user-row.js +22 -15
  47. package/dist/components/bv-view-switcher/bv-view-switcher.js +1 -1
  48. package/dist/themes/base.css +0 -5
  49. package/package.json +11 -8
  50. package/themes/base.css +0 -5
@@ -1,5 +1,5 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-search-picker/bv-search-picker.css
2
- var bv_search_picker_default = ":host {\n display: block;\n position: relative;\n font-family: var(--bv-font-family-base);\n}\n\n/* \u2500\u2500 Field label \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n line-height: 1.5;\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n margin-bottom: var(--bv-spacing-xs-plus);\n}\n\n.field-label:empty {\n display: none;\n}\n\n/* \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.trigger {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-xs);\n width: max-content;\n min-width: 120px;\n max-width: 220px;\n box-sizing: border-box;\n min-height: var(--bv-control-height-lg);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-md);\n background: var(--bv-color-neutral-0);\n padding: 5px var(--bv-spacing-sm);\n cursor: pointer;\n font-family: inherit;\n transition:\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n.trigger:focus-visible {\n outline: none;\n border-color: var(--bv-color-primary);\n box-shadow: 0 0 0 3px var(--bv-color-primary-light);\n}\n\n:host([open]) .trigger {\n border-color: var(--bv-color-primary);\n box-shadow: 0 0 0 3px var(--bv-color-primary-light);\n}\n\n:host([disabled]) .trigger {\n background: var(--bv-color-neutral-100);\n cursor: not-allowed;\n}\n\n.trigger-pill {\n display: inline-flex;\n align-items: center;\n gap: var(--bv-spacing-xs);\n height: 26px;\n /* Symmetric padding so the pill still looks balanced with the clear button\n hidden (count === 0) \u2014 an asymmetric right pad only reads correctly when\n the clear button is actually there to visually fill the extra space. */\n padding: 0 var(--bv-spacing-sm-plus);\n border-radius: var(--bv-radius-full);\n background: var(--bv-color-primary-light);\n color: var(--bv-color-primary-dark);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n white-space: nowrap;\n}\n\n.trigger-pill.mode-exclude {\n background: var(--bv-color-danger-light);\n color: var(--bv-color-danger-dark);\n}\n\n.trigger-pill-clear {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: none;\n color: inherit;\n cursor: pointer;\n opacity: 0.7;\n}\n\n/* The `display` rule above wins over the UA's [hidden]{display:none} (author\n origin beats user-agent origin regardless of specificity) \u2014 restate it. */\n.trigger-pill-clear[hidden] {\n display: none;\n}\n\n.trigger-pill-clear:hover {\n /* Overlay derived from the neutral-900 token (matches the pattern\n bv-alert-banner uses for its close-btn hover \u2014 token + color-mix, no\n hardcoded rgba). Works over both include (primary-light) and exclude\n (danger-light) pill backgrounds. */\n background: color-mix(in srgb, var(--bv-color-neutral-900) 12%, transparent);\n opacity: 1;\n}\n\n/*\n * The pill-clear is a `span[role=\"button\"]` (not a native <button>) so that\n * it can nest inside the trigger button without producing invalid HTML.\n * Native <button> would give us a visible focus ring for free; role=\"button\"\n * doesn't, so paint one explicitly for keyboard users.\n */\n.trigger-pill-clear:focus-visible {\n outline: 2px solid var(--bv-color-primary);\n outline-offset: 1px;\n opacity: 1;\n}\n\n.trigger-caret {\n display: flex;\n align-items: center;\n margin-left: auto;\n color: var(--bv-color-neutral-500);\n flex-shrink: 0;\n transition: transform var(--bv-transition-fast);\n}\n\n:host([open]) .trigger-caret {\n transform: rotate(180deg);\n}\n\n/* \u2500\u2500 BTN-10322 \xB7 cascade cleared affordance \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.cleared-affordance {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n margin-top: var(--bv-spacing-xs-plus);\n padding: var(--bv-spacing-sm) var(--bv-spacing-md-minus);\n background: var(--bv-color-warning-light);\n color: var(--bv-color-warning-dark);\n border-radius: var(--bv-radius-md);\n font-size: var(--bv-font-size-xs);\n line-height: 1.4;\n}\n\n.cleared-affordance[hidden] {\n display: none;\n}\n\n.cleared-affordance-icon {\n display: inline-flex;\n align-items: center;\n color: var(--bv-color-warning);\n flex-shrink: 0;\n}\n\n.cleared-affordance-msg {\n flex: 1;\n}\n\n.cleared-affordance-dismiss {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n padding: 0;\n border: none;\n border-radius: var(--bv-radius-full);\n background: none;\n color: inherit;\n cursor: pointer;\n opacity: 0.7;\n flex-shrink: 0;\n}\n\n.cleared-affordance-dismiss:hover {\n background: color-mix(in srgb, var(--bv-color-neutral-900) 12%, transparent);\n opacity: 1;\n}\n\n/* \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.panel {\n display: none;\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n width: 680px;\n max-width: calc(100vw - var(--bv-spacing-md) * 2);\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n box-shadow: var(--bv-shadow-md);\n z-index: 200;\n overflow: hidden;\n}\n\n:host([open]) .panel {\n display: flex;\n flex-direction: column;\n}\n\n/* Smart positioning \u2014 flips to whichever side has room (see _positionPanel\n in bv-search-picker.ts) instead of always overflowing past a screen edge. */\n:host([data-placement='top']) .panel {\n top: auto;\n bottom: calc(100% + 4px);\n}\n\n:host([data-align='right']) .panel {\n left: auto;\n right: 0;\n}\n\n.panel-toolbar {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n padding: var(--bv-spacing-sm-plus) var(--bv-spacing-md-minus);\n border-bottom: 1px solid var(--bv-color-neutral-200);\n background: var(--bv-color-neutral-100);\n}\n\n.panel-toolbar bv-toggle {\n margin-left: auto;\n flex-shrink: 0;\n}\n\n.panel-body {\n display: flex;\n min-height: 230px;\n}\n\n/* \u2500\u2500 Results pane \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.results-pane {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n border-right: 1px solid var(--bv-color-neutral-200);\n}\n\n/* bv-searchbox's :host is width:100%, so the inset has to be padding on this\n wrapper \u2014 a margin on the searchbox itself would push it past the pane's\n edge, since 100% resolves against the container regardless of the child's\n own margin. */\n.results-search {\n padding: var(--bv-spacing-sm);\n}\n\n.results-list {\n flex: 1;\n max-height: 190px;\n overflow-y: auto;\n}\n\n.result-row {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n padding: var(--bv-spacing-sm) var(--bv-spacing-md-minus);\n border-top: 1px solid var(--bv-color-neutral-100);\n cursor: pointer;\n}\n\n.result-row:hover {\n background: var(--bv-color-primary-50);\n}\n\n/* BTN-10322 \xB7 a11y \u2014 keyboard-focused row (Arrow Up/Down) gets a visible\n ring so a keyboard-only user can see where they are. `aria-selected`\n mirrors the focus position so screen readers announce it. */\n.result-row:focus-visible,\n.result-row[aria-selected='true'] {\n background: var(--bv-color-primary-50);\n outline: 2px solid var(--bv-color-primary);\n outline-offset: -2px;\n}\n\n.results-rows:focus-visible {\n outline: 2px solid var(--bv-color-primary);\n outline-offset: -2px;\n}\n\n.result-name {\n /* min-width:0 overrides the flex-item default of min-width:auto, which\n would otherwise refuse to shrink below the text's natural width and\n defeat the wrap/clamp below entirely. */\n min-width: 0;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-800);\n font-weight: var(--bv-font-weight-semibold);\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n white-space: normal;\n word-break: break-word;\n}\n\n.result-inactive {\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-500);\n flex-shrink: 0;\n}\n\n.result-add {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: none;\n color: var(--bv-color-primary);\n flex-shrink: 0;\n padding: 0;\n cursor: pointer;\n}\n\n.results-empty {\n padding: var(--bv-spacing-md-minus) var(--bv-spacing-md-minus);\n font-size: var(--bv-font-size-xs);\n color: var(--bv-color-neutral-400);\n line-height: 1.5;\n}\n\n.results-empty:empty,\n.results-empty[hidden] {\n display: none;\n}\n\n/* \u2500\u2500 Loading skeleton (mirrors bv-filter-panel's pattern) \u2500\u2500\u2500 */\n\n.skeleton {\n display: none;\n flex-direction: column;\n}\n\n:host([loading]) .skeleton {\n display: flex;\n}\n\n:host([loading]) .results-rows,\n:host([loading]) .results-empty {\n display: none;\n}\n\n.skeleton-row {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm-plus);\n padding: var(--bv-spacing-sm) var(--bv-spacing-md-minus);\n border-top: 1px solid var(--bv-color-neutral-100);\n}\n\n.skeleton-line {\n height: 11px;\n border-radius: var(--bv-radius-sm);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n@keyframes bv-skeleton-shimmer {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n\n/* \u2500\u2500 Basket pane \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.basket-pane {\n width: 210px;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n background: var(--bv-color-neutral-100);\n}\n\n.basket-header {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n padding: var(--bv-spacing-sm-plus) var(--bv-spacing-md-minus);\n}\n\n.basket-header-label {\n font-size: var(--bv-font-size-xs);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-500);\n}\n\n.basket-clear-all {\n margin-left: auto;\n border: none;\n background: none;\n padding: 0;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-primary);\n cursor: pointer;\n}\n\n.basket-clear-all:hover {\n color: var(--bv-color-primary-dark);\n text-decoration: underline;\n}\n\n.basket-clear-all[hidden] {\n display: none;\n}\n\n.basket-list {\n flex: 1;\n max-height: 190px;\n overflow-y: auto;\n padding: 0 var(--bv-spacing-sm) var(--bv-spacing-sm);\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-xs);\n}\n\n.basket-row {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-xs);\n padding: var(--bv-spacing-xs) var(--bv-spacing-sm);\n border-radius: var(--bv-radius-sm);\n background: var(--bv-color-primary-light);\n}\n\n.basket-row.mode-exclude {\n background: var(--bv-color-danger-light);\n}\n\n.basket-row-name {\n min-width: 0;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n white-space: normal;\n word-break: break-word;\n}\n\n.basket-row-remove {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: none;\n color: var(--bv-color-neutral-500);\n flex-shrink: 0;\n padding: 0;\n cursor: pointer;\n}\n\n.basket-empty {\n padding: var(--bv-spacing-xs) var(--bv-spacing-2xs);\n font-size: var(--bv-font-size-xs);\n color: var(--bv-color-neutral-400);\n line-height: 1.5;\n}\n\n/* \u2500\u2500 Footer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.panel-footer {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n padding: var(--bv-spacing-sm-plus) var(--bv-spacing-md-minus);\n border-top: 1px solid var(--bv-color-neutral-200);\n background: var(--bv-color-neutral-0);\n}\n\n.panel-footer bv-button {\n margin-left: auto;\n flex-shrink: 0;\n}\n\n.results-limit-note {\n font-size: var(--bv-font-size-xs);\n color: var(--bv-color-neutral-500);\n line-height: 1.4;\n}\n";
2
+ var bv_search_picker_default = ":host {\n display: block;\n position: relative;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n/* \u2500\u2500 Field label \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n line-height: 1.5;\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n margin-bottom: var(--bv-spacing-xs-plus);\n}\n\n.field-label:empty {\n display: none;\n}\n\n/* \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.trigger {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-xs);\n /* Shrink-to-fit its own label by default (a compact pill, not a full-width\n dropdown) \u2014 consumers that need a uniform width across a row of mixed\n field types (e.g. sitting alongside bv-input-dropdown) can override this\n rather than the component silently always filling its host's box. */\n width: var(--bv-search-picker-trigger-width, max-content);\n /* Also overridable \u2014 a consumer that shrinks the host below 120px (e.g. to\n fit a fixed viewport floor) needs this floor to shrink too, or the\n trigger silently overflows its own host box and overlaps whatever sits\n next to it. */\n min-width: var(--bv-search-picker-trigger-min-width, 120px);\n max-width: 220px;\n box-sizing: border-box;\n min-height: var(--bv-control-height-lg);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-md);\n background: var(--bv-color-neutral-0);\n padding: 5px var(--bv-spacing-sm);\n cursor: pointer;\n font-family: inherit;\n transition:\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n.trigger:focus-visible {\n outline: none;\n border-color: var(--bv-color-primary);\n box-shadow: 0 0 0 3px var(--bv-color-primary-light);\n}\n\n:host([open]) .trigger {\n border-color: var(--bv-color-primary);\n box-shadow: 0 0 0 3px var(--bv-color-primary-light);\n}\n\n:host([disabled]) .trigger {\n background: var(--bv-color-neutral-100);\n cursor: not-allowed;\n}\n\n.trigger-pill {\n display: inline-flex;\n align-items: center;\n gap: var(--bv-spacing-xs);\n height: 26px;\n /* Symmetric padding so the pill still looks balanced with the clear button\n hidden (count === 0) \u2014 an asymmetric right pad only reads correctly when\n the clear button is actually there to visually fill the extra space. */\n padding: 0 var(--bv-spacing-sm-plus);\n border-radius: var(--bv-radius-full);\n background: var(--bv-color-primary-light);\n color: var(--bv-color-primary-dark);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n white-space: nowrap;\n /* Without this, this flex item's default min-width:auto refuses to shrink\n below its content's natural width \u2014 the same reason .trigger needs its\n own min-width overridden (see bv-search-picker.ts) \u2014 and the pill spills\n out past a narrowed .trigger instead of truncating with it. */\n min-width: 0;\n}\n\n.trigger-pill-text {\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.trigger-pill.mode-exclude {\n background: var(--bv-color-danger-light);\n color: var(--bv-color-danger-dark);\n}\n\n.trigger-pill-clear {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: none;\n color: inherit;\n cursor: pointer;\n opacity: 0.7;\n}\n\n/* The `display` rule above wins over the UA's [hidden]{display:none} (author\n origin beats user-agent origin regardless of specificity) \u2014 restate it. */\n.trigger-pill-clear[hidden] {\n display: none;\n}\n\n.trigger-pill-clear:hover {\n /* Overlay derived from the neutral-900 token (matches the pattern\n bv-alert-banner uses for its close-btn hover \u2014 token + color-mix, no\n hardcoded rgba). Works over both include (primary-light) and exclude\n (danger-light) pill backgrounds. */\n background: color-mix(in srgb, var(--bv-color-neutral-900) 12%, transparent);\n opacity: 1;\n}\n\n/*\n * The pill-clear is a `span[role=\"button\"]` (not a native <button>) so that\n * it can nest inside the trigger button without producing invalid HTML.\n * Native <button> would give us a visible focus ring for free; role=\"button\"\n * doesn't, so paint one explicitly for keyboard users.\n */\n.trigger-pill-clear:focus-visible {\n outline: 2px solid var(--bv-color-primary);\n outline-offset: 1px;\n opacity: 1;\n}\n\n.trigger-caret {\n display: flex;\n align-items: center;\n margin-left: auto;\n color: var(--bv-color-neutral-500);\n flex-shrink: 0;\n transition: transform var(--bv-transition-fast);\n}\n\n:host([open]) .trigger-caret {\n transform: rotate(180deg);\n}\n\n/* \u2500\u2500 BTN-10322 \xB7 cascade cleared affordance \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.cleared-affordance {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n margin-top: var(--bv-spacing-xs-plus);\n padding: var(--bv-spacing-sm) var(--bv-spacing-md-minus);\n background: var(--bv-color-warning-light);\n color: var(--bv-color-warning-dark);\n border-radius: var(--bv-radius-md);\n font-size: var(--bv-font-size-xs);\n line-height: 1.4;\n}\n\n.cleared-affordance[hidden] {\n display: none;\n}\n\n.cleared-affordance-icon {\n display: inline-flex;\n align-items: center;\n color: var(--bv-color-warning);\n flex-shrink: 0;\n}\n\n.cleared-affordance-msg {\n flex: 1;\n}\n\n.cleared-affordance-dismiss {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n padding: 0;\n border: none;\n border-radius: var(--bv-radius-full);\n background: none;\n color: inherit;\n cursor: pointer;\n opacity: 0.7;\n flex-shrink: 0;\n}\n\n.cleared-affordance-dismiss:hover {\n background: color-mix(in srgb, var(--bv-color-neutral-900) 12%, transparent);\n opacity: 1;\n}\n\n/* \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.panel {\n display: none;\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n width: 680px;\n max-width: calc(100vw - var(--bv-spacing-md) * 2);\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n box-shadow: var(--bv-shadow-md);\n z-index: 200;\n overflow: hidden;\n}\n\n:host([open]) .panel {\n display: flex;\n flex-direction: column;\n}\n\n/* Smart positioning \u2014 flips to whichever side has room (see _positionPanel\n in bv-search-picker.ts) instead of always overflowing past a screen edge. */\n:host([data-placement='top']) .panel {\n top: auto;\n bottom: calc(100% + 4px);\n}\n\n:host([data-align='right']) .panel {\n left: auto;\n right: 0;\n}\n\n.panel-toolbar {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n padding: var(--bv-spacing-sm-plus) var(--bv-spacing-md-minus);\n border-bottom: 1px solid var(--bv-color-neutral-200);\n background: var(--bv-color-neutral-100);\n}\n\n.panel-toolbar bv-toggle {\n margin-left: auto;\n flex-shrink: 0;\n}\n\n.panel-body {\n display: flex;\n min-height: 230px;\n}\n\n/* \u2500\u2500 Results pane \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.results-pane {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n border-right: 1px solid var(--bv-color-neutral-200);\n}\n\n/* bv-searchbox's :host is width:100%, so the inset has to be padding on this\n wrapper \u2014 a margin on the searchbox itself would push it past the pane's\n edge, since 100% resolves against the container regardless of the child's\n own margin. */\n.results-search {\n padding: var(--bv-spacing-sm);\n}\n\n.results-list {\n flex: 1;\n max-height: 190px;\n overflow-y: auto;\n}\n\n.result-row {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n padding: var(--bv-spacing-sm) var(--bv-spacing-md-minus);\n border-top: 1px solid var(--bv-color-neutral-100);\n cursor: pointer;\n}\n\n.result-row:hover {\n background: var(--bv-color-primary-50);\n}\n\n/* BTN-10322 \xB7 a11y \u2014 keyboard-focused row (Arrow Up/Down) gets a visible\n ring so a keyboard-only user can see where they are. `aria-selected`\n mirrors the focus position so screen readers announce it. */\n.result-row:focus-visible,\n.result-row[aria-selected='true'] {\n background: var(--bv-color-primary-50);\n outline: 2px solid var(--bv-color-primary);\n outline-offset: -2px;\n}\n\n.results-rows:focus-visible {\n outline: 2px solid var(--bv-color-primary);\n outline-offset: -2px;\n}\n\n.result-name {\n /* min-width:0 overrides the flex-item default of min-width:auto, which\n would otherwise refuse to shrink below the text's natural width and\n defeat the wrap/clamp below entirely. */\n min-width: 0;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-800);\n font-weight: var(--bv-font-weight-semibold);\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n white-space: normal;\n word-break: break-word;\n}\n\n.result-inactive {\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-500);\n flex-shrink: 0;\n}\n\n.result-add {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: none;\n color: var(--bv-color-primary);\n flex-shrink: 0;\n padding: 0;\n cursor: pointer;\n}\n\n.results-empty {\n padding: var(--bv-spacing-md-minus) var(--bv-spacing-md-minus);\n font-size: var(--bv-font-size-xs);\n color: var(--bv-color-neutral-400);\n line-height: 1.5;\n}\n\n.results-empty:empty,\n.results-empty[hidden] {\n display: none;\n}\n\n/* \u2500\u2500 Loading skeleton (mirrors bv-filter-panel's pattern) \u2500\u2500\u2500 */\n\n.skeleton {\n display: none;\n flex-direction: column;\n}\n\n:host([loading]) .skeleton {\n display: flex;\n}\n\n:host([loading]) .results-rows,\n:host([loading]) .results-empty {\n display: none;\n}\n\n.skeleton-row {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm-plus);\n padding: var(--bv-spacing-sm) var(--bv-spacing-md-minus);\n border-top: 1px solid var(--bv-color-neutral-100);\n}\n\n.skeleton-line {\n height: 11px;\n border-radius: var(--bv-radius-sm);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n@keyframes bv-skeleton-shimmer {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n\n/* \u2500\u2500 Basket pane \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.basket-pane {\n width: 210px;\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n background: var(--bv-color-neutral-100);\n}\n\n.basket-header {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n padding: var(--bv-spacing-sm-plus) var(--bv-spacing-md-minus);\n}\n\n.basket-header-label {\n font-size: var(--bv-font-size-xs);\n letter-spacing: 0.08em;\n text-transform: uppercase;\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-500);\n}\n\n.basket-clear-all {\n margin-left: auto;\n border: none;\n background: none;\n padding: 0;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-primary);\n cursor: pointer;\n}\n\n.basket-clear-all:hover {\n color: var(--bv-color-primary-dark);\n text-decoration: underline;\n}\n\n.basket-clear-all[hidden] {\n display: none;\n}\n\n.basket-list {\n flex: 1;\n max-height: 190px;\n overflow-y: auto;\n padding: 0 var(--bv-spacing-sm) var(--bv-spacing-sm);\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-xs);\n}\n\n.basket-row {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-xs);\n padding: var(--bv-spacing-xs) var(--bv-spacing-sm);\n border-radius: var(--bv-radius-sm);\n background: var(--bv-color-primary-light);\n}\n\n.basket-row.mode-exclude {\n background: var(--bv-color-danger-light);\n}\n\n.basket-row-name {\n min-width: 0;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n white-space: normal;\n word-break: break-word;\n}\n\n.basket-row-remove {\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: none;\n color: var(--bv-color-neutral-500);\n flex-shrink: 0;\n padding: 0;\n cursor: pointer;\n}\n\n/* BTN-11916 \xB7 a11y \u2014 the basket is a roving-tabindex group, so Arrow Up/Down\n moves focus between these buttons without any click. A keyboard user has to\n be able to see which one they are on; matches the ring on .result-row. */\n.basket-row-remove:focus-visible {\n outline: 2px solid var(--bv-color-primary);\n outline-offset: 2px;\n border-radius: var(--bv-radius-sm);\n}\n\n.basket-empty {\n padding: var(--bv-spacing-xs) var(--bv-spacing-2xs);\n font-size: var(--bv-font-size-xs);\n color: var(--bv-color-neutral-400);\n line-height: 1.5;\n}\n\n/* \u2500\u2500 Footer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.panel-footer {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n padding: var(--bv-spacing-sm-plus) var(--bv-spacing-md-minus);\n border-top: 1px solid var(--bv-color-neutral-200);\n background: var(--bv-color-neutral-0);\n}\n\n.panel-footer bv-button {\n margin-left: auto;\n flex-shrink: 0;\n}\n\n.results-limit-note {\n font-size: var(--bv-font-size-xs);\n color: var(--bv-color-neutral-500);\n line-height: 1.4;\n}\n\n/* These elements have an author `display`, which beats the user-agent\n `[hidden] { display: none }` regardless of specificity. The component\n toggles their `hidden`, so without this the property changes nothing on\n screen (BTN-11521). */\n.cleared-affordance[hidden] {\n display: none;\n}\n";
3
3
 
4
4
  // components/_shared/adopt-styles.ts
5
5
  var _sheetCache = /* @__PURE__ */ new Map();
@@ -78,7 +78,7 @@ function bindDropdownController(host, options = {}) {
78
78
  }
79
79
 
80
80
  // components/bv-icon/icons.ts
81
- var icons = {
81
+ var icons = Object.assign(/* @__PURE__ */ Object.create(null), {
82
82
  // Navigation
83
83
  "chevron-up": `<path d="M18 15l-6-6-6 6"/>`,
84
84
  "chevron-down": `<path d="M6 9l6 6 6-6"/>`,
@@ -129,16 +129,16 @@ var icons = {
129
129
  bell: `<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/>`,
130
130
  mail: `<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/>`,
131
131
  link: `<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>`
132
- };
132
+ });
133
133
  function getIconSvg(name, size = 16) {
134
- const raw = rawIcons[name];
134
+ const raw = RAW_ICON_MAP.get(name);
135
135
  if (raw)
136
136
  return raw.replace(/width="[^"]*"/, `width="${size}"`).replace(/height="[^"]*"/, `height="${size}"`);
137
- const paths = icons[name];
137
+ const paths = ICON_MAP.get(name);
138
138
  if (!paths) return "";
139
139
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${paths}</svg>`;
140
140
  }
141
- var rawIcons = {
141
+ var rawIcons = Object.assign(/* @__PURE__ */ Object.create(null), {
142
142
  // Module type (small, ~18px)
143
143
  "module-scorm": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 15.03 16.28" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13.9014 4.60034L7.51368 8.14201M7.51368 8.14201L1.126 4.60034M7.51368 8.14201L7.5137 15.267M14.2771 11.1859V5.09812C14.2771 4.84113 14.2771 4.71264 14.2392 4.59804C14.2056 4.49666 14.1508 4.4036 14.0783 4.32508C13.9963 4.23633 13.8838 4.17393 13.6587 4.04913L8.09763 0.965793C7.88451 0.847624 7.77794 0.78854 7.66509 0.765376C7.56521 0.744875 7.46219 0.744875 7.36231 0.765376C7.24946 0.78854 7.1429 0.847624 6.92977 0.965793L1.36873 4.04913C1.14364 4.17393 1.0311 4.23633 0.949147 4.32508C0.876647 4.4036 0.82178 4.49666 0.788217 4.59804C0.750278 4.71264 0.750278 4.84113 0.750278 5.09812V11.1859C0.750278 11.4429 0.750278 11.5714 0.788217 11.686C0.82178 11.7874 0.876647 11.8805 0.949147 11.959C1.0311 12.0477 1.14364 12.1101 1.36873 12.2349L6.92977 15.3183C7.1429 15.4364 7.24946 15.4955 7.36231 15.5187C7.46219 15.5392 7.56521 15.5392 7.66509 15.5187C7.77794 15.4955 7.88451 15.4364 8.09763 15.3183L13.6587 12.2349C13.8838 12.1101 13.9963 12.0477 14.0783 11.959C14.1508 11.8805 14.2056 11.7874 14.2392 11.686C14.2771 11.5714 14.2771 11.4429 14.2771 11.1859Z"/></svg>`,
144
144
  "module-assessment": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 13.72 16.13" fill="none" stroke="currentColor" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12.507 6.1875V4.1625C12.507 2.90238 12.507 2.27232 12.2629 1.79102C12.0482 1.36766 11.7056 1.02345 11.2841 0.807736C10.8051 0.5625 10.1779 0.5625 8.92364 0.5625H4.14585C2.89156 0.5625 2.26441 0.5625 1.78534 0.807736C1.36393 1.02345 1.02132 1.36766 0.806601 1.79102C0.5625 2.27232 0.5625 2.90238 0.5625 4.1625V11.9625C0.5625 13.2226 0.5625 13.8527 0.806601 14.334C1.02132 14.7573 1.36393 15.1015 1.78534 15.3173C2.26441 15.5625 2.89156 15.5625 4.14585 15.5625H8.0278M8.0278 7.3125H3.54862M5.04168 10.3125H3.54862M9.52086 4.3125H3.54862M9.89413 10.3142C10.0257 9.93852 10.2853 9.62175 10.627 9.41998C10.9688 9.21821 11.3705 9.14445 11.7612 9.21178C12.1519 9.2791 12.5062 9.48315 12.7615 9.7878C13.0168 10.0925 13.1565 10.478 13.1559 10.8763C13.1559 12.0004 11.4775 12.5625 11.4775 12.5625M11.4991 14.8125H11.5066"/></svg>`,
@@ -148,7 +148,9 @@ var rawIcons = {
148
148
  "module-adobe-connect": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 16.06 14.63" fill="none" stroke="currentColor" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11.7605 0.56252L8.0278 3.56252L4.29515 0.56252M4.14585 14.0625H11.9098C13.164 14.0625 13.7912 14.0625 14.2703 13.8173C14.6917 13.6016 15.0343 13.2574 15.249 12.834C15.4931 12.3527 15.4931 11.7226 15.4931 10.4625V7.16252C15.4931 5.9024 15.4931 5.27234 15.249 4.79104C15.0343 4.36768 14.6917 4.02347 14.2703 3.80776C13.7912 3.56252 13.164 3.56252 11.9098 3.56252H4.14585C2.89156 3.56252 2.26441 3.56252 1.78534 3.80776C1.36393 4.02347 1.02132 4.36768 0.806601 4.79104C0.5625 5.27234 0.5625 5.9024 0.5625 7.16252V10.4625C0.5625 11.7226 0.5625 12.3527 0.806601 12.834C1.02132 13.2574 1.36393 13.6016 1.78534 13.8173C2.26441 14.0625 2.89156 14.0625 4.14585 14.0625Z"/></svg>`,
149
149
  "module-video": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 16.06 11.63" fill="none" stroke="currentColor" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15.4931 3.51103C15.4931 3.05667 15.4931 2.82949 15.4037 2.72429C15.3261 2.63301 15.2097 2.58457 15.0906 2.59399C14.9533 2.60484 14.7934 2.76548 14.4736 3.08676L11.7605 5.8125L14.4736 8.53824C14.7934 8.85952 14.9533 9.02016 15.0906 9.03101C15.2097 9.04043 15.3261 8.99199 15.4037 8.90071C15.4931 8.79552 15.4931 8.56833 15.4931 8.11397V3.51103ZM0.5625 4.1625C0.5625 2.90238 0.5625 2.27232 0.806601 1.79102C1.02132 1.36766 1.36393 1.02345 1.78534 0.807736C2.26441 0.5625 2.89156 0.5625 4.14585 0.5625H8.17711C9.4314 0.5625 10.0585 0.5625 10.5376 0.807736C10.959 1.02345 11.3016 1.36766 11.5164 1.79102C11.7605 2.27232 11.7605 2.90238 11.7605 4.1625V7.4625C11.7605 8.72262 11.7605 9.35268 11.5164 9.83398C11.3016 10.2573 10.959 10.6015 10.5376 10.8173C10.0585 11.0625 9.4314 11.0625 8.17711 11.0625H4.14584C2.89156 11.0625 2.26441 11.0625 1.78534 10.8173C1.36393 10.6015 1.02132 10.2573 0.806601 9.83398C0.5625 9.35268 0.5625 8.72262 0.5625 7.4625V4.1625Z"/></svg>`,
150
150
  "module-upload": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 14.75 16.13" fill="none" stroke="currentColor" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13.39 4.3125V4.1625C13.39 2.90238 13.39 2.27232 13.1278 1.79102C12.8972 1.36766 12.5293 1.02345 12.0767 0.807736C11.5622 0.5625 10.8887 0.5625 9.54172 0.5625H4.41074C3.06373 0.5625 2.39022 0.5625 1.87573 0.807736C1.42318 1.02345 1.05524 1.36766 0.824646 1.79102C0.5625 2.27232 0.5625 2.90238 0.5625 4.1625V11.9625C0.5625 13.2226 0.5625 13.8527 0.824646 14.334C1.05524 14.7573 1.42318 15.1015 1.87573 15.3173C2.39022 15.5625 3.06373 15.5625 4.41074 15.5625H7.37709M7.37709 7.3125H3.76936M6.57537 10.3125H3.76936M10.1831 4.3125H3.76936M11.7865 12.5625V8.4375C11.7865 7.81618 12.3249 7.3125 12.9891 7.3125C13.6533 7.3125 14.1917 7.81618 14.1917 8.4375V12.5625C14.1917 13.8051 13.1149 14.8125 11.7865 14.8125C10.4582 14.8125 9.38138 13.8051 9.38138 12.5625V9.5625"/></svg>`
151
- };
151
+ });
152
+ var RAW_ICON_MAP = new Map(Object.entries(rawIcons));
153
+ var ICON_MAP = new Map(Object.entries(icons));
152
154
 
153
155
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-searchbox/bv-searchbox.css
154
156
  var bv_searchbox_default = ":host {\n display: block;\n width: 100%;\n position: relative;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--bv-color-neutral-400);\n display: flex;\n pointer-events: none;\n}\n\n.search-input {\n width: 100%;\n box-sizing: border-box;\n height: 40px;\n padding: 0 12px 0 38px;\n font-size: var(--bv-font-size-sm);\n font-family: inherit;\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-lg);\n outline: none;\n color: var(--bv-color-neutral-800);\n background: var(--bv-color-neutral-0);\n transition: border-color var(--bv-transition-fast);\n}\n\n:host([size='sm']) .search-input {\n height: 36px;\n}\n:host([size='lg']) .search-input {\n height: 46px;\n}\n\n.search-input::placeholder {\n color: var(--bv-color-neutral-400);\n}\n\n.search-input:focus {\n border-color: #6fb0d8;\n box-shadow:\n 0px 0px 0px 4px #dbe8ff,\n 0px 1px 2px 0px rgba(16, 24, 40, 0.05);\n}\n";
@@ -207,7 +209,7 @@ if (!customElements.get("bv-searchbox")) {
207
209
  }
208
210
 
209
211
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-segmented-control/bv-segmented-control.css
210
- var bv_segmented_control_default = ":host {\n display: block;\n font-family: var(--bv-font-family-base);\n}\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n line-height: 20px;\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n margin-bottom: 6px;\n}\n\n.field-label[hidden] {\n display: none;\n}\n\n.required-mark {\n color: var(--bv-color-danger);\n margin-left: 2px;\n}\n\n.container {\n display: flex;\n align-items: center;\n height: 44px;\n box-sizing: border-box;\n background: var(--bv-color-neutral-100);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n padding: 3px;\n gap: 2px;\n}\n\n:host([size='sm']) .container {\n height: var(--bv-control-height-md);\n border-radius: var(--bv-radius-md);\n padding: 3px;\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 0 var(--bv-spacing-md);\n border: none;\n border-radius: calc(var(--bv-radius-lg) - 3px);\n background: transparent;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-500);\n cursor: pointer;\n white-space: nowrap;\n user-select: none;\n transition:\n color var(--bv-transition-fast),\n background var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n:host([size='sm']) .pill {\n padding: 0 var(--bv-spacing-md-minus);\n font-size: var(--bv-font-size-sm);\n}\n\n.pill:hover:not(.selected) {\n color: var(--bv-color-neutral-800);\n}\n\n.pill.selected {\n background: var(--bv-color-neutral-0);\n color: var(--bv-color-neutral-900);\n box-shadow: var(--bv-shadow-sm);\n}\n\n/* Filled variant \u2014 selected pill uses the primary color instead of white */\n:host([variant='primary']) .pill.selected {\n background: var(--bv-color-primary);\n color: var(--bv-color-neutral-0);\n}\n";
212
+ var bv_segmented_control_default = ":host {\n display: block;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n line-height: 20px;\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n margin-bottom: 6px;\n}\n\n.field-label[hidden] {\n display: none;\n}\n\n.required-mark {\n color: var(--bv-color-danger);\n margin-left: 2px;\n}\n\n.container {\n display: flex;\n align-items: center;\n height: 44px;\n box-sizing: border-box;\n background: var(--bv-color-neutral-100);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n padding: 3px;\n gap: 2px;\n}\n\n:host([size='sm']) .container {\n height: var(--bv-control-height-md);\n border-radius: var(--bv-radius-md);\n padding: 3px;\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n /* Horizontal-only override, independent of `size` \u2014 a consumer fighting\n for width in a row of same-height controls needs the pill narrower\n without the control itself getting shorter than its neighbors, which\n `size=\"sm\"` would also do (it shrinks the container height too). */\n padding: 0 var(--bv-segmented-control-pill-padding-x, var(--bv-spacing-md));\n border: none;\n border-radius: calc(var(--bv-radius-lg) - 3px);\n background: transparent;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-500);\n cursor: pointer;\n white-space: nowrap;\n user-select: none;\n transition:\n color var(--bv-transition-fast),\n background var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n:host([size='sm']) .pill {\n /* Same override hook as the default size, with sm's own tighter fallback \u2014\n otherwise the custom property would silently do nothing on size=\"sm\",\n which is exactly the combination a consumer squeezed for width reaches\n for first. */\n padding: 0 var(--bv-segmented-control-pill-padding-x, var(--bv-spacing-md-minus));\n font-size: var(--bv-font-size-sm);\n}\n\n.pill:hover:not(.selected) {\n color: var(--bv-color-neutral-800);\n}\n\n.pill.selected {\n background: var(--bv-color-neutral-0);\n color: var(--bv-color-neutral-900);\n box-shadow: var(--bv-shadow-sm);\n}\n\n/* Filled variant \u2014 selected pill uses the primary color instead of white */\n:host([variant='primary']) .pill.selected {\n background: var(--bv-color-primary);\n color: var(--bv-color-neutral-0);\n}\n\n/* These elements have an author `display`, which beats the user-agent\n `[hidden] { display: none }` regardless of specificity. The component\n toggles their `hidden`, so without this the property changes nothing on\n screen (BTN-11521). */\n.field-label[hidden] {\n display: none;\n}\n";
211
213
 
212
214
  // components/bv-segmented-control/bv-segmented-control.ts
213
215
  var BvSegmentedControl = class extends HTMLElement {
@@ -336,12 +338,13 @@ if (!customElements.get("bv-segmented-control")) {
336
338
  }
337
339
 
338
340
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-toggle/bv-toggle.css
339
- var bv_toggle_default = ":host {\n --bv-toggle-width: 44px;\n --bv-toggle-height: 24px;\n --bv-toggle-track-off: var(--bv-color-neutral-300);\n --bv-toggle-track-on: var(--bv-color-primary);\n --bv-toggle-thumb: var(--bv-color-neutral-0);\n display: inline-flex;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host([size='sm']) {\n --bv-toggle-width: 32px;\n --bv-toggle-height: 18px;\n}\n\n.wrap {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n user-select: none;\n}\n\n:host([disabled]) .wrap {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.track {\n position: relative;\n width: var(--bv-toggle-width);\n height: var(--bv-toggle-height);\n border-radius: var(--bv-radius-full);\n background: var(--bv-toggle-track-off);\n transition: background var(--bv-transition-fast);\n flex-shrink: 0;\n}\n\n:host([checked]) .track {\n background: var(--bv-toggle-track-on);\n}\n\n.thumb {\n position: absolute;\n top: 3px;\n left: 3px;\n width: calc(var(--bv-toggle-height) - 6px);\n height: calc(var(--bv-toggle-height) - 6px);\n border-radius: 50%;\n background: var(--bv-toggle-thumb);\n box-shadow: var(--bv-shadow-sm);\n transition: transform var(--bv-transition-fast);\n}\n\n:host([checked]) .thumb {\n transform: translateX(calc(var(--bv-toggle-width) - var(--bv-toggle-height)));\n}\n\n.label {\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-800);\n line-height: 20px;\n}\n\n:host([size='sm']) .label {\n font-size: var(--bv-font-size-xs);\n line-height: 18px;\n}\n";
341
+ var bv_toggle_default = ":host {\n --bv-toggle-width: 44px;\n --bv-toggle-height: 24px;\n --bv-toggle-track-off: var(--bv-color-neutral-300);\n --bv-toggle-track-on: var(--bv-color-primary);\n --bv-toggle-thumb: var(--bv-color-neutral-0);\n display: inline-flex;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host([size='sm']) {\n --bv-toggle-width: 32px;\n --bv-toggle-height: 18px;\n}\n\n.wrap {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n user-select: none;\n border-radius: var(--bv-radius-sm);\n}\n\n.wrap:focus-visible {\n outline: 2px solid var(--bv-color-primary);\n outline-offset: 2px;\n}\n\n:host([disabled]) .wrap {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.track {\n position: relative;\n width: var(--bv-toggle-width);\n height: var(--bv-toggle-height);\n border-radius: var(--bv-radius-full);\n background: var(--bv-toggle-track-off);\n transition: background var(--bv-transition-fast);\n flex-shrink: 0;\n}\n\n:host([checked]) .track {\n background: var(--bv-toggle-track-on);\n}\n\n.thumb {\n position: absolute;\n top: 3px;\n left: 3px;\n width: calc(var(--bv-toggle-height) - 6px);\n height: calc(var(--bv-toggle-height) - 6px);\n border-radius: 50%;\n background: var(--bv-toggle-thumb);\n box-shadow: var(--bv-shadow-sm);\n transition: transform var(--bv-transition-fast);\n}\n\n:host([checked]) .thumb {\n transform: translateX(calc(var(--bv-toggle-width) - var(--bv-toggle-height)));\n}\n\n.label {\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-800);\n line-height: 20px;\n}\n\n:host([size='sm']) .label {\n font-size: var(--bv-font-size-xs);\n line-height: 18px;\n}\n";
340
342
 
341
343
  // components/bv-toggle/bv-toggle.ts
342
344
  var BvToggle = class extends HTMLElement {
343
345
  static observedAttributes = ["checked", "disabled", "label", "size"];
344
346
  _rendered = false;
347
+ _wrapEl = null;
345
348
  _labelEl = null;
346
349
  constructor() {
347
350
  super();
@@ -352,6 +355,7 @@ var BvToggle = class extends HTMLElement {
352
355
  }
353
356
  attributeChangedCallback(name, _old, val) {
354
357
  if (!this._rendered) return;
358
+ if (name === "checked" || name === "disabled") this._syncAria();
355
359
  if (name === "label" && this._labelEl) this._labelEl.textContent = val ?? "";
356
360
  }
357
361
  get checked() {
@@ -361,12 +365,32 @@ var BvToggle = class extends HTMLElement {
361
365
  if (v) this.setAttribute("checked", "");
362
366
  else this.removeAttribute("checked");
363
367
  }
368
+ /**
369
+ * Focus the toggle. The focusable element is the internal `.wrap`, not the
370
+ * host, so `hostEl.focus()` would otherwise be a silent no-op. Consumers that
371
+ * rebuild the panel a toggle lives in (bv-input-dropdown's `toggle-label`,
372
+ * bv-search-picker's `inactive-toggle-label`) need this to restore focus
373
+ * after the rebuild without reaching into this component's shadow root.
374
+ *
375
+ * No-op before the first render, and when disabled — `tabindex="-1"` only
376
+ * removes the element from Tab order, it does not block programmatic focus,
377
+ * so a restore pass could otherwise land focus on a control that was
378
+ * disabled mid-rebuild.
379
+ */
380
+ focus(options) {
381
+ var _a;
382
+ if (this.hasAttribute("disabled")) return;
383
+ (_a = this._wrapEl) == null ? void 0 : _a.focus(options);
384
+ }
364
385
  _render() {
365
386
  if (this._rendered) return;
366
387
  this._rendered = true;
367
388
  const shadow = this.shadowRoot;
368
- const wrap = document.createElement("label");
389
+ const wrap = document.createElement("div");
369
390
  wrap.className = "wrap";
391
+ wrap.setAttribute("role", "switch");
392
+ wrap.setAttribute("part", "toggle");
393
+ this._wrapEl = wrap;
370
394
  const track = document.createElement("span");
371
395
  track.className = "track";
372
396
  const thumb = document.createElement("span");
@@ -378,7 +402,7 @@ var BvToggle = class extends HTMLElement {
378
402
  const slot = document.createElement("slot");
379
403
  wrap.append(track, this._labelEl, slot);
380
404
  shadow.appendChild(wrap);
381
- wrap.addEventListener("click", () => {
405
+ const toggle = () => {
382
406
  if (this.hasAttribute("disabled")) return;
383
407
  this.checked = !this.checked;
384
408
  this.dispatchEvent(
@@ -388,7 +412,22 @@ var BvToggle = class extends HTMLElement {
388
412
  detail: { checked: this.checked }
389
413
  })
390
414
  );
415
+ };
416
+ wrap.addEventListener("click", toggle);
417
+ wrap.addEventListener("keydown", (e) => {
418
+ if (e.key !== "Enter" && e.key !== " ") return;
419
+ if (e.key === " ") e.preventDefault();
420
+ toggle();
391
421
  });
422
+ this._syncAria();
423
+ }
424
+ _syncAria() {
425
+ if (!this._wrapEl) return;
426
+ const disabled = this.hasAttribute("disabled");
427
+ this._wrapEl.tabIndex = disabled ? -1 : 0;
428
+ this._wrapEl.setAttribute("aria-checked", String(this.checked));
429
+ if (disabled) this._wrapEl.setAttribute("aria-disabled", "true");
430
+ else this._wrapEl.removeAttribute("aria-disabled");
392
431
  }
393
432
  };
394
433
  if (!customElements.get("bv-toggle")) {
@@ -527,6 +566,7 @@ if (!customElements.get("bv-button")) {
527
566
  // components/bv-search-picker/bv-search-picker.ts
528
567
  var SKELETON_ROW_COUNT = 5;
529
568
  var DEFAULT_DEBOUNCE_MS = 300;
569
+ var RESULT_ROW_ID_PREFIX = "bv-sp-opt-";
530
570
  function parseItems(raw) {
531
571
  if (!raw) return [];
532
572
  try {
@@ -601,6 +641,14 @@ var BvSearchPicker = class extends HTMLElement {
601
641
  * cleared when the user next opens the panel or explicitly dismisses.
602
642
  */
603
643
  _clearedReason = null;
644
+ /**
645
+ * BTN-11916 — roving-tabindex position in the basket. The basket is a
646
+ * composite widget: one tab stop for the whole group, Arrow keys to move
647
+ * between the remove buttons inside it. Without this, a basket of 40 picked
648
+ * users costs 40 tab presses to step over — and the basket is the *unbounded*
649
+ * list here, since the results list is capped by the consumer.
650
+ */
651
+ _basketActiveIdx = 0;
604
652
  _labelEl = null;
605
653
  _triggerEl = null;
606
654
  _panelEl = null;
@@ -801,6 +849,7 @@ var BvSearchPicker = class extends HTMLElement {
801
849
  pill.className = "trigger-pill";
802
850
  this._pillEl = pill;
803
851
  const pillText = document.createElement("span");
852
+ pillText.className = "trigger-pill-text";
804
853
  this._pillTextEl = pillText;
805
854
  const pillClear = document.createElement("span");
806
855
  pillClear.className = "trigger-pill-clear";
@@ -869,8 +918,7 @@ var BvSearchPicker = class extends HTMLElement {
869
918
  const firstRow = this._resultsRowsEl.querySelector(".result-row");
870
919
  if (!firstRow) return;
871
920
  e.preventDefault();
872
- this._resultsRowsEl.querySelectorAll(".result-row").forEach((row, i) => row.setAttribute("aria-selected", i === 0 ? "true" : "false"));
873
- firstRow.focus();
921
+ this._setActiveRow(0, true);
874
922
  });
875
923
  this._searchEl = searchEl;
876
924
  const searchWrap = document.createElement("div");
@@ -892,6 +940,12 @@ var BvSearchPicker = class extends HTMLElement {
892
940
  resultsRows.setAttribute("aria-label", `${this.entityLabel} matching your search`);
893
941
  resultsRows.tabIndex = 0;
894
942
  resultsRows.addEventListener("keydown", (e) => this._onResultsKeyDown(e));
943
+ resultsRows.addEventListener("focus", () => {
944
+ const rows = resultsRows.querySelectorAll(".result-row");
945
+ if (rows.length === 0) return;
946
+ const hasActive = Array.from(rows).some((r) => r.getAttribute("aria-selected") === "true");
947
+ if (!hasActive) this._setActiveRow(0, false);
948
+ });
895
949
  this._resultsRowsEl = resultsRows;
896
950
  const resultsEmpty = document.createElement("div");
897
951
  resultsEmpty.className = "results-empty";
@@ -913,6 +967,7 @@ var BvSearchPicker = class extends HTMLElement {
913
967
  basketHeader.append(basketHeaderLabel, basketClearAll);
914
968
  const basketList = document.createElement("div");
915
969
  basketList.className = "basket-list";
970
+ basketList.addEventListener("keydown", (e) => this._onBasketKeyDown(e));
916
971
  this._basketListEl = basketList;
917
972
  const basketEmpty = document.createElement("div");
918
973
  basketEmpty.className = "basket-empty";
@@ -1057,6 +1112,7 @@ var BvSearchPicker = class extends HTMLElement {
1057
1112
  else this._inactiveToggleEl.removeAttribute("checked");
1058
1113
  }
1059
1114
  _syncResults() {
1115
+ var _a;
1060
1116
  if (!this._resultsRowsEl || !this._resultsEmptyEl) return;
1061
1117
  this._searchPending = false;
1062
1118
  if (this._resultsListEl) {
@@ -1065,11 +1121,13 @@ var BvSearchPicker = class extends HTMLElement {
1065
1121
  const results = this.results;
1066
1122
  const stagedIds = new Set(this._stagedBasket.map((c) => c.id));
1067
1123
  this._resultsRowsEl.innerHTML = "";
1124
+ this._resultsRowsEl.removeAttribute("aria-activedescendant");
1068
1125
  for (const item of results) {
1069
1126
  if (stagedIds.has(item.id)) continue;
1070
1127
  const row = document.createElement("div");
1071
1128
  row.className = "result-row";
1072
1129
  row.dataset["id"] = item.id;
1130
+ row.id = `${RESULT_ROW_ID_PREFIX}${item.id}`;
1073
1131
  row.title = item.name;
1074
1132
  row.setAttribute("role", "option");
1075
1133
  row.setAttribute("aria-selected", "false");
@@ -1092,6 +1150,7 @@ var BvSearchPicker = class extends HTMLElement {
1092
1150
  row.addEventListener("click", () => this._addBasket(item));
1093
1151
  this._resultsRowsEl.appendChild(row);
1094
1152
  }
1153
+ if (((_a = this.shadowRoot) == null ? void 0 : _a.activeElement) === this._resultsRowsEl) this._setActiveRow(0, false);
1095
1154
  this._syncResultsEmptyText();
1096
1155
  this._syncResultsLimitNote();
1097
1156
  }
@@ -1156,7 +1215,11 @@ var BvSearchPicker = class extends HTMLElement {
1156
1215
  removeBtn.className = "basket-row-remove";
1157
1216
  removeBtn.setAttribute("aria-label", `Remove ${item.name}`);
1158
1217
  removeBtn.innerHTML = getIconSvg("x", 10);
1159
- removeBtn.addEventListener("click", () => this._removeBasket(item.id));
1218
+ removeBtn.addEventListener("click", (e) => {
1219
+ const idx = this._stagedBasket.findIndex((c) => c.id === item.id);
1220
+ this._removeBasket(item.id);
1221
+ if (e.detail === 0) this._setActiveBasketRow(idx, true);
1222
+ });
1160
1223
  row.append(nameEl, removeBtn);
1161
1224
  this._basketListEl.appendChild(row);
1162
1225
  }
@@ -1166,6 +1229,7 @@ var BvSearchPicker = class extends HTMLElement {
1166
1229
  { count: basket.length }
1167
1230
  );
1168
1231
  this._basketEmptyEl.hidden = basket.length > 0;
1232
+ this._setActiveBasketRow(this._basketActiveIdx, false);
1169
1233
  this._syncBasketRowColors();
1170
1234
  this._syncBasketHeaderLabel();
1171
1235
  this._syncBasketEmptyText();
@@ -1201,7 +1265,7 @@ var BvSearchPicker = class extends HTMLElement {
1201
1265
  );
1202
1266
  } else if (isExclude) {
1203
1267
  this._pillTextEl.textContent = this._interp(
1204
- this.getAttribute("label-except") ?? "All except {count}",
1268
+ this.getAttribute("label-except") ?? "{count} excluded",
1205
1269
  { count, entity }
1206
1270
  );
1207
1271
  } else {
@@ -1356,6 +1420,93 @@ var BvSearchPicker = class extends HTMLElement {
1356
1420
  this._syncResultsEmptyText();
1357
1421
  }, this.debounceMs);
1358
1422
  }
1423
+ /**
1424
+ * Makes one result row the active option. The single place that decides
1425
+ * which row Enter acts on, so the three entry points (ArrowDown out of the
1426
+ * search box, arrow keys inside the list, and Tab onto the list) cannot
1427
+ * drift apart.
1428
+ *
1429
+ * Sets three things together on purpose:
1430
+ * - `aria-selected` on the row — drives the visible highlight and tells AT
1431
+ * the option is the current one.
1432
+ * - `aria-activedescendant` on the listbox — the only way a screen reader
1433
+ * can know which option is active while focus sits on the container.
1434
+ * - DOM focus, when `moveFocus` is true. It is false for the Tab path: the
1435
+ * container is tabbable and precedes its rows, so focusing a row there
1436
+ * would bounce Shift+Tab back into the container's focus handler.
1437
+ */
1438
+ _setActiveRow(idx, moveFocus) {
1439
+ if (!this._resultsRowsEl) return;
1440
+ const rows = Array.from(this._resultsRowsEl.querySelectorAll(".result-row"));
1441
+ if (rows.length === 0) return;
1442
+ const bounded = Math.max(0, Math.min(idx, rows.length - 1));
1443
+ rows.forEach((row, i) => row.setAttribute("aria-selected", i === bounded ? "true" : "false"));
1444
+ const active = rows[bounded];
1445
+ if (!active) return;
1446
+ this._resultsRowsEl.setAttribute("aria-activedescendant", active.id);
1447
+ if (moveFocus) active.focus();
1448
+ }
1449
+ /**
1450
+ * BTN-11916 — the basket's counterpart to `_setActiveRow`, and deliberately
1451
+ * a different mechanism. The results list is a `role="listbox"`: one focus
1452
+ * holder, `aria-activedescendant` pointing at the active option. The basket
1453
+ * is not a listbox — nothing is being *chosen* there, each row carries its
1454
+ * own action — so it uses a roving tabindex over the native buttons instead,
1455
+ * which keeps their button semantics intact.
1456
+ *
1457
+ * Clamps, so callers may pass an index that has just gone out of range after
1458
+ * a removal. When the basket empties there is no button left to hold focus:
1459
+ * `moveFocus` then falls back to the search box rather than letting the
1460
+ * document drop focus to <body>.
1461
+ */
1462
+ _setActiveBasketRow(idx, moveFocus) {
1463
+ var _a, _b;
1464
+ if (!this._basketListEl) return;
1465
+ const btns = Array.from(
1466
+ this._basketListEl.querySelectorAll(".basket-row-remove")
1467
+ );
1468
+ if (btns.length === 0) {
1469
+ this._basketActiveIdx = 0;
1470
+ if (moveFocus) (_a = this._searchEl) == null ? void 0 : _a.focus();
1471
+ return;
1472
+ }
1473
+ const bounded = Math.max(0, Math.min(idx, btns.length - 1));
1474
+ this._basketActiveIdx = bounded;
1475
+ btns.forEach((btn, i) => {
1476
+ btn.tabIndex = i === bounded ? 0 : -1;
1477
+ });
1478
+ if (moveFocus) (_b = btns[bounded]) == null ? void 0 : _b.focus();
1479
+ }
1480
+ /**
1481
+ * BTN-11916 — Arrow Up/Down (plus Home/End) rove between the basket's remove
1482
+ * buttons. Enter and Space are NOT handled here on purpose: these are native
1483
+ * `<button>`s, so the browser already turns both into a click, and the click
1484
+ * handler owns both the removal and the follow-up focus move. Intercepting
1485
+ * them would mean re-implementing activation we get for free.
1486
+ */
1487
+ _onBasketKeyDown(e) {
1488
+ if (!this._basketListEl) return;
1489
+ const count = this._basketListEl.querySelectorAll(".basket-row-remove").length;
1490
+ if (count === 0) return;
1491
+ switch (e.key) {
1492
+ case "ArrowDown":
1493
+ e.preventDefault();
1494
+ this._setActiveBasketRow(this._basketActiveIdx + 1, true);
1495
+ break;
1496
+ case "ArrowUp":
1497
+ e.preventDefault();
1498
+ this._setActiveBasketRow(this._basketActiveIdx - 1, true);
1499
+ break;
1500
+ case "Home":
1501
+ e.preventDefault();
1502
+ this._setActiveBasketRow(0, true);
1503
+ break;
1504
+ case "End":
1505
+ e.preventDefault();
1506
+ this._setActiveBasketRow(count - 1, true);
1507
+ break;
1508
+ }
1509
+ }
1359
1510
  /**
1360
1511
  * BTN-10322 — Arrow Up/Down navigation between result rows; Enter or Space
1361
1512
  * adds the currently-focused row to the staged basket. Home/End jump to
@@ -1367,17 +1518,12 @@ var BvSearchPicker = class extends HTMLElement {
1367
1518
  * which then removes the row from the results list.
1368
1519
  */
1369
1520
  _onResultsKeyDown(e) {
1370
- var _a;
1521
+ var _a, _b, _c;
1371
1522
  if (!this._resultsRowsEl) return;
1372
1523
  const rows = Array.from(this._resultsRowsEl.querySelectorAll(".result-row"));
1373
1524
  if (rows.length === 0) return;
1374
1525
  const currentIdx = rows.findIndex((row) => row.getAttribute("aria-selected") === "true");
1375
- const focusRow = (idx) => {
1376
- var _a2;
1377
- const bounded = Math.max(0, Math.min(idx, rows.length - 1));
1378
- rows.forEach((row, i) => row.setAttribute("aria-selected", i === bounded ? "true" : "false"));
1379
- (_a2 = rows[bounded]) == null ? void 0 : _a2.focus();
1380
- };
1526
+ const focusRow = (idx) => this._setActiveRow(idx, true);
1381
1527
  switch (e.key) {
1382
1528
  case "ArrowDown":
1383
1529
  e.preventDefault();
@@ -1402,7 +1548,13 @@ var BvSearchPicker = class extends HTMLElement {
1402
1548
  const focusedId = (_a = rows[currentIdx]) == null ? void 0 : _a.dataset["id"];
1403
1549
  if (!focusedId) return;
1404
1550
  const item = this.results.find((r) => r.id === focusedId);
1405
- if (item) this._addBasket(item);
1551
+ if (!item) return;
1552
+ this._addBasket(item);
1553
+ if ((_b = this._resultsRowsEl) == null ? void 0 : _b.querySelector(".result-row")) {
1554
+ this._setActiveRow(currentIdx, true);
1555
+ } else {
1556
+ (_c = this._searchEl) == null ? void 0 : _c.focus();
1557
+ }
1406
1558
  break;
1407
1559
  }
1408
1560
  }
@@ -8,6 +8,19 @@ export interface SegmentedControlChangeDetail {
8
8
  value: string;
9
9
  label: string;
10
10
  }
11
+ /**
12
+ * Public CSS custom property (BTN-10686):
13
+ *
14
+ * - `--bv-segmented-control-pill-padding-x` — horizontal padding of each option
15
+ * pill, independent of `size`. Use it when a control needs to be narrower
16
+ * while staying the same height as its neighbours in a toolbar row;
17
+ * `size="sm"` would shrink the height too. Honoured by both sizes, each
18
+ * falling back to its own default: `var(--bv-spacing-md)` at the default
19
+ * size, `var(--bv-spacing-md-minus)` at `size="sm"`.
20
+ *
21
+ * Consumer-facing theming API — renaming or removing it is a major bump per
22
+ * the Consumer Contract.
23
+ */
11
24
  export declare class BvSegmentedControl extends HTMLElement {
12
25
  static readonly observedAttributes: readonly ["options", "value", "label", "required", "size", "variant"];
13
26
  private _rendered;
@@ -1,5 +1,5 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-segmented-control/bv-segmented-control.css
2
- var bv_segmented_control_default = ":host {\n display: block;\n font-family: var(--bv-font-family-base);\n}\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n line-height: 20px;\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n margin-bottom: 6px;\n}\n\n.field-label[hidden] {\n display: none;\n}\n\n.required-mark {\n color: var(--bv-color-danger);\n margin-left: 2px;\n}\n\n.container {\n display: flex;\n align-items: center;\n height: 44px;\n box-sizing: border-box;\n background: var(--bv-color-neutral-100);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n padding: 3px;\n gap: 2px;\n}\n\n:host([size='sm']) .container {\n height: var(--bv-control-height-md);\n border-radius: var(--bv-radius-md);\n padding: 3px;\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n padding: 0 var(--bv-spacing-md);\n border: none;\n border-radius: calc(var(--bv-radius-lg) - 3px);\n background: transparent;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-500);\n cursor: pointer;\n white-space: nowrap;\n user-select: none;\n transition:\n color var(--bv-transition-fast),\n background var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n:host([size='sm']) .pill {\n padding: 0 var(--bv-spacing-md-minus);\n font-size: var(--bv-font-size-sm);\n}\n\n.pill:hover:not(.selected) {\n color: var(--bv-color-neutral-800);\n}\n\n.pill.selected {\n background: var(--bv-color-neutral-0);\n color: var(--bv-color-neutral-900);\n box-shadow: var(--bv-shadow-sm);\n}\n\n/* Filled variant \u2014 selected pill uses the primary color instead of white */\n:host([variant='primary']) .pill.selected {\n background: var(--bv-color-primary);\n color: var(--bv-color-neutral-0);\n}\n";
2
+ var bv_segmented_control_default = ":host {\n display: block;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n line-height: 20px;\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n margin-bottom: 6px;\n}\n\n.field-label[hidden] {\n display: none;\n}\n\n.required-mark {\n color: var(--bv-color-danger);\n margin-left: 2px;\n}\n\n.container {\n display: flex;\n align-items: center;\n height: 44px;\n box-sizing: border-box;\n background: var(--bv-color-neutral-100);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n padding: 3px;\n gap: 2px;\n}\n\n:host([size='sm']) .container {\n height: var(--bv-control-height-md);\n border-radius: var(--bv-radius-md);\n padding: 3px;\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n /* Horizontal-only override, independent of `size` \u2014 a consumer fighting\n for width in a row of same-height controls needs the pill narrower\n without the control itself getting shorter than its neighbors, which\n `size=\"sm\"` would also do (it shrinks the container height too). */\n padding: 0 var(--bv-segmented-control-pill-padding-x, var(--bv-spacing-md));\n border: none;\n border-radius: calc(var(--bv-radius-lg) - 3px);\n background: transparent;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-500);\n cursor: pointer;\n white-space: nowrap;\n user-select: none;\n transition:\n color var(--bv-transition-fast),\n background var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n:host([size='sm']) .pill {\n /* Same override hook as the default size, with sm's own tighter fallback \u2014\n otherwise the custom property would silently do nothing on size=\"sm\",\n which is exactly the combination a consumer squeezed for width reaches\n for first. */\n padding: 0 var(--bv-segmented-control-pill-padding-x, var(--bv-spacing-md-minus));\n font-size: var(--bv-font-size-sm);\n}\n\n.pill:hover:not(.selected) {\n color: var(--bv-color-neutral-800);\n}\n\n.pill.selected {\n background: var(--bv-color-neutral-0);\n color: var(--bv-color-neutral-900);\n box-shadow: var(--bv-shadow-sm);\n}\n\n/* Filled variant \u2014 selected pill uses the primary color instead of white */\n:host([variant='primary']) .pill.selected {\n background: var(--bv-color-primary);\n color: var(--bv-color-neutral-0);\n}\n\n/* These elements have an author `display`, which beats the user-agent\n `[hidden] { display: none }` regardless of specificity. The component\n toggles their `hidden`, so without this the property changes nothing on\n screen (BTN-11521). */\n.field-label[hidden] {\n display: none;\n}\n";
3
3
 
4
4
  // components/_shared/adopt-styles.ts
5
5
  var _sheetCache = /* @__PURE__ */ new Map();
@@ -1,5 +1,5 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-select/bv-select.css
2
- var bv_select_default = ":host {\n display: block;\n position: relative;\n font-family: var(--bv-font-family-base);\n}\n\n/* \u2500\u2500 Label \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n margin-bottom: 6px;\n}\n\n.required-mark {\n color: var(--bv-color-danger);\n margin-left: 2px;\n}\n\n/* \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: 44px;\n padding: 0 var(--bv-spacing-md);\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-lg);\n cursor: pointer;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-800);\n text-align: left;\n transition:\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n.trigger:focus-visible {\n outline: none;\n border-color: var(--bv-color-primary);\n box-shadow:\n 0 0 0 3px var(--bv-color-primary-light),\n 0 1px 2px 0 rgba(16, 24, 40, 0.05);\n}\n\n:host([open]) .trigger {\n border-color: var(--bv-color-primary);\n box-shadow:\n 0 0 0 3px var(--bv-color-primary-light),\n 0 1px 2px 0 rgba(16, 24, 40, 0.05);\n}\n\n:host([error]:not([error=''])) .trigger {\n border-color: var(--bv-color-danger);\n}\n\n.trigger:disabled {\n background: var(--bv-color-neutral-100);\n color: var(--bv-color-neutral-400);\n cursor: not-allowed;\n}\n\n.trigger-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.trigger-label.is-placeholder {\n color: var(--bv-color-neutral-400);\n}\n\n.trigger-chevron {\n display: flex;\n color: var(--bv-color-neutral-500);\n flex-shrink: 0;\n margin-left: var(--bv-spacing-sm);\n transition: transform var(--bv-transition-fast);\n}\n\n:host([open]) .trigger-chevron {\n transform: rotate(180deg);\n}\n\n/* \u2500\u2500 Dropdown panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.panel {\n display: none;\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n box-shadow: var(--bv-shadow-md);\n z-index: 200;\n overflow: hidden;\n padding: var(--bv-spacing-xs) 0;\n}\n\n:host([open]) .panel {\n display: block;\n}\n\n/* \u2500\u2500 Options \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.option {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--bv-spacing-sm);\n padding: 10px var(--bv-spacing-md);\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-700);\n cursor: pointer;\n transition: background var(--bv-transition-fast);\n}\n\n.option:hover {\n background: var(--bv-color-secondary);\n}\n\n.option[aria-selected='true'] {\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-900);\n background: var(--bv-color-secondary-light);\n}\n\n.option-text {\n flex: 1;\n}\n\n.option-check {\n display: none;\n color: var(--bv-color-primary);\n flex-shrink: 0;\n}\n\n.option[aria-selected='true'] .option-check {\n display: flex;\n}\n\n/* \u2500\u2500 Error message \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.field-error {\n display: block;\n font-size: var(--bv-font-size-xs);\n color: var(--bv-color-danger);\n margin-top: var(--bv-spacing-xs);\n}\n";
2
+ var bv_select_default = ":host {\n display: block;\n position: relative;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n/* \u2500\u2500 Label \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n margin-bottom: 6px;\n}\n\n/* Author `display: block` above beats the user-agent `[hidden] { display:\n none }`, so `_syncLabel()` setting `.hidden` did nothing on screen. With no\n label text the element collapses to 0px on its own, which is why this went\n unnoticed - but `required` appends an asterisk after the text is cleared, so\n a required field with no label rendered a stray \"*\" above the control\n (BTN-11521). */\n.field-label[hidden] {\n display: none;\n}\n\n.required-mark {\n color: var(--bv-color-danger);\n margin-left: 2px;\n}\n\n/* \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: 44px;\n padding: 0 var(--bv-spacing-md);\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-lg);\n cursor: pointer;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-800);\n text-align: left;\n transition:\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n.trigger:focus-visible {\n outline: none;\n border-color: var(--bv-color-primary);\n box-shadow:\n 0 0 0 3px var(--bv-color-primary-light),\n 0 1px 2px 0 rgba(16, 24, 40, 0.05);\n}\n\n:host([open]) .trigger {\n border-color: var(--bv-color-primary);\n box-shadow:\n 0 0 0 3px var(--bv-color-primary-light),\n 0 1px 2px 0 rgba(16, 24, 40, 0.05);\n}\n\n:host([error]:not([error=''])) .trigger {\n border-color: var(--bv-color-danger);\n}\n\n.trigger:disabled {\n background: var(--bv-color-neutral-100);\n color: var(--bv-color-neutral-400);\n cursor: not-allowed;\n}\n\n.trigger-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.trigger-label.is-placeholder {\n color: var(--bv-color-neutral-400);\n}\n\n.trigger-chevron {\n display: flex;\n color: var(--bv-color-neutral-500);\n flex-shrink: 0;\n margin-left: var(--bv-spacing-sm);\n transition: transform var(--bv-transition-fast);\n}\n\n:host([open]) .trigger-chevron {\n transform: rotate(180deg);\n}\n\n/* \u2500\u2500 Dropdown panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.panel {\n display: none;\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n box-shadow: var(--bv-shadow-md);\n z-index: 200;\n overflow: hidden;\n padding: var(--bv-spacing-xs) 0;\n}\n\n:host([open]) .panel {\n display: block;\n}\n\n/* \u2500\u2500 Options \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.option {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--bv-spacing-sm);\n padding: 10px var(--bv-spacing-md);\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-700);\n cursor: pointer;\n transition: background var(--bv-transition-fast);\n}\n\n.option:hover {\n background: var(--bv-color-secondary);\n}\n\n.option[aria-selected='true'] {\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-900);\n background: var(--bv-color-secondary-light);\n}\n\n.option-text {\n flex: 1;\n}\n\n.option-check {\n display: none;\n color: var(--bv-color-primary);\n flex-shrink: 0;\n}\n\n.option[aria-selected='true'] .option-check {\n display: flex;\n}\n\n/* \u2500\u2500 Error message \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.field-error {\n display: block;\n font-size: var(--bv-font-size-xs);\n color: var(--bv-color-danger);\n margin-top: var(--bv-spacing-xs);\n}\n\n/* These elements have an author `display`, which beats the user-agent\n `[hidden] { display: none }` regardless of specificity. The component\n toggles their `hidden`, so without this the property changes nothing on\n screen (BTN-11521). */\n.field-error[hidden] {\n display: none;\n}\n";
3
3
 
4
4
  // components/_shared/adopt-styles.ts
5
5
  var _sheetCache = /* @__PURE__ */ new Map();
@@ -78,7 +78,7 @@ function bindDropdownController(host, options = {}) {
78
78
  }
79
79
 
80
80
  // components/bv-icon/icons.ts
81
- var icons = {
81
+ var icons = Object.assign(/* @__PURE__ */ Object.create(null), {
82
82
  // Navigation
83
83
  "chevron-up": `<path d="M18 15l-6-6-6 6"/>`,
84
84
  "chevron-down": `<path d="M6 9l6 6 6-6"/>`,
@@ -129,16 +129,16 @@ var icons = {
129
129
  bell: `<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/>`,
130
130
  mail: `<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/>`,
131
131
  link: `<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>`
132
- };
132
+ });
133
133
  function getIconSvg(name, size = 16) {
134
- const raw = rawIcons[name];
134
+ const raw = RAW_ICON_MAP.get(name);
135
135
  if (raw)
136
136
  return raw.replace(/width="[^"]*"/, `width="${size}"`).replace(/height="[^"]*"/, `height="${size}"`);
137
- const paths = icons[name];
137
+ const paths = ICON_MAP.get(name);
138
138
  if (!paths) return "";
139
139
  return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${paths}</svg>`;
140
140
  }
141
- var rawIcons = {
141
+ var rawIcons = Object.assign(/* @__PURE__ */ Object.create(null), {
142
142
  // Module type (small, ~18px)
143
143
  "module-scorm": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 15.03 16.28" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13.9014 4.60034L7.51368 8.14201M7.51368 8.14201L1.126 4.60034M7.51368 8.14201L7.5137 15.267M14.2771 11.1859V5.09812C14.2771 4.84113 14.2771 4.71264 14.2392 4.59804C14.2056 4.49666 14.1508 4.4036 14.0783 4.32508C13.9963 4.23633 13.8838 4.17393 13.6587 4.04913L8.09763 0.965793C7.88451 0.847624 7.77794 0.78854 7.66509 0.765376C7.56521 0.744875 7.46219 0.744875 7.36231 0.765376C7.24946 0.78854 7.1429 0.847624 6.92977 0.965793L1.36873 4.04913C1.14364 4.17393 1.0311 4.23633 0.949147 4.32508C0.876647 4.4036 0.82178 4.49666 0.788217 4.59804C0.750278 4.71264 0.750278 4.84113 0.750278 5.09812V11.1859C0.750278 11.4429 0.750278 11.5714 0.788217 11.686C0.82178 11.7874 0.876647 11.8805 0.949147 11.959C1.0311 12.0477 1.14364 12.1101 1.36873 12.2349L6.92977 15.3183C7.1429 15.4364 7.24946 15.4955 7.36231 15.5187C7.46219 15.5392 7.56521 15.5392 7.66509 15.5187C7.77794 15.4955 7.88451 15.4364 8.09763 15.3183L13.6587 12.2349C13.8838 12.1101 13.9963 12.0477 14.0783 11.959C14.1508 11.8805 14.2056 11.7874 14.2392 11.686C14.2771 11.5714 14.2771 11.4429 14.2771 11.1859Z"/></svg>`,
144
144
  "module-assessment": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 13.72 16.13" fill="none" stroke="currentColor" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12.507 6.1875V4.1625C12.507 2.90238 12.507 2.27232 12.2629 1.79102C12.0482 1.36766 11.7056 1.02345 11.2841 0.807736C10.8051 0.5625 10.1779 0.5625 8.92364 0.5625H4.14585C2.89156 0.5625 2.26441 0.5625 1.78534 0.807736C1.36393 1.02345 1.02132 1.36766 0.806601 1.79102C0.5625 2.27232 0.5625 2.90238 0.5625 4.1625V11.9625C0.5625 13.2226 0.5625 13.8527 0.806601 14.334C1.02132 14.7573 1.36393 15.1015 1.78534 15.3173C2.26441 15.5625 2.89156 15.5625 4.14585 15.5625H8.0278M8.0278 7.3125H3.54862M5.04168 10.3125H3.54862M9.52086 4.3125H3.54862M9.89413 10.3142C10.0257 9.93852 10.2853 9.62175 10.627 9.41998C10.9688 9.21821 11.3705 9.14445 11.7612 9.21178C12.1519 9.2791 12.5062 9.48315 12.7615 9.7878C13.0168 10.0925 13.1565 10.478 13.1559 10.8763C13.1559 12.0004 11.4775 12.5625 11.4775 12.5625M11.4991 14.8125H11.5066"/></svg>`,
@@ -148,7 +148,9 @@ var rawIcons = {
148
148
  "module-adobe-connect": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 16.06 14.63" fill="none" stroke="currentColor" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11.7605 0.56252L8.0278 3.56252L4.29515 0.56252M4.14585 14.0625H11.9098C13.164 14.0625 13.7912 14.0625 14.2703 13.8173C14.6917 13.6016 15.0343 13.2574 15.249 12.834C15.4931 12.3527 15.4931 11.7226 15.4931 10.4625V7.16252C15.4931 5.9024 15.4931 5.27234 15.249 4.79104C15.0343 4.36768 14.6917 4.02347 14.2703 3.80776C13.7912 3.56252 13.164 3.56252 11.9098 3.56252H4.14585C2.89156 3.56252 2.26441 3.56252 1.78534 3.80776C1.36393 4.02347 1.02132 4.36768 0.806601 4.79104C0.5625 5.27234 0.5625 5.9024 0.5625 7.16252V10.4625C0.5625 11.7226 0.5625 12.3527 0.806601 12.834C1.02132 13.2574 1.36393 13.6016 1.78534 13.8173C2.26441 14.0625 2.89156 14.0625 4.14585 14.0625Z"/></svg>`,
149
149
  "module-video": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 16.06 11.63" fill="none" stroke="currentColor" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15.4931 3.51103C15.4931 3.05667 15.4931 2.82949 15.4037 2.72429C15.3261 2.63301 15.2097 2.58457 15.0906 2.59399C14.9533 2.60484 14.7934 2.76548 14.4736 3.08676L11.7605 5.8125L14.4736 8.53824C14.7934 8.85952 14.9533 9.02016 15.0906 9.03101C15.2097 9.04043 15.3261 8.99199 15.4037 8.90071C15.4931 8.79552 15.4931 8.56833 15.4931 8.11397V3.51103ZM0.5625 4.1625C0.5625 2.90238 0.5625 2.27232 0.806601 1.79102C1.02132 1.36766 1.36393 1.02345 1.78534 0.807736C2.26441 0.5625 2.89156 0.5625 4.14585 0.5625H8.17711C9.4314 0.5625 10.0585 0.5625 10.5376 0.807736C10.959 1.02345 11.3016 1.36766 11.5164 1.79102C11.7605 2.27232 11.7605 2.90238 11.7605 4.1625V7.4625C11.7605 8.72262 11.7605 9.35268 11.5164 9.83398C11.3016 10.2573 10.959 10.6015 10.5376 10.8173C10.0585 11.0625 9.4314 11.0625 8.17711 11.0625H4.14584C2.89156 11.0625 2.26441 11.0625 1.78534 10.8173C1.36393 10.6015 1.02132 10.2573 0.806601 9.83398C0.5625 9.35268 0.5625 8.72262 0.5625 7.4625V4.1625Z"/></svg>`,
150
150
  "module-upload": `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 14.75 16.13" fill="none" stroke="currentColor" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13.39 4.3125V4.1625C13.39 2.90238 13.39 2.27232 13.1278 1.79102C12.8972 1.36766 12.5293 1.02345 12.0767 0.807736C11.5622 0.5625 10.8887 0.5625 9.54172 0.5625H4.41074C3.06373 0.5625 2.39022 0.5625 1.87573 0.807736C1.42318 1.02345 1.05524 1.36766 0.824646 1.79102C0.5625 2.27232 0.5625 2.90238 0.5625 4.1625V11.9625C0.5625 13.2226 0.5625 13.8527 0.824646 14.334C1.05524 14.7573 1.42318 15.1015 1.87573 15.3173C2.39022 15.5625 3.06373 15.5625 4.41074 15.5625H7.37709M7.37709 7.3125H3.76936M6.57537 10.3125H3.76936M10.1831 4.3125H3.76936M11.7865 12.5625V8.4375C11.7865 7.81618 12.3249 7.3125 12.9891 7.3125C13.6533 7.3125 14.1917 7.81618 14.1917 8.4375V12.5625C14.1917 13.8051 13.1149 14.8125 11.7865 14.8125C10.4582 14.8125 9.38138 13.8051 9.38138 12.5625V9.5625"/></svg>`
151
- };
151
+ });
152
+ var RAW_ICON_MAP = new Map(Object.entries(rawIcons));
153
+ var ICON_MAP = new Map(Object.entries(icons));
152
154
 
153
155
  // components/bv-split-button/bv-split-button.ts
154
156
  var CHEVRON_DOWN = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>`;
@@ -1,5 +1,5 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-star-rating/bv-star-rating.css
2
- var bv_star_rating_default = ":host {\n --bv-star-color: #f59e0b;\n --bv-star-empty-color: var(--bv-color-neutral-200);\n --bv-star-size: 20px;\n display: inline-flex;\n}\n\n:host([size='sm']) {\n --bv-star-size: 14px;\n}\n:host([size='lg']) {\n --bv-star-size: 28px;\n}\n\n.stars {\n display: inline-flex;\n gap: 2px;\n align-items: center;\n}\n\n.star {\n width: var(--bv-star-size);\n height: var(--bv-star-size);\n color: var(--bv-star-empty-color);\n flex-shrink: 0;\n transition: color var(--bv-transition-fast);\n}\n\n.star.filled {\n color: var(--bv-star-color);\n}\n";
2
+ var bv_star_rating_default = ":host {\n --bv-star-color: #f59e0b;\n --bv-star-empty-color: var(--bv-color-neutral-200);\n --bv-star-size: 20px;\n display: inline-flex;\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host([size='sm']) {\n --bv-star-size: 14px;\n}\n:host([size='lg']) {\n --bv-star-size: 28px;\n}\n\n.stars {\n display: inline-flex;\n gap: 2px;\n align-items: center;\n}\n\n.star {\n width: var(--bv-star-size);\n height: var(--bv-star-size);\n color: var(--bv-star-empty-color);\n flex-shrink: 0;\n transition: color var(--bv-transition-fast);\n}\n\n.star.filled {\n color: var(--bv-star-color);\n}\n";
3
3
 
4
4
  // components/_shared/adopt-styles.ts
5
5
  var _sheetCache = /* @__PURE__ */ new Map();