@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,75 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-input-dropdown/bv-input-dropdown.css
2
2
  var bv_input_dropdown_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: 20px;\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 box-sizing: border-box;\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([disabled]) .trigger {\n background: var(--bv-color-neutral-100);\n color: var(--bv-color-neutral-400);\n cursor: not-allowed;\n}\n\n:host([error]:not([error=''])) .trigger {\n border-color: var(--bv-color-danger);\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 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 min-width: 100%;\n width: max-content;\n max-width: 600px;\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([toggle-label]) .panel {\n min-width: 260px;\n}\n\n:host([open]) .panel {\n display: block;\n}\n\n/* \u2500\u2500 Panel header (search + toolbar) \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-header {\n border-bottom: 1px solid var(--bv-color-neutral-200);\n padding: var(--bv-spacing-sm);\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-xs);\n}\n\n.panel-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--bv-spacing-xs) 0;\n}\n\n/* \u2500\u2500 Panel content (scrollable slot area) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.panel-content {\n overflow-y: auto;\n max-height: var(--bv-input-dropdown-content-height, 280px);\n padding: var(--bv-spacing-xs) 0;\n}\n\n/* Stack all slotted content vertically */\n::slotted(*) {\n display: block;\n}\n\n/* Row padding \u2014 left aligns with the panel-header padding */\n::slotted(bv-checkbox) {\n padding: 6px var(--bv-spacing-sm);\n box-sizing: border-box;\n white-space: nowrap;\n max-width: 100%;\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.field-error:empty {\n display: none;\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
+
22
+ // components/_shared/dropdown-controller.ts
23
+ function bindDropdownController(host, options = {}) {
24
+ if (!host.shadowRoot) {
25
+ throw new Error("bindDropdownController requires the host to have an open shadow root.");
26
+ }
27
+ const syncExpanded = () => {
28
+ var _a;
29
+ (_a = options.trigger) == null ? void 0 : _a.setAttribute("aria-expanded", host.hasAttribute("open") ? "true" : "false");
30
+ };
31
+ const open = () => {
32
+ var _a;
33
+ if (host.hasAttribute("open")) return;
34
+ (_a = options.onBeforeOpen) == null ? void 0 : _a.call(options);
35
+ host.setAttribute("open", "");
36
+ syncExpanded();
37
+ host.dispatchEvent(new CustomEvent("bv-open", { bubbles: true, composed: true }));
38
+ };
39
+ const closeWithReason = (reason) => {
40
+ var _a;
41
+ if (!host.hasAttribute("open")) return;
42
+ if (options.canClose && !options.canClose(reason)) return;
43
+ host.removeAttribute("open");
44
+ syncExpanded();
45
+ (_a = options.onAfterClose) == null ? void 0 : _a.call(options);
46
+ };
47
+ const close = () => closeWithReason("programmatic");
48
+ const toggle = () => {
49
+ if (host.hasAttribute("open")) closeWithReason("programmatic");
50
+ else open();
51
+ };
52
+ const offClick = (e) => {
53
+ if (!host.hasAttribute("open")) return;
54
+ if (e.composedPath().includes(host)) return;
55
+ closeWithReason("outside-click");
56
+ };
57
+ document.addEventListener("click", offClick);
58
+ const onKeyDown = (e) => {
59
+ if (e.key === "Escape") closeWithReason("escape");
60
+ };
61
+ host.addEventListener("keydown", onKeyDown);
62
+ const observer = new MutationObserver(syncExpanded);
63
+ observer.observe(host, { attributes: true, attributeFilter: ["open"] });
64
+ const cleanup = () => {
65
+ observer.disconnect();
66
+ document.removeEventListener("click", offClick);
67
+ host.removeEventListener("keydown", onKeyDown);
68
+ };
69
+ syncExpanded();
70
+ return { open, close, toggle, cleanup };
71
+ }
72
+
4
73
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-searchbox/bv-searchbox.css
5
74
  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";
6
75
 
@@ -15,12 +84,7 @@ var BvSearchbox = class extends HTMLElement {
15
84
  _input = null;
16
85
  constructor() {
17
86
  super();
18
- this.attachShadow({ mode: "open" });
19
- if ("replaceSync" in CSSStyleSheet.prototype) {
20
- const sheet = new CSSStyleSheet();
21
- sheet.replaceSync(bv_searchbox_default);
22
- this.shadowRoot.adoptedStyleSheets = [sheet];
23
- }
87
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_searchbox_default);
24
88
  }
25
89
  connectedCallback() {
26
90
  this._render();
@@ -38,11 +102,6 @@ var BvSearchbox = class extends HTMLElement {
38
102
  if (this._rendered) return;
39
103
  this._rendered = true;
40
104
  const shadow = this.shadowRoot;
41
- if (!shadow.adoptedStyleSheets.length) {
42
- const s = document.createElement("style");
43
- s.textContent = bv_searchbox_default;
44
- shadow.appendChild(s);
45
- }
46
105
  const icon = document.createElement("span");
47
106
  icon.className = "search-icon";
48
107
  icon.innerHTML = SEARCH_ICON;
@@ -84,12 +143,7 @@ var BvCheckbox = class extends HTMLElement {
84
143
  _labelEl = null;
85
144
  constructor() {
86
145
  super();
87
- this.attachShadow({ mode: "open" });
88
- if ("replaceSync" in CSSStyleSheet.prototype) {
89
- const sheet = new CSSStyleSheet();
90
- sheet.replaceSync(bv_checkbox_default);
91
- this.shadowRoot.adoptedStyleSheets = [sheet];
92
- }
146
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_checkbox_default);
93
147
  }
94
148
  connectedCallback() {
95
149
  this._render();
@@ -113,11 +167,6 @@ var BvCheckbox = class extends HTMLElement {
113
167
  if (this._rendered) return;
114
168
  this._rendered = true;
115
169
  const shadow = this.shadowRoot;
116
- if (!shadow.adoptedStyleSheets.length) {
117
- const s = document.createElement("style");
118
- s.textContent = bv_checkbox_default;
119
- shadow.appendChild(s);
120
- }
121
170
  const wrap = document.createElement("label");
122
171
  wrap.className = "wrap";
123
172
  const box = document.createElement("span");
@@ -164,12 +213,7 @@ var BvToggle = class extends HTMLElement {
164
213
  _labelEl = null;
165
214
  constructor() {
166
215
  super();
167
- this.attachShadow({ mode: "open" });
168
- if ("replaceSync" in CSSStyleSheet.prototype) {
169
- const sheet = new CSSStyleSheet();
170
- sheet.replaceSync(bv_toggle_default);
171
- this.shadowRoot.adoptedStyleSheets = [sheet];
172
- }
216
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_toggle_default);
173
217
  }
174
218
  connectedCallback() {
175
219
  this._render();
@@ -189,11 +233,6 @@ var BvToggle = class extends HTMLElement {
189
233
  if (this._rendered) return;
190
234
  this._rendered = true;
191
235
  const shadow = this.shadowRoot;
192
- if (!shadow.adoptedStyleSheets.length) {
193
- const s = document.createElement("style");
194
- s.textContent = bv_toggle_default;
195
- shadow.appendChild(s);
196
- }
197
236
  const wrap = document.createElement("label");
198
237
  wrap.className = "wrap";
199
238
  const track = document.createElement("span");
@@ -226,14 +265,6 @@ if (!customElements.get("bv-toggle")) {
226
265
 
227
266
  // components/bv-input-dropdown/bv-input-dropdown.ts
228
267
  var CHEVRON_ICON = `<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>`;
229
- var _sheet = null;
230
- function getSheet() {
231
- if (!_sheet) {
232
- _sheet = new CSSStyleSheet();
233
- _sheet.replaceSync(bv_input_dropdown_default);
234
- }
235
- return _sheet;
236
- }
237
268
  var BvInputDropdown = class extends HTMLElement {
238
269
  static observedAttributes = [
239
270
  "label",
@@ -258,13 +289,10 @@ var BvInputDropdown = class extends HTMLElement {
258
289
  _selectAllEl = null;
259
290
  _toggleEl = null;
260
291
  _errorEl = null;
261
- _offClick = null;
292
+ _dropdown = null;
262
293
  constructor() {
263
294
  super();
264
- const shadow = this.attachShadow({ mode: "open" });
265
- if ("adoptedStyleSheets" in ShadowRoot.prototype) {
266
- shadow.adoptedStyleSheets = [getSheet()];
267
- }
295
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_input_dropdown_default);
268
296
  }
269
297
  get value() {
270
298
  return this.getAttribute("value") ?? "";
@@ -290,7 +318,8 @@ var BvInputDropdown = class extends HTMLElement {
290
318
  this._render();
291
319
  }
292
320
  disconnectedCallback() {
293
- if (this._offClick) document.removeEventListener("click", this._offClick);
321
+ var _a;
322
+ (_a = this._dropdown) == null ? void 0 : _a.cleanup();
294
323
  }
295
324
  attributeChangedCallback(name, _old, _val) {
296
325
  if (!this._rendered) return;
@@ -300,20 +329,11 @@ var BvInputDropdown = class extends HTMLElement {
300
329
  if (name === "search") this._syncSearch();
301
330
  if (name === "select-all" || name === "select-all-state" || name === "toggle-label" || name === "toggle-checked")
302
331
  this._syncToolbar();
303
- if (name === "open") {
304
- const trigger = this.shadowRoot.querySelector(".trigger");
305
- if (trigger) trigger.setAttribute("aria-expanded", _val !== null ? "true" : "false");
306
- }
307
332
  }
308
333
  _render() {
309
334
  if (this._rendered) return;
310
335
  this._rendered = true;
311
336
  const shadow = this.shadowRoot;
312
- if (!shadow.adoptedStyleSheets.length) {
313
- const s = document.createElement("style");
314
- s.textContent = bv_input_dropdown_default;
315
- shadow.appendChild(s);
316
- }
317
337
  const label = document.createElement("label");
318
338
  label.className = "field-label";
319
339
  this._labelEl = label;
@@ -324,8 +344,9 @@ var BvInputDropdown = class extends HTMLElement {
324
344
  trigger.setAttribute("aria-expanded", "false");
325
345
  trigger.setAttribute("part", "trigger");
326
346
  trigger.addEventListener("click", (e) => {
347
+ var _a;
327
348
  e.stopPropagation();
328
- if (!this.disabled) this._toggle();
349
+ if (!this.disabled) (_a = this._dropdown) == null ? void 0 : _a.toggle();
329
350
  });
330
351
  const triggerLabel = document.createElement("span");
331
352
  triggerLabel.className = "trigger-label";
@@ -398,27 +419,7 @@ var BvInputDropdown = class extends HTMLElement {
398
419
  this._syncError();
399
420
  this._syncSearch();
400
421
  this._syncToolbar();
401
- this._offClick = (e) => {
402
- if (!this.contains(e.target) && !shadow.contains(e.target)) {
403
- this._close();
404
- }
405
- };
406
- document.addEventListener("click", this._offClick);
407
- }
408
- _toggle() {
409
- if (this.hasAttribute("open")) this._close();
410
- else this._open();
411
- }
412
- _open() {
413
- var _a;
414
- this.setAttribute("open", "");
415
- (_a = this.shadowRoot.querySelector(".trigger")) == null ? void 0 : _a.setAttribute("aria-expanded", "true");
416
- this.dispatchEvent(new CustomEvent("bv-open", { bubbles: true, composed: true }));
417
- }
418
- _close() {
419
- var _a;
420
- this.removeAttribute("open");
421
- (_a = this.shadowRoot.querySelector(".trigger")) == null ? void 0 : _a.setAttribute("aria-expanded", "false");
422
+ this._dropdown = bindDropdownController(this, { trigger });
422
423
  }
423
424
  _syncLabel() {
424
425
  if (!this._labelEl) return;
@@ -1,6 +1,24 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-modal/bv-modal.css
2
2
  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';
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-modal/bv-modal.ts
5
23
  var BvModal = class extends HTMLElement {
6
24
  static observedAttributes = ["title", "open"];
@@ -9,12 +27,7 @@ var BvModal = class extends HTMLElement {
9
27
  _rendered = false;
10
28
  constructor() {
11
29
  super();
12
- this.attachShadow({ mode: "open" });
13
- if (typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
14
- const sheet = new CSSStyleSheet();
15
- sheet.replaceSync(bv_modal_default);
16
- this.shadowRoot.adoptedStyleSheets = [sheet];
17
- }
30
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_modal_default);
18
31
  }
19
32
  connectedCallback() {
20
33
  this._render();
@@ -48,11 +61,6 @@ var BvModal = class extends HTMLElement {
48
61
  if (this._rendered) return;
49
62
  this._rendered = true;
50
63
  const shadow = this.shadowRoot;
51
- if (!shadow.adoptedStyleSheets.length) {
52
- const style = document.createElement("style");
53
- style.textContent = bv_modal_default;
54
- shadow.appendChild(style);
55
- }
56
64
  const dialog = document.createElement("dialog");
57
65
  this._dialog = dialog;
58
66
  dialog.addEventListener("click", (e) => {
@@ -1,16 +1,29 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-page-title/bv-page-title.css
2
2
  var bv_page_title_default = ":host {\n display: block;\n}\n\nh1 {\n margin: 0;\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-2xl);\n font-weight: var(--bv-font-weight-medium);\n line-height: 1.2;\n color: var(--bv-color-neutral-900);\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-page-title/bv-page-title.ts
5
23
  var BvPageTitle = class extends HTMLElement {
6
24
  constructor() {
7
25
  super();
8
- this.attachShadow({ mode: "open" });
9
- if ("replaceSync" in CSSStyleSheet.prototype) {
10
- const sheet = new CSSStyleSheet();
11
- sheet.replaceSync(bv_page_title_default);
12
- this.shadowRoot.adoptedStyleSheets = [sheet];
13
- }
26
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_page_title_default);
14
27
  }
15
28
  connectedCallback() {
16
29
  if (this.shadowRoot.childElementCount > (this.shadowRoot.adoptedStyleSheets.length ? 0 : 1))
@@ -1,6 +1,7 @@
1
1
  export declare class BvPagination extends HTMLElement {
2
2
  static readonly observedAttributes: readonly ["page", "total-pages", "total", "page-size", "siblings", "show-results", "show-page-size", "page-size-options", "compact"];
3
3
  private _rendered;
4
+ private _metaEl;
4
5
  private _pagesEl;
5
6
  private _prevBtn;
6
7
  private _nextBtn;
@@ -1,180 +1,23 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-pagination/bv-pagination.css
2
- var bv_pagination_default = `:host {
3
- display: block;
4
- }
5
-
6
- .wrap {
7
- display: flex;
8
- align-items: center;
9
- justify-content: space-between;
10
- gap: var(--bv-spacing-xl);
11
- width: 100%;
12
- font-family: var(--bv-font-family-base);
13
- }
14
-
15
- /* \u2500\u2500 Meta section (results count + page-size) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2
+ var bv_pagination_default = ":host {\n display: block;\n}\n\n/*\n * Any element inside the shadow tree that carries author-declared display\n * still respects the `hidden` attribute. Without this, `[hidden] { display: none }`\n * (UA rule) loses to author `display: <value>` and the element stays visible.\n */\n[hidden] {\n display: none !important;\n}\n\n.wrap {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--bv-spacing-xl);\n width: 100%;\n font-family: var(--bv-font-family-base);\n}\n\n/* \u2500\u2500 Meta section (results count + page-size) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.meta {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n}\n\n.results-count {\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-700);\n white-space: nowrap;\n margin-right: var(--bv-spacing-sm);\n}\n\n.page-size-wrap {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.page-size-select {\n height: 36px;\n box-sizing: border-box;\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-lg);\n background-color: var(--bv-color-neutral-0);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5 7.5l5 5 5-5' stroke='%23667085' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 8px center;\n appearance: none;\n -webkit-appearance: none;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-700);\n padding: 0 28px 0 var(--bv-spacing-sm);\n cursor: pointer;\n box-shadow: var(--bv-shadow-sm);\n outline: none;\n}\n\n.page-size-select:focus {\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.per-page-label {\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-500);\n white-space: nowrap;\n}\n\n/* \u2500\u2500 Nav section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.nav {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-xs);\n}\n\n/*\n * When .meta collapses (opt-out consumers: no show-results, no show-page-size),\n * .wrap's `space-between` has only one visible child and packs .nav to the\n * left. Give .nav the full width and use auto-margins to reproduce the\n * pre-v2.0.0 3-column layout: Prev on far left, pages in the middle,\n * (range + Next) grouped on the far right.\n */\n.meta[hidden] ~ .nav {\n flex: 1;\n}\n/*\n * Non-compact: two auto-margins split the extra space into equal gaps so the\n * layout reads `[Prev]___[pages]___[range][Next]`. Prev sits on the far left,\n * pages centered in the middle, range + Next grouped on the far right.\n */\n.meta[hidden] ~ .nav .pages {\n margin-left: auto;\n}\n.meta[hidden] ~ .nav .range-label {\n margin-left: auto;\n}\n/* Compact: page label centers between Prev and Next. */\n.meta[hidden] ~ .nav .page-label {\n margin-left: auto;\n margin-right: auto;\n}\n\n/* \u2500\u2500 Shared button base \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 1px solid transparent;\n border-radius: var(--bv-radius-lg);\n background: transparent;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n color var(--bv-transition-fast);\n}\n\n/* Prev / Next buttons */\n.nav-btn {\n gap: var(--bv-spacing-xs);\n height: 36px;\n padding: 0 var(--bv-spacing-sm);\n border-color: var(--bv-color-neutral-300);\n background: var(--bv-color-neutral-0);\n color: var(--bv-color-neutral-700);\n font-weight: var(--bv-font-weight-semibold);\n box-shadow: var(--bv-shadow-sm);\n white-space: nowrap;\n}\n\n.nav-btn:hover:not(:disabled) {\n background: var(--bv-color-neutral-100);\n}\n\n.nav-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.nav-icon {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n}\n\n/* Compact page label \u2014 plain text between Prev / Next */\n.page-label {\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-700);\n white-space: nowrap;\n padding: 0 var(--bv-spacing-md);\n}\n\n/* \u2500\u2500 Page number buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.pages {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.page-btn {\n width: 40px;\n height: 40px;\n color: var(--bv-color-neutral-600);\n font-weight: var(--bv-font-weight-medium);\n}\n\n.page-btn:hover:not(.active) {\n background: var(--bv-color-neutral-100);\n}\n\n.page-btn.active {\n background: var(--bv-color-neutral-100);\n color: var(--bv-color-neutral-900);\n cursor: default;\n}\n\n.ellipsis {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-400);\n}\n\n/* \u2500\u2500 Range 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 */\n\n.range-label {\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-600);\n white-space: nowrap;\n margin-left: var(--bv-spacing-xs);\n}\n";
16
3
 
17
- .meta {
18
- display: flex;
19
- align-items: center;
20
- gap: var(--bv-spacing-sm);
21
- }
22
-
23
- .results-count {
24
- font-size: var(--bv-font-size-sm);
25
- font-weight: var(--bv-font-weight-semibold);
26
- color: var(--bv-color-neutral-700);
27
- white-space: nowrap;
28
- margin-right: var(--bv-spacing-sm);
29
- }
30
-
31
- .page-size-wrap {
32
- display: inline-flex;
33
- align-items: center;
34
- gap: 6px;
35
- }
36
-
37
- .page-size-select {
38
- height: 36px;
39
- box-sizing: border-box;
40
- border: 1px solid var(--bv-color-neutral-300);
41
- border-radius: var(--bv-radius-lg);
42
- background-color: var(--bv-color-neutral-0);
43
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5 7.5l5 5 5-5' stroke='%23667085' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
44
- background-repeat: no-repeat;
45
- background-position: right 8px center;
46
- appearance: none;
47
- -webkit-appearance: none;
48
- font-family: inherit;
49
- font-size: var(--bv-font-size-sm);
50
- font-weight: var(--bv-font-weight-semibold);
51
- color: var(--bv-color-neutral-700);
52
- padding: 0 28px 0 var(--bv-spacing-sm);
53
- cursor: pointer;
54
- box-shadow: var(--bv-shadow-sm);
55
- outline: none;
56
- }
57
-
58
- .page-size-select:focus {
59
- border-color: var(--bv-color-primary);
60
- box-shadow:
61
- 0 0 0 3px var(--bv-color-primary-light),
62
- 0 1px 2px 0 rgba(16, 24, 40, 0.05);
63
- }
64
-
65
- .per-page-label {
66
- font-size: var(--bv-font-size-sm);
67
- color: var(--bv-color-neutral-500);
68
- white-space: nowrap;
69
- }
70
-
71
- /* \u2500\u2500 Nav section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
72
-
73
- .nav {
74
- display: flex;
75
- align-items: center;
76
- gap: var(--bv-spacing-xs);
77
- }
78
-
79
- /* \u2500\u2500 Shared button base \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
80
-
81
- .btn {
82
- display: inline-flex;
83
- align-items: center;
84
- justify-content: center;
85
- border: 1px solid transparent;
86
- border-radius: var(--bv-radius-lg);
87
- background: transparent;
88
- font-family: inherit;
89
- font-size: var(--bv-font-size-sm);
90
- cursor: pointer;
91
- transition:
92
- background var(--bv-transition-fast),
93
- color var(--bv-transition-fast);
94
- }
95
-
96
- /* Prev / Next buttons */
97
- .nav-btn {
98
- gap: var(--bv-spacing-xs);
99
- height: 36px;
100
- padding: 0 var(--bv-spacing-sm);
101
- border-color: var(--bv-color-neutral-300);
102
- background: var(--bv-color-neutral-0);
103
- color: var(--bv-color-neutral-700);
104
- font-weight: var(--bv-font-weight-semibold);
105
- box-shadow: var(--bv-shadow-sm);
106
- white-space: nowrap;
107
- }
108
-
109
- .nav-btn:hover:not(:disabled) {
110
- background: var(--bv-color-neutral-100);
111
- }
112
-
113
- .nav-btn:disabled {
114
- opacity: 0.5;
115
- cursor: not-allowed;
116
- }
117
-
118
- .nav-icon {
119
- width: 20px;
120
- height: 20px;
121
- flex-shrink: 0;
122
- }
123
-
124
- /* Compact page label \u2014 plain text between Prev / Next */
125
- .page-label {
126
- font-size: var(--bv-font-size-sm);
127
- font-weight: var(--bv-font-weight-semibold);
128
- color: var(--bv-color-neutral-700);
129
- white-space: nowrap;
130
- padding: 0 var(--bv-spacing-md);
131
- }
132
-
133
- /* \u2500\u2500 Page number buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
134
-
135
- .pages {
136
- display: flex;
137
- align-items: center;
138
- gap: 2px;
139
- }
140
-
141
- .page-btn {
142
- width: 40px;
143
- height: 40px;
144
- color: var(--bv-color-neutral-600);
145
- font-weight: var(--bv-font-weight-medium);
146
- }
147
-
148
- .page-btn:hover:not(.active) {
149
- background: var(--bv-color-neutral-100);
150
- }
151
-
152
- .page-btn.active {
153
- background: var(--bv-color-neutral-100);
154
- color: var(--bv-color-neutral-900);
155
- cursor: default;
156
- }
157
-
158
- .ellipsis {
159
- display: inline-flex;
160
- align-items: center;
161
- justify-content: center;
162
- width: 40px;
163
- height: 40px;
164
- font-size: var(--bv-font-size-sm);
165
- color: var(--bv-color-neutral-400);
166
- }
167
-
168
- /* \u2500\u2500 Range 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 */
169
-
170
- .range-label {
171
- font-size: var(--bv-font-size-sm);
172
- font-weight: var(--bv-font-weight-medium);
173
- color: var(--bv-color-neutral-600);
174
- white-space: nowrap;
175
- margin-left: var(--bv-spacing-xs);
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);
176
20
  }
177
- `;
178
21
 
179
22
  // components/bv-pagination/bv-pagination.ts
180
23
  var PREV_ICON = `<svg class="nav-icon" viewBox="0 0 20 20" fill="none"><path d="M12.5 15l-5-5 5-5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
@@ -192,6 +35,7 @@ var BvPagination = class extends HTMLElement {
192
35
  "compact"
193
36
  ];
194
37
  _rendered = false;
38
+ _metaEl = null;
195
39
  _pagesEl = null;
196
40
  _prevBtn = null;
197
41
  _nextBtn = null;
@@ -202,12 +46,7 @@ var BvPagination = class extends HTMLElement {
202
46
  _pageLabelEl = null;
203
47
  constructor() {
204
48
  super();
205
- this.attachShadow({ mode: "open" });
206
- if ("replaceSync" in CSSStyleSheet.prototype) {
207
- const sheet = new CSSStyleSheet();
208
- sheet.replaceSync(bv_pagination_default);
209
- this.shadowRoot.adoptedStyleSheets = [sheet];
210
- }
49
+ adoptStyles(this.attachShadow({ mode: "open" }), bv_pagination_default);
211
50
  }
212
51
  connectedCallback() {
213
52
  this._render();
@@ -271,15 +110,11 @@ var BvPagination = class extends HTMLElement {
271
110
  if (this._rendered) return;
272
111
  this._rendered = true;
273
112
  const shadow = this.shadowRoot;
274
- if (!shadow.adoptedStyleSheets.length) {
275
- const s = document.createElement("style");
276
- s.textContent = bv_pagination_default;
277
- shadow.appendChild(s);
278
- }
279
113
  const wrap = document.createElement("div");
280
114
  wrap.className = "wrap";
281
115
  const metaEl = document.createElement("div");
282
116
  metaEl.className = "meta";
117
+ this._metaEl = metaEl;
283
118
  const resultsEl = document.createElement("span");
284
119
  resultsEl.className = "results-count";
285
120
  this._resultsEl = resultsEl;
@@ -291,7 +126,6 @@ var BvPagination = class extends HTMLElement {
291
126
  this._pageSizeSelectEl = pageSizeSelect;
292
127
  pageSizeSelect.addEventListener("change", () => {
293
128
  const newSize = parseInt(pageSizeSelect.value, 10);
294
- this.setAttribute("page-size", String(newSize));
295
129
  this.dispatchEvent(
296
130
  new CustomEvent("bv-page-size-change", {
297
131
  bubbles: true,
@@ -367,6 +201,9 @@ var BvPagination = class extends HTMLElement {
367
201
  if (this._pageSizeSelectEl) {
368
202
  this._syncPageSizeOptions(pageSize);
369
203
  }
204
+ if (this._metaEl) {
205
+ this._metaEl.hidden = !this.showResults && !this.showPageSize;
206
+ }
370
207
  if (!this._pagesEl || compact) return;
371
208
  this._pagesEl.innerHTML = "";
372
209
  const pages = this._pageRange(page, totalPages, siblings);