@bluevolt-tech/lumen 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +37 -23
  2. package/dist/components/_shared/adopt-styles.d.ts +8 -0
  3. package/dist/components/_shared/date-range-validator.d.ts +86 -0
  4. package/dist/components/_shared/dropdown-controller.d.ts +60 -0
  5. package/dist/components/_shared/selectable-card.d.ts +10 -0
  6. package/dist/components/bv-alert-banner/bv-alert-banner.js +19 -17
  7. package/dist/components/bv-avatar/bv-avatar.js +19 -11
  8. package/dist/components/bv-badge/bv-badge.js +19 -11
  9. package/dist/components/bv-button/bv-button.js +18 -16
  10. package/dist/components/bv-category-pill/bv-category-pill.js +18 -16
  11. package/dist/components/bv-checkbox/bv-checkbox.js +19 -11
  12. package/dist/components/bv-chip/bv-chip.js +19 -11
  13. package/dist/components/bv-course-detail/bv-course-detail.js +20 -34
  14. package/dist/components/bv-course-detail-modal/bv-course-detail-modal.js +24 -90
  15. package/dist/components/bv-course-grid-card/bv-course-grid-card.d.ts +2 -6
  16. package/dist/components/bv-course-grid-card/bv-course-grid-card.js +98 -105
  17. package/dist/components/bv-course-list-card/bv-course-list-card.d.ts +2 -6
  18. package/dist/components/bv-course-list-card/bv-course-list-card.js +98 -105
  19. package/dist/components/bv-course-outline/bv-course-outline.js +19 -11
  20. package/dist/components/bv-date-range-input/bv-date-range-input.d.ts +10 -6
  21. package/dist/components/bv-date-range-input/bv-date-range-input.js +602 -125
  22. package/dist/components/bv-date-range-picker/bv-date-range-picker.d.ts +71 -4
  23. package/dist/components/bv-date-range-picker/bv-date-range-picker.js +441 -76
  24. package/dist/components/bv-empty-state/bv-empty-state.js +20 -28
  25. package/dist/components/bv-filter-dropdown/bv-filter-dropdown.d.ts +1 -4
  26. package/dist/components/bv-filter-dropdown/bv-filter-dropdown.js +80 -53
  27. package/dist/components/bv-filter-panel/bv-filter-panel.js +20 -22
  28. package/dist/components/bv-icon/bv-icon.js +19 -11
  29. package/dist/components/bv-input/bv-input.js +18 -16
  30. package/dist/components/bv-input-dropdown/bv-input-dropdown.d.ts +1 -4
  31. package/dist/components/bv-input-dropdown/bv-input-dropdown.js +79 -78
  32. package/dist/components/bv-modal/bv-modal.js +19 -11
  33. package/dist/components/bv-page-title/bv-page-title.js +19 -6
  34. package/dist/components/bv-pagination/bv-pagination.d.ts +1 -0
  35. package/dist/components/bv-pagination/bv-pagination.js +23 -186
  36. package/dist/components/bv-portal-header/bv-portal-header.js +25 -83
  37. package/dist/components/bv-portal-layout/bv-portal-layout.js +19 -11
  38. package/dist/components/bv-progress-bar/bv-progress-bar.js +19 -11
  39. package/dist/components/bv-promo-banner/bv-promo-banner.js +19 -11
  40. package/dist/components/bv-radio/bv-radio.js +19 -11
  41. package/dist/components/bv-searchbox/bv-searchbox.js +19 -11
  42. package/dist/components/bv-segmented-control/bv-segmented-control.js +18 -16
  43. package/dist/components/bv-select/bv-select.d.ts +1 -4
  44. package/dist/components/bv-select/bv-select.js +78 -44
  45. package/dist/components/bv-split-button/bv-split-button.d.ts +1 -4
  46. package/dist/components/bv-split-button/bv-split-button.js +78 -42
  47. package/dist/components/bv-star-rating/bv-star-rating.js +19 -11
  48. package/dist/components/bv-table/bv-table.d.ts +5 -0
  49. package/dist/components/bv-table/bv-table.js +70 -19
  50. package/dist/components/bv-toggle/bv-toggle.js +19 -11
  51. package/dist/components/bv-tooltip/bv-tooltip.js +20 -17
  52. package/dist/components/bv-user-row/bv-user-row.js +22 -50
  53. package/dist/components/bv-view-switcher/bv-view-switcher.js +19 -11
  54. package/dist/themes/base.css +1 -1
  55. package/package.json +8 -1
  56. package/themes/base.css +1 -1
@@ -1,6 +1,24 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-chip/bv-chip.css
2
2
  var bv_chip_default = ":host {\n display: inline-flex;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 28px;\n padding: 0 10px 0 12px;\n border-radius: var(--bv-radius-md, 6px);\n background: var(--bv-color-primary-50, #eff8ff);\n border: 1px solid #b9e6fe;\n color: var(--bv-color-primary-dark, #026aa2);\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-medium);\n line-height: 1;\n white-space: nowrap;\n user-select: none;\n}\n\n.label {\n flex: none;\n}\n\n.dismiss {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n padding: 0;\n background: none;\n border: none;\n cursor: pointer;\n color: inherit;\n flex-shrink: 0;\n opacity: 0.6;\n border-radius: 2px;\n transition: opacity var(--bv-transition-fast, 150ms);\n}\n\n.dismiss:hover {\n opacity: 1;\n}\n\n.dismiss:focus-visible {\n outline: 2px solid var(--bv-color-primary);\n outline-offset: 1px;\n}\n";
3
3
 
4
+ // components/_shared/adopt-styles.ts
5
+ var _sheetCache = /* @__PURE__ */ new Map();
6
+ function adoptStyles(shadow, css) {
7
+ if ("adoptedStyleSheets" in ShadowRoot.prototype && typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
8
+ let sheet = _sheetCache.get(css);
9
+ if (!sheet) {
10
+ sheet = new CSSStyleSheet();
11
+ sheet.replaceSync(css);
12
+ _sheetCache.set(css, sheet);
13
+ }
14
+ shadow.adoptedStyleSheets = [sheet];
15
+ return;
16
+ }
17
+ const style = document.createElement("style");
18
+ style.textContent = css;
19
+ shadow.appendChild(style);
20
+ }
21
+
4
22
  // components/bv-chip/bv-chip.ts
5
23
  var BvChip = class extends HTMLElement {
6
24
  static observedAttributes = ["label"];
@@ -14,12 +32,7 @@ var BvChip = class extends HTMLElement {
14
32
  _labelEl = null;
15
33
  constructor() {
16
34
  super();
17
- this.attachShadow({ mode: "open" });
18
- if ("replaceSync" in CSSStyleSheet.prototype) {
19
- const sheet = new CSSStyleSheet();
20
- sheet.replaceSync(bv_chip_default);
21
- this.shadowRoot.adoptedStyleSheets = [sheet];
22
- }
35
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_chip_default);
23
36
  }
24
37
  connectedCallback() {
25
38
  this._render();
@@ -34,11 +47,6 @@ var BvChip = class extends HTMLElement {
34
47
  if (this._rendered) return;
35
48
  this._rendered = true;
36
49
  const shadow = this.shadowRoot;
37
- if (!shadow.adoptedStyleSheets.length) {
38
- const s = document.createElement("style");
39
- s.textContent = bv_chip_default;
40
- shadow.appendChild(s);
41
- }
42
50
  const chip = document.createElement("span");
43
51
  chip.className = "chip";
44
52
  const labelEl = document.createElement("span");
@@ -1,28 +1,35 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-course-detail/bv-course-detail.css
2
2
  var bv_course_detail_default = ":host {\n display: block;\n font-family: var(--bv-font-family-base);\n}\n\n[hidden] {\n display: none !important;\n}\n\n/* \u2500\u2500 Root layout \u2500\u2500 */\n\n.course-detail {\n display: flex;\n gap: 20px;\n align-items: flex-start;\n}\n\n/* \u2500\u2500 Thumbnail column \u2500\u2500 */\n\n.thumb-col {\n flex-shrink: 0;\n width: 160px;\n}\n\n.thumb-wrap {\n width: 160px;\n height: 113px;\n background: var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n overflow: hidden;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.thumb-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.thumb-placeholder {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n}\n\n.thumb-placeholder svg {\n width: 100%;\n height: 100%;\n}\n\n/* \u2500\u2500 Right column \u2500\u2500 */\n\n.right-col {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* \u2500\u2500 Top row: pills + title + separator \u2500\u2500 */\n\n.top-row {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.card-header {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.pills-row {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.course-title {\n font-size: var(--bv-font-size-xl);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-900);\n line-height: 32px;\n}\n\n.separator {\n height: 0;\n border-top: 0.5px solid var(--bv-color-neutral-300);\n}\n\n/* \u2500\u2500 Description \u2500\u2500 */\n\n.desc-section {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.desc-text {\n margin: 0;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 20px;\n display: -webkit-box;\n -webkit-line-clamp: 6;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* Read More expands the clamp */\n.desc-wrap--expanded .desc-text {\n -webkit-line-clamp: unset;\n}\n\n.read-more-btn {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-primary);\n line-height: 24px;\n white-space: nowrap;\n text-align: left;\n}\n\n.read-more-btn:hover {\n text-decoration: underline;\n}\n";
3
3
 
4
+ // components/_shared/adopt-styles.ts
5
+ var _sheetCache = /* @__PURE__ */ new Map();
6
+ function adoptStyles(shadow, css) {
7
+ if ("adoptedStyleSheets" in ShadowRoot.prototype && typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
8
+ let sheet = _sheetCache.get(css);
9
+ if (!sheet) {
10
+ sheet = new CSSStyleSheet();
11
+ sheet.replaceSync(css);
12
+ _sheetCache.set(css, sheet);
13
+ }
14
+ shadow.adoptedStyleSheets = [sheet];
15
+ return;
16
+ }
17
+ const style = document.createElement("style");
18
+ style.textContent = css;
19
+ shadow.appendChild(style);
20
+ }
21
+
4
22
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-category-pill/bv-category-pill.css
5
23
  var bv_category_pill_default = ":host {\n display: inline-flex;\n font-family: var(--bv-font-family-base);\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 6px;\n border: 0.5px solid var(--bv-color-neutral-900);\n border-radius: var(--bv-radius-sm);\n font-size: 10px;\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 1;\n white-space: nowrap;\n}\n";
6
24
 
7
25
  // components/bv-category-pill/bv-category-pill.ts
8
- var _sheet = null;
9
- function getSheet() {
10
- if (!_sheet) {
11
- _sheet = new CSSStyleSheet();
12
- _sheet.replaceSync(bv_category_pill_default);
13
- }
14
- return _sheet;
15
- }
16
26
  var BvCategoryPill = class extends HTMLElement {
17
27
  static observedAttributes = ["label"];
18
28
  _rendered = false;
19
29
  _labelEl = null;
20
30
  constructor() {
21
31
  super();
22
- const shadow = this.attachShadow({ mode: "open" });
23
- if ("adoptedStyleSheets" in ShadowRoot.prototype) {
24
- shadow.adoptedStyleSheets = [getSheet()];
25
- }
32
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_category_pill_default);
26
33
  }
27
34
  get label() {
28
35
  return this.getAttribute("label") ?? "";
@@ -41,11 +48,6 @@ var BvCategoryPill = class extends HTMLElement {
41
48
  if (this._rendered) return;
42
49
  this._rendered = true;
43
50
  const shadow = this.shadowRoot;
44
- if (!shadow.adoptedStyleSheets.length) {
45
- const s = document.createElement("style");
46
- s.textContent = bv_category_pill_default;
47
- shadow.appendChild(s);
48
- }
49
51
  const pill = document.createElement("span");
50
52
  pill.className = "pill";
51
53
  pill.setAttribute("part", "pill");
@@ -61,14 +63,6 @@ if (!customElements.get("bv-category-pill")) {
61
63
  }
62
64
 
63
65
  // components/bv-course-detail/bv-course-detail.ts
64
- var _sheet2 = null;
65
- function getSheet2() {
66
- if (!_sheet2) {
67
- _sheet2 = new CSSStyleSheet();
68
- _sheet2.replaceSync(bv_course_detail_default);
69
- }
70
- return _sheet2;
71
- }
72
66
  var BvCourseDetail = class extends HTMLElement {
73
67
  static observedAttributes = ["thumbnail", "title", "description", "categories"];
74
68
  _rendered = false;
@@ -82,10 +76,7 @@ var BvCourseDetail = class extends HTMLElement {
82
76
  _readMoreBtn = null;
83
77
  constructor() {
84
78
  super();
85
- const shadow = this.attachShadow({ mode: "open" });
86
- if ("adoptedStyleSheets" in ShadowRoot.prototype) {
87
- shadow.adoptedStyleSheets = [getSheet2()];
88
- }
79
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_course_detail_default);
89
80
  }
90
81
  get thumbnail() {
91
82
  return this.getAttribute("thumbnail") ?? "";
@@ -150,11 +141,6 @@ var BvCourseDetail = class extends HTMLElement {
150
141
  }
151
142
  }
152
143
  const shadow = this.shadowRoot;
153
- if (!shadow.adoptedStyleSheets.length) {
154
- const s = document.createElement("style");
155
- s.textContent = bv_course_detail_default;
156
- shadow.appendChild(s);
157
- }
158
144
  const root = document.createElement("div");
159
145
  root.className = "course-detail";
160
146
  const thumbCol = document.createElement("div");
@@ -1,6 +1,24 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-course-detail-modal/bv-course-detail-modal.css
2
2
  var bv_course_detail_modal_default = ":host {\n display: contents;\n font-family: var(--bv-font-family-base);\n}\n\n/* Ensure hidden attribute works on slotted custom elements */\n[hidden] {\n display: none !important;\n}\n\n.modal-body {\n display: flex;\n flex-direction: column;\n gap: 20px;\n width: 100%;\n}\n";
3
3
 
4
+ // components/_shared/adopt-styles.ts
5
+ var _sheetCache = /* @__PURE__ */ new Map();
6
+ function adoptStyles(shadow, css) {
7
+ if ("adoptedStyleSheets" in ShadowRoot.prototype && typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
8
+ let sheet = _sheetCache.get(css);
9
+ if (!sheet) {
10
+ sheet = new CSSStyleSheet();
11
+ sheet.replaceSync(css);
12
+ _sheetCache.set(css, sheet);
13
+ }
14
+ shadow.adoptedStyleSheets = [sheet];
15
+ return;
16
+ }
17
+ const style = document.createElement("style");
18
+ style.textContent = css;
19
+ shadow.appendChild(style);
20
+ }
21
+
4
22
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-modal/bv-modal.css
5
23
  var bv_modal_default = '/* \u2500\u2500 Public theming API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 Apps can override per-instance:\n\n HTML: <bv-modal style="--bv-modal-width: 600px;">\n Angular: <bv-modal [style.--bv-modal-bg]="bgColor">\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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:host {\n --bv-modal-width: 800px;\n --bv-modal-bg: var(--bv-color-neutral-0);\n --bv-modal-radius: var(--bv-radius-xl);\n --bv-modal-title-color: #101828;\n --bv-modal-backdrop: rgba(16, 24, 40, 0.6);\n --bv-modal-body-max-height: none;\n}\n\ndialog {\n padding: 0;\n border: none;\n border-radius: var(--bv-modal-radius);\n background: transparent;\n width: var(--bv-modal-width);\n max-width: min(var(--bv-modal-width), calc(100vw - 32px));\n outline: none;\n}\n\ndialog::backdrop {\n background: var(--bv-modal-backdrop);\n}\n\n.panel {\n display: flex;\n width: 100%;\n padding: 20px 16px;\n flex-direction: column;\n justify-content: center;\n align-items: flex-start;\n gap: 20px;\n border-radius: var(--bv-modal-radius);\n background: var(--bv-modal-bg);\n box-sizing: border-box;\n}\n\n/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.header {\n display: flex;\n width: 100%;\n align-items: center;\n justify-content: space-between;\n}\n\n.title {\n margin: 0;\n color: var(--bv-modal-title-color);\n font-family: var(--bv-font-family-base);\n font-size: 24px;\n font-style: normal;\n font-weight: var(--bv-font-weight-medium);\n line-height: 32px;\n}\n\n.close-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--bv-radius-md);\n cursor: pointer;\n color: var(--bv-color-neutral-500);\n font-size: 18px;\n line-height: 1;\n flex-shrink: 0;\n transition:\n color var(--bv-transition-fast),\n background var(--bv-transition-fast);\n}\n\n.close-btn:hover {\n color: var(--bv-color-neutral-800);\n background: var(--bv-color-neutral-100);\n}\n\n/* \u2500\u2500 Separator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.separator {\n width: 100%;\n border: none;\n border-top: 1px solid var(--bv-color-neutral-200);\n margin: 0;\n}\n\n/* \u2500\u2500 Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.body {\n width: 100%;\n max-height: var(--bv-modal-body-max-height);\n overflow-y: auto;\n color: var(--bv-color-neutral-600);\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n line-height: 20px;\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\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n.footer {\n width: 100%;\n}\n';
6
24
 
@@ -12,12 +30,7 @@ var BvModal = class extends HTMLElement {
12
30
  _rendered = false;
13
31
  constructor() {
14
32
  super();
15
- this.attachShadow({ mode: "open" });
16
- if (typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
17
- const sheet = new CSSStyleSheet();
18
- sheet.replaceSync(bv_modal_default);
19
- this.shadowRoot.adoptedStyleSheets = [sheet];
20
- }
33
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_modal_default);
21
34
  }
22
35
  connectedCallback() {
23
36
  this._render();
@@ -51,11 +64,6 @@ var BvModal = class extends HTMLElement {
51
64
  if (this._rendered) return;
52
65
  this._rendered = true;
53
66
  const shadow = this.shadowRoot;
54
- if (!shadow.adoptedStyleSheets.length) {
55
- const style = document.createElement("style");
56
- style.textContent = bv_modal_default;
57
- shadow.appendChild(style);
58
- }
59
67
  const dialog = document.createElement("dialog");
60
68
  this._dialog = dialog;
61
69
  dialog.addEventListener("click", (e) => {
@@ -110,24 +118,13 @@ var bv_course_detail_default = ":host {\n display: block;\n font-family: var(-
110
118
  var bv_category_pill_default = ":host {\n display: inline-flex;\n font-family: var(--bv-font-family-base);\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 6px;\n border: 0.5px solid var(--bv-color-neutral-900);\n border-radius: var(--bv-radius-sm);\n font-size: 10px;\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 1;\n white-space: nowrap;\n}\n";
111
119
 
112
120
  // components/bv-category-pill/bv-category-pill.ts
113
- var _sheet = null;
114
- function getSheet() {
115
- if (!_sheet) {
116
- _sheet = new CSSStyleSheet();
117
- _sheet.replaceSync(bv_category_pill_default);
118
- }
119
- return _sheet;
120
- }
121
121
  var BvCategoryPill = class extends HTMLElement {
122
122
  static observedAttributes = ["label"];
123
123
  _rendered = false;
124
124
  _labelEl = null;
125
125
  constructor() {
126
126
  super();
127
- const shadow = this.attachShadow({ mode: "open" });
128
- if ("adoptedStyleSheets" in ShadowRoot.prototype) {
129
- shadow.adoptedStyleSheets = [getSheet()];
130
- }
127
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_category_pill_default);
131
128
  }
132
129
  get label() {
133
130
  return this.getAttribute("label") ?? "";
@@ -146,11 +143,6 @@ var BvCategoryPill = class extends HTMLElement {
146
143
  if (this._rendered) return;
147
144
  this._rendered = true;
148
145
  const shadow = this.shadowRoot;
149
- if (!shadow.adoptedStyleSheets.length) {
150
- const s = document.createElement("style");
151
- s.textContent = bv_category_pill_default;
152
- shadow.appendChild(s);
153
- }
154
146
  const pill = document.createElement("span");
155
147
  pill.className = "pill";
156
148
  pill.setAttribute("part", "pill");
@@ -166,14 +158,6 @@ if (!customElements.get("bv-category-pill")) {
166
158
  }
167
159
 
168
160
  // components/bv-course-detail/bv-course-detail.ts
169
- var _sheet2 = null;
170
- function getSheet2() {
171
- if (!_sheet2) {
172
- _sheet2 = new CSSStyleSheet();
173
- _sheet2.replaceSync(bv_course_detail_default);
174
- }
175
- return _sheet2;
176
- }
177
161
  var BvCourseDetail = class extends HTMLElement {
178
162
  static observedAttributes = ["thumbnail", "title", "description", "categories"];
179
163
  _rendered = false;
@@ -187,10 +171,7 @@ var BvCourseDetail = class extends HTMLElement {
187
171
  _readMoreBtn = null;
188
172
  constructor() {
189
173
  super();
190
- const shadow = this.attachShadow({ mode: "open" });
191
- if ("adoptedStyleSheets" in ShadowRoot.prototype) {
192
- shadow.adoptedStyleSheets = [getSheet2()];
193
- }
174
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_course_detail_default);
194
175
  }
195
176
  get thumbnail() {
196
177
  return this.getAttribute("thumbnail") ?? "";
@@ -255,11 +236,6 @@ var BvCourseDetail = class extends HTMLElement {
255
236
  }
256
237
  }
257
238
  const shadow = this.shadowRoot;
258
- if (!shadow.adoptedStyleSheets.length) {
259
- const s = document.createElement("style");
260
- s.textContent = bv_course_detail_default;
261
- shadow.appendChild(s);
262
- }
263
239
  const root = document.createElement("div");
264
240
  root.className = "course-detail";
265
241
  const thumbCol = document.createElement("div");
@@ -398,12 +374,7 @@ var BvCourseOutline = class extends HTMLElement {
398
374
  }
399
375
  constructor() {
400
376
  super();
401
- this.attachShadow({ mode: "open" });
402
- if ("replaceSync" in CSSStyleSheet.prototype) {
403
- const sheet = new CSSStyleSheet();
404
- sheet.replaceSync(bv_course_outline_default);
405
- this.shadowRoot.adoptedStyleSheets = [sheet];
406
- }
377
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_course_outline_default);
407
378
  }
408
379
  connectedCallback() {
409
380
  this._render();
@@ -426,11 +397,6 @@ var BvCourseOutline = class extends HTMLElement {
426
397
  if (this._rendered) return;
427
398
  this._rendered = true;
428
399
  const shadow = this.shadowRoot;
429
- if (!shadow.adoptedStyleSheets.length) {
430
- const s = document.createElement("style");
431
- s.textContent = bv_course_outline_default;
432
- shadow.appendChild(s);
433
- }
434
400
  const attr = this.getAttribute("sections");
435
401
  if (attr !== null) {
436
402
  try {
@@ -933,14 +899,6 @@ var rawIcons = {
933
899
  };
934
900
 
935
901
  // components/bv-button/bv-button.ts
936
- var _sheet3 = null;
937
- function getSheet3() {
938
- if (!_sheet3) {
939
- _sheet3 = new CSSStyleSheet();
940
- _sheet3.replaceSync(bv_button_default);
941
- }
942
- return _sheet3;
943
- }
944
902
  var BvButton = class extends HTMLElement {
945
903
  static observedAttributes = [
946
904
  "variant",
@@ -956,10 +914,7 @@ var BvButton = class extends HTMLElement {
956
914
  ];
957
915
  constructor() {
958
916
  super();
959
- const shadow = this.attachShadow({ mode: "open" });
960
- if ("adoptedStyleSheets" in ShadowRoot.prototype) {
961
- shadow.adoptedStyleSheets = [getSheet3()];
962
- }
917
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_button_default);
963
918
  }
964
919
  // ── Accessors ────────────────────────────────────────────────
965
920
  get variant() {
@@ -1016,11 +971,6 @@ var BvButton = class extends HTMLElement {
1016
971
  const shadow = this.shadowRoot;
1017
972
  let btn = shadow.querySelector("button");
1018
973
  if (!btn) {
1019
- if (!shadow.adoptedStyleSheets.length) {
1020
- const styleEl = document.createElement("style");
1021
- styleEl.textContent = bv_button_default;
1022
- shadow.appendChild(styleEl);
1023
- }
1024
974
  btn = document.createElement("button");
1025
975
  btn.setAttribute("part", "button");
1026
976
  btn.appendChild(document.createElement("slot"));
@@ -1075,14 +1025,6 @@ if (!customElements.get("bv-button")) {
1075
1025
  }
1076
1026
 
1077
1027
  // components/bv-course-detail-modal/bv-course-detail-modal.ts
1078
- var _sheet4 = null;
1079
- function getSheet4() {
1080
- if (!_sheet4) {
1081
- _sheet4 = new CSSStyleSheet();
1082
- _sheet4.replaceSync(bv_course_detail_modal_default);
1083
- }
1084
- return _sheet4;
1085
- }
1086
1028
  var BvCourseDetailModal = class extends HTMLElement {
1087
1029
  static observedAttributes = [
1088
1030
  "open",
@@ -1103,10 +1045,7 @@ var BvCourseDetailModal = class extends HTMLElement {
1103
1045
  _outlineEl = null;
1104
1046
  constructor() {
1105
1047
  super();
1106
- const shadow = this.attachShadow({ mode: "open" });
1107
- if ("adoptedStyleSheets" in ShadowRoot.prototype) {
1108
- shadow.adoptedStyleSheets = [getSheet4()];
1109
- }
1048
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_course_detail_modal_default);
1110
1049
  }
1111
1050
  get open() {
1112
1051
  return this.hasAttribute("open");
@@ -1229,11 +1168,6 @@ var BvCourseDetailModal = class extends HTMLElement {
1229
1168
  }
1230
1169
  }
1231
1170
  const shadow = this.shadowRoot;
1232
- if (!shadow.adoptedStyleSheets.length) {
1233
- const s = document.createElement("style");
1234
- s.textContent = bv_course_detail_modal_default;
1235
- shadow.appendChild(s);
1236
- }
1237
1171
  const modal = document.createElement("bv-modal");
1238
1172
  modal.setAttribute("title", this.title);
1239
1173
  if (this.open) modal.setAttribute("open", "");
@@ -1,5 +1,6 @@
1
1
  import '../bv-button/bv-button.ts';
2
- export declare class BvCourseGridCard extends HTMLElement {
2
+ import { type SelectableHost } from '../_shared/selectable-card.ts';
3
+ export declare class BvCourseGridCard extends HTMLElement implements SelectableHost {
3
4
  static readonly observedAttributes: string[];
4
5
  get selected(): boolean;
5
6
  set selected(v: boolean);
@@ -19,9 +20,4 @@ export declare class BvCourseGridCard extends HTMLElement {
19
20
  connectedCallback(): void;
20
21
  attributeChangedCallback(name: string, _old: string | null, val: string | null): void;
21
22
  private _render;
22
- private _toggleSelected;
23
- private _buildAriaLabel;
24
- private _setPrefixedStrong;
25
- private _syncSelectionA11y;
26
- private _syncLoading;
27
23
  }