@bluevolt-tech/lumen 1.5.1 → 2.0.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 (47) hide show
  1. package/dist/components/bv-alert-banner/bv-alert-banner.d.ts +33 -0
  2. package/dist/components/bv-alert-banner/bv-alert-banner.js +206 -0
  3. package/dist/components/bv-badge/bv-badge.d.ts +1 -1
  4. package/dist/components/bv-badge/bv-badge.js +1 -1
  5. package/dist/components/bv-button/bv-button.d.ts +1 -1
  6. package/dist/components/bv-button/bv-button.js +7 -2
  7. package/dist/components/bv-checkbox/bv-checkbox.js +1 -1
  8. package/dist/components/bv-course-detail-modal/bv-course-detail-modal.js +7 -2
  9. package/dist/components/bv-course-grid-card/bv-course-grid-card.d.ts +0 -1
  10. package/dist/components/bv-course-grid-card/bv-course-grid-card.js +8 -12
  11. package/dist/components/bv-course-list-card/bv-course-list-card.js +7 -2
  12. package/dist/components/bv-date-range-input/bv-date-range-input.d.ts +23 -0
  13. package/dist/components/bv-date-range-input/bv-date-range-input.js +950 -0
  14. package/dist/components/bv-date-range-picker/bv-date-range-picker.d.ts +56 -0
  15. package/dist/components/bv-date-range-picker/bv-date-range-picker.js +778 -0
  16. package/dist/components/bv-empty-state/bv-empty-state.js +7 -2
  17. package/dist/components/bv-filter-dropdown/bv-filter-dropdown.d.ts +20 -5
  18. package/dist/components/bv-filter-dropdown/bv-filter-dropdown.js +263 -25
  19. package/dist/components/bv-filter-panel/bv-filter-panel.js +1 -1
  20. package/dist/components/bv-icon/bv-icon.js +1 -0
  21. package/dist/components/bv-input/bv-input.d.ts +24 -0
  22. package/dist/components/bv-input/bv-input.js +148 -0
  23. package/dist/components/bv-input-dropdown/bv-input-dropdown.d.ts +46 -0
  24. package/dist/components/bv-input-dropdown/bv-input-dropdown.js +501 -0
  25. package/dist/components/bv-pagination/bv-pagination.d.ts +13 -1
  26. package/dist/components/bv-pagination/bv-pagination.js +290 -9
  27. package/dist/components/bv-portal-header/bv-portal-header.js +63 -5
  28. package/dist/components/bv-searchbox/bv-searchbox.js +1 -1
  29. package/dist/components/bv-segmented-control/bv-segmented-control.d.ts +26 -0
  30. package/dist/components/bv-segmented-control/bv-segmented-control.js +128 -0
  31. package/dist/components/bv-select/bv-select.d.ts +41 -0
  32. package/dist/components/bv-select/bv-select.js +240 -0
  33. package/dist/components/bv-split-button/bv-split-button.d.ts +37 -0
  34. package/dist/components/bv-split-button/bv-split-button.js +264 -0
  35. package/dist/components/bv-table/bv-table.d.ts +15 -0
  36. package/dist/components/bv-table/bv-table.js +260 -33
  37. package/dist/components/bv-toggle/bv-toggle.d.ts +2 -1
  38. package/dist/components/bv-toggle/bv-toggle.js +2 -2
  39. package/dist/components/bv-tooltip/bv-tooltip.d.ts +18 -0
  40. package/dist/components/bv-tooltip/bv-tooltip.js +144 -0
  41. package/dist/components/bv-user-row/bv-user-row.d.ts +1 -0
  42. package/dist/components/bv-user-row/bv-user-row.js +62 -4
  43. package/dist/storybook/stories/screens/cet-report.data.d.ts +55 -0
  44. package/dist/storybook/stories/screens/cet-report.data.js +3697 -0
  45. package/dist/themes/base.css +14 -1
  46. package/package.json +42 -1
  47. package/themes/base.css +14 -1
@@ -1,5 +1,147 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-table/bv-table.css
2
- var bv_table_default = "bv-table {\n display: block;\n width: 100%;\n overflow-x: auto;\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n font-family: var(--bv-font-family-base);\n}\n\nbv-table table {\n width: 100%;\n border-collapse: collapse;\n min-width: 0;\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\nbv-table thead tr {\n background: var(--bv-color-neutral-100);\n}\n\nbv-table thead th {\n padding: 12px 16px;\n text-align: left;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-500);\n border-bottom: 1px solid var(--bv-color-neutral-200);\n white-space: nowrap;\n user-select: none;\n vertical-align: middle;\n}\n\nbv-table thead th[data-sortable] {\n cursor: pointer;\n}\n\nbv-table thead th[data-sortable]:hover {\n color: var(--bv-color-neutral-700);\n}\n\nbv-table thead th[data-sort='asc'] .bv-sort-icon,\nbv-table thead th[data-sort='desc'] .bv-sort-icon {\n color: var(--bv-color-primary);\n}\n\n.bv-th-content {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.bv-sort-icon {\n width: 14px;\n height: 14px;\n flex-shrink: 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\nbv-table tbody td {\n padding: 12px 16px;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-700);\n border-bottom: 1px solid var(--bv-color-neutral-100);\n vertical-align: middle;\n}\n\nbv-table tbody tr:last-child td {\n border-bottom: none;\n}\n\nbv-table tbody tr:hover td {\n background: var(--bv-color-neutral-100);\n}\n\n/* \u2500\u2500 Modifiers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nbv-table[striped] tbody tr:nth-child(even) td {\n background: var(--bv-color-neutral-100);\n}\n\nbv-table[bordered] thead th,\nbv-table[bordered] tbody td {\n border-right: 1px solid var(--bv-color-neutral-100);\n}\n\nbv-table[bordered] thead th:last-child,\nbv-table[bordered] tbody td:last-child {\n border-right: none;\n}\n\n/* \u2500\u2500 Checkbox column \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nbv-table thead th.bv-col-check,\nbv-table tbody td.bv-col-check {\n width: 48px;\n padding: 12px 16px;\n}\n";
2
+ var bv_table_default = "bv-table {\n display: block;\n width: 100%;\n box-sizing: border-box;\n overflow-x: auto;\n border: 1px solid var(--bv-color-neutral-200);\n font-family: var(--bv-font-family-base);\n cursor: grab;\n}\n\n/* During drag: override cursor for the entire table and all children */\nbv-table[data-dragging],\nbv-table[data-dragging] * {\n cursor: grabbing !important;\n user-select: none !important;\n}\n\nbv-table tbody td {\n cursor: grab;\n}\n\n/* Only the rendered glyphs are text-selectable \u2014 see _enhanceBodyCells in bv-table.ts */\nbv-table tbody td .bv-cell-text {\n cursor: text;\n}\n\nbv-table table {\n width: 100%;\n border-collapse: collapse;\n min-width: 0;\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\nbv-table thead tr {\n background: var(--bv-color-neutral-100);\n}\n\nbv-table thead th {\n padding: 12px 16px;\n text-align: left;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n border-bottom: 1px solid var(--bv-color-neutral-200);\n white-space: nowrap;\n user-select: none;\n vertical-align: middle;\n}\n\nbv-table thead th[data-sortable] {\n cursor: pointer;\n}\n\nbv-table thead th[data-sortable]:hover {\n color: var(--bv-color-neutral-700);\n}\n\nbv-table thead th[data-sort='asc'] .bv-sort-icon,\nbv-table thead th[data-sort='desc'] .bv-sort-icon {\n color: var(--bv-color-primary);\n}\n\n.bv-th-content {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.bv-sort-icon {\n width: 14px;\n height: 14px;\n flex-shrink: 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\nbv-table tbody td {\n padding: 12px 16px;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-700);\n border-bottom: 1px solid var(--bv-color-neutral-100);\n vertical-align: middle;\n white-space: nowrap;\n}\n\nbv-table tbody tr:last-child td {\n border-bottom: none;\n}\n\nbv-table tbody tr:hover td {\n background: var(--bv-color-neutral-100);\n}\n\n/* \u2500\u2500 Column alignment \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nbv-table thead th[data-align='right'],\nbv-table tbody td[data-align='right'] {\n text-align: right;\n}\n\nbv-table thead th[data-align='center'],\nbv-table tbody td[data-align='center'] {\n text-align: center;\n}\n\n/* \u2500\u2500 Cell modifier classes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/* Muted: em dash or empty placeholder */\nbv-table td.bv-cell-muted {\n color: var(--bv-color-neutral-400);\n}\n\n/* Hidden: redacted identity for external users */\nbv-table td.bv-cell-hidden {\n color: var(--bv-color-neutral-400);\n font-style: italic;\n}\n\n/* Colored text for numeric highlight states */\nbv-table td.bv-cell-success {\n color: var(--bv-color-success);\n font-weight: var(--bv-font-weight-medium);\n}\n\nbv-table td.bv-cell-warning {\n color: var(--bv-color-warning);\n font-weight: var(--bv-font-weight-medium);\n}\n\nbv-table td.bv-cell-danger {\n color: var(--bv-color-danger);\n font-weight: var(--bv-font-weight-medium);\n}\n\nbv-table td.bv-cell-info {\n color: var(--bv-color-primary);\n font-weight: var(--bv-font-weight-medium);\n}\n\n/* \u2500\u2500 Modifiers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nbv-table[striped] tbody tr:nth-child(even) td {\n background: var(--bv-color-neutral-100);\n}\n\nbv-table[bordered] thead th,\nbv-table[bordered] tbody td {\n border-right: 1px solid var(--bv-color-neutral-100);\n}\n\nbv-table[bordered] thead th:last-child,\nbv-table[bordered] tbody td:last-child {\n border-right: none;\n}\n\n/* \u2500\u2500 Column divider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nbv-table thead th[data-divider],\nbv-table tbody td[data-divider] {\n border-left: 1px solid var(--bv-color-neutral-200);\n}\n\n/* \u2500\u2500 Checkbox column \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nbv-table thead th.bv-col-check,\nbv-table tbody td.bv-col-check {\n width: 48px;\n padding: 12px 16px;\n}\n";
3
+
4
+ // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-tooltip/bv-tooltip.css
5
+ var bv_tooltip_default = ":host {\n display: inline-flex;\n align-items: center;\n position: relative;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.wrap {\n display: inline-flex;\n align-items: center;\n position: relative;\n}\n\n.trigger {\n display: inline-flex;\n align-items: center;\n cursor: help;\n color: var(--bv-color-neutral-400);\n outline: none;\n border: none;\n background: none;\n padding: 0;\n line-height: 0;\n}\n\n.trigger:hover,\n.trigger:focus {\n color: var(--bv-color-neutral-600);\n}\n\n.trigger svg {\n display: block;\n width: 14px;\n height: 14px;\n}\n\n/* \u2500\u2500 Popup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.popup {\n /* Shown/positioned entirely via JS \u2014 display starts as none */\n display: none;\n position: absolute;\n z-index: 500;\n min-width: 200px;\n max-width: 300px;\n background: var(--bv-color-neutral-900);\n color: var(--bv-color-neutral-0);\n border-radius: var(--bv-radius-md);\n padding: 10px 12px;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-regular);\n line-height: 1.6;\n box-shadow: var(--bv-shadow-lg);\n pointer-events: none;\n white-space: normal;\n}\n\n/* \u2500\u2500 Content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.text-content {\n display: none;\n}\n\n:host([text]) .text-content {\n display: block;\n}\n\n:host([text]) slot {\n display: none;\n}\n\n::slotted(p) {\n margin: 0 0 4px;\n}\n\n::slotted(p:last-child) {\n margin-bottom: 0;\n}\n";
6
+
7
+ // components/bv-tooltip/bv-tooltip.ts
8
+ var QUESTION_MARK_SVG = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>`;
9
+ var _sheet = null;
10
+ function getSheet() {
11
+ if (!_sheet) {
12
+ _sheet = new CSSStyleSheet();
13
+ _sheet.replaceSync(bv_tooltip_default);
14
+ }
15
+ return _sheet;
16
+ }
17
+ var _uid = 0;
18
+ var BvTooltip = class extends HTMLElement {
19
+ static observedAttributes = ["text", "position"];
20
+ _rendered = false;
21
+ _textEl = null;
22
+ _triggerEl = null;
23
+ _popupEl = null;
24
+ constructor() {
25
+ super();
26
+ const shadow = this.attachShadow({ mode: "open" });
27
+ if ("adoptedStyleSheets" in ShadowRoot.prototype) {
28
+ shadow.adoptedStyleSheets = [getSheet()];
29
+ }
30
+ }
31
+ get text() {
32
+ return this.getAttribute("text") ?? "";
33
+ }
34
+ set text(v) {
35
+ this.setAttribute("text", v);
36
+ }
37
+ get position() {
38
+ return this.getAttribute("position") ?? "top";
39
+ }
40
+ set position(v) {
41
+ this.setAttribute("position", v);
42
+ }
43
+ connectedCallback() {
44
+ this._render();
45
+ }
46
+ attributeChangedCallback(name, _old, _val) {
47
+ if (!this._rendered) return;
48
+ if (name === "text" && this._textEl) {
49
+ this._textEl.textContent = this.text;
50
+ }
51
+ }
52
+ _render() {
53
+ if (this._rendered) return;
54
+ this._rendered = true;
55
+ const shadow = this.shadowRoot;
56
+ if (!shadow.adoptedStyleSheets.length) {
57
+ const s = document.createElement("style");
58
+ s.textContent = bv_tooltip_default;
59
+ shadow.appendChild(s);
60
+ }
61
+ const wrap = document.createElement("span");
62
+ wrap.className = "wrap";
63
+ const popupId = `bv-tooltip-popup-${++_uid}`;
64
+ const trigger = document.createElement("span");
65
+ trigger.className = "trigger";
66
+ trigger.setAttribute("tabindex", "0");
67
+ trigger.setAttribute("role", "button");
68
+ trigger.setAttribute("aria-label", "More information");
69
+ trigger.setAttribute("aria-describedby", popupId);
70
+ trigger.innerHTML = QUESTION_MARK_SVG;
71
+ this._triggerEl = trigger;
72
+ const popup = document.createElement("span");
73
+ popup.id = popupId;
74
+ popup.className = "popup";
75
+ popup.setAttribute("role", "tooltip");
76
+ this._popupEl = popup;
77
+ const textEl = document.createElement("span");
78
+ textEl.className = "text-content";
79
+ textEl.textContent = this.text;
80
+ this._textEl = textEl;
81
+ const slot = document.createElement("slot");
82
+ popup.append(textEl, slot);
83
+ wrap.append(trigger, popup);
84
+ shadow.appendChild(wrap);
85
+ trigger.addEventListener("mouseenter", () => this._show());
86
+ trigger.addEventListener("mouseleave", () => this._hide());
87
+ trigger.addEventListener("focus", () => this._show());
88
+ trigger.addEventListener("blur", () => this._hide());
89
+ }
90
+ _show() {
91
+ const popup = this._popupEl;
92
+ const trigger = this._triggerEl;
93
+ if (!popup || !trigger) return;
94
+ popup.style.top = "0";
95
+ popup.style.bottom = "auto";
96
+ popup.style.left = "0";
97
+ popup.style.right = "auto";
98
+ popup.style.transform = "none";
99
+ popup.style.display = "block";
100
+ popup.style.visibility = "hidden";
101
+ const tRect = trigger.getBoundingClientRect();
102
+ const pRect = popup.getBoundingClientRect();
103
+ const vw = window.innerWidth;
104
+ const vh = window.innerHeight;
105
+ const gap = 8;
106
+ const spaceAbove = tRect.top - gap;
107
+ const spaceBelow = vh - tRect.bottom - gap;
108
+ const preferBottom = this.position === "bottom";
109
+ const goBelow = preferBottom ? spaceBelow >= pRect.height || spaceBelow >= spaceAbove : spaceAbove < pRect.height;
110
+ if (goBelow) {
111
+ popup.style.top = "calc(100% + 8px)";
112
+ popup.style.bottom = "auto";
113
+ } else {
114
+ popup.style.bottom = "calc(100% + 8px)";
115
+ popup.style.top = "auto";
116
+ }
117
+ const rawLeft = tRect.left;
118
+ const rawRight = tRect.left + pRect.width;
119
+ let transformX = 0;
120
+ if (rawRight > vw - gap) {
121
+ transformX = vw - gap - rawRight;
122
+ }
123
+ if (rawLeft + transformX < gap) {
124
+ transformX = gap - rawLeft;
125
+ }
126
+ popup.style.left = "0";
127
+ popup.style.transform = transformX !== 0 ? `translateX(${transformX}px)` : "none";
128
+ popup.style.visibility = "";
129
+ }
130
+ _hide() {
131
+ const popup = this._popupEl;
132
+ if (!popup) return;
133
+ popup.style.display = "";
134
+ popup.style.top = "";
135
+ popup.style.bottom = "";
136
+ popup.style.left = "";
137
+ popup.style.right = "";
138
+ popup.style.transform = "";
139
+ popup.style.visibility = "";
140
+ }
141
+ };
142
+ if (!customElements.get("bv-tooltip")) {
143
+ customElements.define("bv-tooltip", BvTooltip);
144
+ }
3
145
 
4
146
  // components/bv-table/bv-table.ts
5
147
  var SORT_NONE = `<svg class="bv-sort-icon" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -11,6 +153,9 @@ var SORT_ASC = `<svg class="bv-sort-icon" viewBox="0 0 16 16" fill="none" xmlns=
11
153
  var SORT_DESC = `<svg class="bv-sort-icon" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
12
154
  <path d="M8 3v10M5 10l3 3 3-3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
13
155
  </svg>`;
156
+ function escapeAttr(s) {
157
+ return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
158
+ }
14
159
  function injectTableStyles() {
15
160
  if (document.getElementById("bv-table-styles")) return;
16
161
  const style = document.createElement("style");
@@ -20,47 +165,129 @@ function injectTableStyles() {
20
165
  }
21
166
  var BvTable = class extends HTMLElement {
22
167
  static observedAttributes = ["striped", "bordered"];
168
+ _isDragging = false;
169
+ _dragStartX = 0;
170
+ _dragScrollLeft = 0;
171
+ _boundMouseDown = (e) => this._onMouseDown(e);
172
+ _boundMouseMove = (e) => this._onMouseMove(e);
173
+ _boundMouseUp = () => this._onMouseUp();
23
174
  connectedCallback() {
24
175
  injectTableStyles();
25
176
  this._enhanceHeaders();
177
+ this._enhanceBodyCells();
178
+ this._setupDrag();
179
+ }
180
+ disconnectedCallback() {
181
+ this._teardownDrag();
182
+ }
183
+ _setupDrag() {
184
+ this.addEventListener("mousedown", this._boundMouseDown);
185
+ window.addEventListener("mousemove", this._boundMouseMove);
186
+ window.addEventListener("mouseup", this._boundMouseUp);
187
+ }
188
+ _teardownDrag() {
189
+ this.removeEventListener("mousedown", this._boundMouseDown);
190
+ window.removeEventListener("mousemove", this._boundMouseMove);
191
+ window.removeEventListener("mouseup", this._boundMouseUp);
192
+ }
193
+ // Wraps each plain-text body cell's content in an inline span. Unlike the
194
+ // <td> itself, an inline span only occupies the rendered width of its text —
195
+ // so hovering the cell's padding (short values, blank space) stays grab-able,
196
+ // and only the glyphs themselves resolve to a text-selectable target.
197
+ _enhanceBodyCells() {
198
+ this.querySelectorAll("tbody td").forEach((td) => {
199
+ if (td.children.length > 0) return;
200
+ const text = td.textContent;
201
+ if (!text || !text.trim()) return;
202
+ const span = document.createElement("span");
203
+ span.className = "bv-cell-text";
204
+ span.textContent = text;
205
+ td.replaceChildren(span);
206
+ });
207
+ }
208
+ _onMouseDown(e) {
209
+ if (e.button !== 0) return;
210
+ if (this._isOverText(e.target)) return;
211
+ this._isDragging = true;
212
+ this._dragStartX = e.pageX;
213
+ this._dragScrollLeft = this.scrollLeft;
214
+ this.setAttribute("data-dragging", "");
215
+ e.preventDefault();
216
+ }
217
+ _onMouseMove(e) {
218
+ if (!this._isDragging) return;
219
+ this.scrollLeft = this._dragScrollLeft - (e.pageX - this._dragStartX);
220
+ }
221
+ _onMouseUp() {
222
+ if (!this._isDragging) return;
223
+ this._isDragging = false;
224
+ this.removeAttribute("data-dragging");
225
+ }
226
+ // Returns true when the mousedown target is rendered text the user may want
227
+ // to select: either a body cell's .bv-cell-text span (see _enhanceBodyCells)
228
+ // or a header cell with a direct text-node child (headers are left unwrapped).
229
+ _isOverText(target) {
230
+ var _a;
231
+ if (!(target instanceof Element)) return false;
232
+ if (target.closest(".bv-cell-text")) return true;
233
+ for (const node of target.childNodes) {
234
+ if (node.nodeType === Node.TEXT_NODE && ((_a = node.textContent) == null ? void 0 : _a.trim())) return true;
235
+ }
236
+ return false;
26
237
  }
27
238
  _enhanceHeaders() {
28
- this.querySelectorAll("thead th[data-sortable]").forEach((th) => {
239
+ this.querySelectorAll("thead th").forEach((th) => {
29
240
  var _a;
241
+ const hasSortable = th.hasAttribute("data-sortable");
242
+ const hasTooltip = th.hasAttribute("data-tooltip");
243
+ if (!hasSortable && !hasTooltip) return;
30
244
  const label = ((_a = th.textContent) == null ? void 0 : _a.trim()) ?? "";
31
- const sortDir = th.getAttribute("data-sort") ?? "none";
32
- const icon = sortDir === "asc" ? SORT_ASC : sortDir === "desc" ? SORT_DESC : SORT_NONE;
33
- th.innerHTML = `<span class="bv-th-content">${label}${icon}</span>`;
34
- th.addEventListener("click", () => {
35
- var _a2, _b, _c, _d;
36
- const current = th.getAttribute("data-sort") ?? "none";
37
- const next = current === "none" ? "asc" : current === "asc" ? "desc" : "none";
38
- this.querySelectorAll("thead th[data-sortable]").forEach((other) => {
39
- var _a3, _b2;
40
- if (other !== th) {
41
- other.removeAttribute("data-sort");
42
- const otherLabel = ((_b2 = (_a3 = other.querySelector(".bv-th-content")) == null ? void 0 : _a3.firstChild) == null ? void 0 : _b2.textContent) ?? "";
43
- other.innerHTML = `<span class="bv-th-content">${otherLabel}${SORT_NONE}</span>`;
245
+ let inner = label;
246
+ if (hasTooltip) {
247
+ const tip = escapeAttr(th.getAttribute("data-tooltip") ?? "");
248
+ inner += `<bv-tooltip text="${tip}" position="bottom"></bv-tooltip>`;
249
+ }
250
+ if (hasSortable) {
251
+ const sortDir = th.getAttribute("data-sort") ?? "none";
252
+ const icon = sortDir === "asc" ? SORT_ASC : sortDir === "desc" ? SORT_DESC : SORT_NONE;
253
+ inner = `<span class="bv-th-content">${inner}${icon}</span>`;
254
+ } else {
255
+ inner = `<span class="bv-th-content">${inner}</span>`;
256
+ }
257
+ th.innerHTML = inner;
258
+ if (hasSortable) {
259
+ th.addEventListener("click", () => {
260
+ var _a2, _b;
261
+ const current = th.getAttribute("data-sort") ?? "none";
262
+ const next = current === "none" ? "asc" : current === "asc" ? "desc" : "none";
263
+ this.querySelectorAll("thead th[data-sortable]").forEach((other) => {
264
+ var _a3, _b2;
265
+ if (other !== th) {
266
+ other.removeAttribute("data-sort");
267
+ const otherLabel = ((_b2 = (_a3 = other.querySelector(".bv-th-content")) == null ? void 0 : _a3.childNodes[0]) == null ? void 0 : _b2.textContent) ?? "";
268
+ const otherTooltip = other.hasAttribute("data-tooltip") ? `<bv-tooltip text="${escapeAttr(other.getAttribute("data-tooltip") ?? "")}" position="bottom"></bv-tooltip>` : "";
269
+ other.innerHTML = `<span class="bv-th-content">${otherLabel}${otherTooltip}${SORT_NONE}</span>`;
270
+ }
271
+ });
272
+ const currentLabel = ((_b = (_a2 = th.querySelector(".bv-th-content")) == null ? void 0 : _a2.childNodes[0]) == null ? void 0 : _b.textContent) ?? label;
273
+ const currentTooltip = hasTooltip ? `<bv-tooltip text="${escapeAttr(th.getAttribute("data-tooltip") ?? "")}" position="bottom"></bv-tooltip>` : "";
274
+ if (next === "none") {
275
+ th.removeAttribute("data-sort");
276
+ th.innerHTML = `<span class="bv-th-content">${currentLabel}${currentTooltip}${SORT_NONE}</span>`;
277
+ } else {
278
+ th.setAttribute("data-sort", next);
279
+ const newIcon = next === "asc" ? SORT_ASC : SORT_DESC;
280
+ th.innerHTML = `<span class="bv-th-content">${currentLabel}${currentTooltip}${newIcon}</span>`;
44
281
  }
282
+ this.dispatchEvent(
283
+ new CustomEvent("bv-sort", {
284
+ bubbles: true,
285
+ composed: true,
286
+ detail: { column: th.getAttribute("data-column"), direction: next }
287
+ })
288
+ );
45
289
  });
46
- if (next === "none") {
47
- th.removeAttribute("data-sort");
48
- const l = ((_b = (_a2 = th.querySelector(".bv-th-content")) == null ? void 0 : _a2.firstChild) == null ? void 0 : _b.textContent) ?? label;
49
- th.innerHTML = `<span class="bv-th-content">${l}${SORT_NONE}</span>`;
50
- } else {
51
- th.setAttribute("data-sort", next);
52
- const newIcon = next === "asc" ? SORT_ASC : SORT_DESC;
53
- const l = ((_d = (_c = th.querySelector(".bv-th-content")) == null ? void 0 : _c.firstChild) == null ? void 0 : _d.textContent) ?? label;
54
- th.innerHTML = `<span class="bv-th-content">${l}${newIcon}</span>`;
55
- }
56
- this.dispatchEvent(
57
- new CustomEvent("bv-sort", {
58
- bubbles: true,
59
- composed: true,
60
- detail: { column: th.getAttribute("data-column"), direction: next }
61
- })
62
- );
63
- });
290
+ }
64
291
  });
65
292
  }
66
293
  };
@@ -1,5 +1,6 @@
1
+ export type ToggleSize = 'sm' | 'md';
1
2
  export declare class BvToggle extends HTMLElement {
2
- static readonly observedAttributes: string[];
3
+ static readonly observedAttributes: readonly ["checked", "disabled", "label", "size"];
3
4
  private _rendered;
4
5
  private _labelEl;
5
6
  constructor();
@@ -1,9 +1,9 @@
1
1
  // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-toggle/bv-toggle.css
2
- 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.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";
2
+ 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";
3
3
 
4
4
  // components/bv-toggle/bv-toggle.ts
5
5
  var BvToggle = class extends HTMLElement {
6
- static observedAttributes = ["checked", "disabled", "label"];
6
+ static observedAttributes = ["checked", "disabled", "label", "size"];
7
7
  _rendered = false;
8
8
  _labelEl = null;
9
9
  constructor() {
@@ -0,0 +1,18 @@
1
+ export type TooltipPosition = 'top' | 'bottom';
2
+ export declare class BvTooltip extends HTMLElement {
3
+ static readonly observedAttributes: readonly ["text", "position"];
4
+ private _rendered;
5
+ private _textEl;
6
+ private _triggerEl;
7
+ private _popupEl;
8
+ constructor();
9
+ get text(): string;
10
+ set text(v: string);
11
+ get position(): TooltipPosition;
12
+ set position(v: TooltipPosition);
13
+ connectedCallback(): void;
14
+ attributeChangedCallback(name: string, _old: string | null, _val: string | null): void;
15
+ private _render;
16
+ private _show;
17
+ private _hide;
18
+ }
@@ -0,0 +1,144 @@
1
+ // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-tooltip/bv-tooltip.css
2
+ var bv_tooltip_default = ":host {\n display: inline-flex;\n align-items: center;\n position: relative;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n.wrap {\n display: inline-flex;\n align-items: center;\n position: relative;\n}\n\n.trigger {\n display: inline-flex;\n align-items: center;\n cursor: help;\n color: var(--bv-color-neutral-400);\n outline: none;\n border: none;\n background: none;\n padding: 0;\n line-height: 0;\n}\n\n.trigger:hover,\n.trigger:focus {\n color: var(--bv-color-neutral-600);\n}\n\n.trigger svg {\n display: block;\n width: 14px;\n height: 14px;\n}\n\n/* \u2500\u2500 Popup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.popup {\n /* Shown/positioned entirely via JS \u2014 display starts as none */\n display: none;\n position: absolute;\n z-index: 500;\n min-width: 200px;\n max-width: 300px;\n background: var(--bv-color-neutral-900);\n color: var(--bv-color-neutral-0);\n border-radius: var(--bv-radius-md);\n padding: 10px 12px;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-regular);\n line-height: 1.6;\n box-shadow: var(--bv-shadow-lg);\n pointer-events: none;\n white-space: normal;\n}\n\n/* \u2500\u2500 Content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.text-content {\n display: none;\n}\n\n:host([text]) .text-content {\n display: block;\n}\n\n:host([text]) slot {\n display: none;\n}\n\n::slotted(p) {\n margin: 0 0 4px;\n}\n\n::slotted(p:last-child) {\n margin-bottom: 0;\n}\n";
3
+
4
+ // components/bv-tooltip/bv-tooltip.ts
5
+ var QUESTION_MARK_SVG = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>`;
6
+ var _sheet = null;
7
+ function getSheet() {
8
+ if (!_sheet) {
9
+ _sheet = new CSSStyleSheet();
10
+ _sheet.replaceSync(bv_tooltip_default);
11
+ }
12
+ return _sheet;
13
+ }
14
+ var _uid = 0;
15
+ var BvTooltip = class extends HTMLElement {
16
+ static observedAttributes = ["text", "position"];
17
+ _rendered = false;
18
+ _textEl = null;
19
+ _triggerEl = null;
20
+ _popupEl = null;
21
+ constructor() {
22
+ super();
23
+ const shadow = this.attachShadow({ mode: "open" });
24
+ if ("adoptedStyleSheets" in ShadowRoot.prototype) {
25
+ shadow.adoptedStyleSheets = [getSheet()];
26
+ }
27
+ }
28
+ get text() {
29
+ return this.getAttribute("text") ?? "";
30
+ }
31
+ set text(v) {
32
+ this.setAttribute("text", v);
33
+ }
34
+ get position() {
35
+ return this.getAttribute("position") ?? "top";
36
+ }
37
+ set position(v) {
38
+ this.setAttribute("position", v);
39
+ }
40
+ connectedCallback() {
41
+ this._render();
42
+ }
43
+ attributeChangedCallback(name, _old, _val) {
44
+ if (!this._rendered) return;
45
+ if (name === "text" && this._textEl) {
46
+ this._textEl.textContent = this.text;
47
+ }
48
+ }
49
+ _render() {
50
+ if (this._rendered) return;
51
+ this._rendered = true;
52
+ const shadow = this.shadowRoot;
53
+ if (!shadow.adoptedStyleSheets.length) {
54
+ const s = document.createElement("style");
55
+ s.textContent = bv_tooltip_default;
56
+ shadow.appendChild(s);
57
+ }
58
+ const wrap = document.createElement("span");
59
+ wrap.className = "wrap";
60
+ const popupId = `bv-tooltip-popup-${++_uid}`;
61
+ const trigger = document.createElement("span");
62
+ trigger.className = "trigger";
63
+ trigger.setAttribute("tabindex", "0");
64
+ trigger.setAttribute("role", "button");
65
+ trigger.setAttribute("aria-label", "More information");
66
+ trigger.setAttribute("aria-describedby", popupId);
67
+ trigger.innerHTML = QUESTION_MARK_SVG;
68
+ this._triggerEl = trigger;
69
+ const popup = document.createElement("span");
70
+ popup.id = popupId;
71
+ popup.className = "popup";
72
+ popup.setAttribute("role", "tooltip");
73
+ this._popupEl = popup;
74
+ const textEl = document.createElement("span");
75
+ textEl.className = "text-content";
76
+ textEl.textContent = this.text;
77
+ this._textEl = textEl;
78
+ const slot = document.createElement("slot");
79
+ popup.append(textEl, slot);
80
+ wrap.append(trigger, popup);
81
+ shadow.appendChild(wrap);
82
+ trigger.addEventListener("mouseenter", () => this._show());
83
+ trigger.addEventListener("mouseleave", () => this._hide());
84
+ trigger.addEventListener("focus", () => this._show());
85
+ trigger.addEventListener("blur", () => this._hide());
86
+ }
87
+ _show() {
88
+ const popup = this._popupEl;
89
+ const trigger = this._triggerEl;
90
+ if (!popup || !trigger) return;
91
+ popup.style.top = "0";
92
+ popup.style.bottom = "auto";
93
+ popup.style.left = "0";
94
+ popup.style.right = "auto";
95
+ popup.style.transform = "none";
96
+ popup.style.display = "block";
97
+ popup.style.visibility = "hidden";
98
+ const tRect = trigger.getBoundingClientRect();
99
+ const pRect = popup.getBoundingClientRect();
100
+ const vw = window.innerWidth;
101
+ const vh = window.innerHeight;
102
+ const gap = 8;
103
+ const spaceAbove = tRect.top - gap;
104
+ const spaceBelow = vh - tRect.bottom - gap;
105
+ const preferBottom = this.position === "bottom";
106
+ const goBelow = preferBottom ? spaceBelow >= pRect.height || spaceBelow >= spaceAbove : spaceAbove < pRect.height;
107
+ if (goBelow) {
108
+ popup.style.top = "calc(100% + 8px)";
109
+ popup.style.bottom = "auto";
110
+ } else {
111
+ popup.style.bottom = "calc(100% + 8px)";
112
+ popup.style.top = "auto";
113
+ }
114
+ const rawLeft = tRect.left;
115
+ const rawRight = tRect.left + pRect.width;
116
+ let transformX = 0;
117
+ if (rawRight > vw - gap) {
118
+ transformX = vw - gap - rawRight;
119
+ }
120
+ if (rawLeft + transformX < gap) {
121
+ transformX = gap - rawLeft;
122
+ }
123
+ popup.style.left = "0";
124
+ popup.style.transform = transformX !== 0 ? `translateX(${transformX}px)` : "none";
125
+ popup.style.visibility = "";
126
+ }
127
+ _hide() {
128
+ const popup = this._popupEl;
129
+ if (!popup) return;
130
+ popup.style.display = "";
131
+ popup.style.top = "";
132
+ popup.style.bottom = "";
133
+ popup.style.left = "";
134
+ popup.style.right = "";
135
+ popup.style.transform = "";
136
+ popup.style.visibility = "";
137
+ }
138
+ };
139
+ if (!customElements.get("bv-tooltip")) {
140
+ customElements.define("bv-tooltip", BvTooltip);
141
+ }
142
+ export {
143
+ BvTooltip
144
+ };
@@ -1,5 +1,6 @@
1
1
  import '../bv-avatar/bv-avatar.ts';
2
2
  import '../bv-button/bv-button.ts';
3
+ import '../bv-icon/bv-icon.ts';
3
4
  export type UserRowEditProfileTarget = '_self' | '_blank' | '_parent' | '_top' | '';
4
5
  export declare class BvUserRow extends HTMLElement {
5
6
  static readonly observedAttributes: string[];