@bluevolt-tech/lumen 1.5.2 → 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 (44) 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 +1 -1
  7. package/dist/components/bv-checkbox/bv-checkbox.js +1 -1
  8. package/dist/components/bv-course-detail-modal/bv-course-detail-modal.js +1 -1
  9. package/dist/components/bv-course-grid-card/bv-course-grid-card.js +1 -1
  10. package/dist/components/bv-course-list-card/bv-course-list-card.js +1 -1
  11. package/dist/components/bv-date-range-input/bv-date-range-input.d.ts +23 -0
  12. package/dist/components/bv-date-range-input/bv-date-range-input.js +950 -0
  13. package/dist/components/bv-date-range-picker/bv-date-range-picker.d.ts +56 -0
  14. package/dist/components/bv-date-range-picker/bv-date-range-picker.js +778 -0
  15. package/dist/components/bv-empty-state/bv-empty-state.js +1 -1
  16. package/dist/components/bv-filter-dropdown/bv-filter-dropdown.d.ts +20 -5
  17. package/dist/components/bv-filter-dropdown/bv-filter-dropdown.js +263 -25
  18. package/dist/components/bv-filter-panel/bv-filter-panel.js +1 -1
  19. package/dist/components/bv-input/bv-input.d.ts +24 -0
  20. package/dist/components/bv-input/bv-input.js +148 -0
  21. package/dist/components/bv-input-dropdown/bv-input-dropdown.d.ts +46 -0
  22. package/dist/components/bv-input-dropdown/bv-input-dropdown.js +501 -0
  23. package/dist/components/bv-pagination/bv-pagination.d.ts +13 -1
  24. package/dist/components/bv-pagination/bv-pagination.js +290 -9
  25. package/dist/components/bv-portal-header/bv-portal-header.js +2 -2
  26. package/dist/components/bv-searchbox/bv-searchbox.js +1 -1
  27. package/dist/components/bv-segmented-control/bv-segmented-control.d.ts +26 -0
  28. package/dist/components/bv-segmented-control/bv-segmented-control.js +128 -0
  29. package/dist/components/bv-select/bv-select.d.ts +41 -0
  30. package/dist/components/bv-select/bv-select.js +240 -0
  31. package/dist/components/bv-split-button/bv-split-button.d.ts +37 -0
  32. package/dist/components/bv-split-button/bv-split-button.js +264 -0
  33. package/dist/components/bv-table/bv-table.d.ts +15 -0
  34. package/dist/components/bv-table/bv-table.js +260 -33
  35. package/dist/components/bv-toggle/bv-toggle.d.ts +2 -1
  36. package/dist/components/bv-toggle/bv-toggle.js +2 -2
  37. package/dist/components/bv-tooltip/bv-tooltip.d.ts +18 -0
  38. package/dist/components/bv-tooltip/bv-tooltip.js +144 -0
  39. package/dist/components/bv-user-row/bv-user-row.js +1 -1
  40. package/dist/storybook/stories/screens/cet-report.data.d.ts +55 -0
  41. package/dist/storybook/stories/screens/cet-report.data.js +3697 -0
  42. package/dist/themes/base.css +14 -1
  43. package/package.json +42 -1
  44. package/themes/base.css +14 -1
@@ -0,0 +1,950 @@
1
+ // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-date-range-input/bv-date-range-input.css
2
+ var bv_date_range_input_default = ":host {\n display: block;\n position: relative;\n font-family: var(--bv-font-family-base);\n}\n\n/* \u2500\u2500 Label \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.field-label {\n display: block;\n font-size: var(--bv-font-size-sm);\n 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.trigger-display {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.trigger-display.is-placeholder {\n color: var(--bv-color-neutral-400);\n}\n\n.trigger-icon {\n display: flex;\n flex-shrink: 0;\n margin-left: var(--bv-spacing-sm);\n color: var(--bv-color-neutral-400);\n transition: color var(--bv-transition-fast);\n}\n\n:host([open]) .trigger-icon {\n color: var(--bv-color-primary);\n}\n\n/* \u2500\u2500 Picker 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 */\n\n.picker-popup {\n display: none;\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: 300;\n}\n\n:host([open]) .picker-popup {\n display: block;\n}\n";
3
+
4
+ // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-date-range-picker/bv-date-range-picker.css
5
+ var bv_date_range_picker_default = ":host {\n display: inline-block;\n font-family: var(--bv-font-family-base);\n}\n\n/* \u2500\u2500 Picker shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.picker {\n display: flex;\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-xl);\n box-shadow: var(--bv-shadow-lg);\n overflow: hidden;\n user-select: none;\n}\n\n/* \u2500\u2500 Sidebar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.sidebar {\n display: flex;\n flex-direction: column;\n width: 152px;\n flex-shrink: 0;\n padding: var(--bv-spacing-sm) 0;\n border-right: 1px solid var(--bv-color-neutral-200);\n}\n\n.preset-btn {\n display: block;\n width: 100%;\n padding: 10px var(--bv-spacing-md);\n text-align: left;\n background: none;\n border: none;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n color var(--bv-transition-fast);\n white-space: nowrap;\n}\n\n.preset-btn:hover {\n background: var(--bv-color-secondary);\n color: var(--bv-color-neutral-900);\n}\n\n.sidebar-sep {\n margin: var(--bv-spacing-xs) 0;\n border: none;\n border-top: 1px solid var(--bv-color-neutral-200);\n}\n\n.preset-btn.active {\n background: var(--bv-color-secondary-light);\n color: var(--bv-color-neutral-900);\n font-weight: var(--bv-font-weight-medium);\n}\n\n/* \u2500\u2500 Main 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 */\n\n.main {\n display: flex;\n flex-direction: column;\n flex: 1;\n}\n\n/* \u2500\u2500 Calendars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.calendars {\n display: flex;\n border-bottom: 1px solid var(--bv-color-neutral-200);\n}\n\n.calendar {\n padding: var(--bv-spacing-md) var(--bv-spacing-lg);\n flex: 1;\n}\n\n.calendar--left {\n border-right: 1px solid var(--bv-color-neutral-200);\n}\n\n/* \u2500\u2500 Calendar 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 */\n\n.calendar-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--bv-spacing-md);\n}\n\n.calendar-title {\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-800);\n}\n\n.nav-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--bv-radius-md);\n color: var(--bv-color-neutral-500);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n color var(--bv-transition-fast);\n flex-shrink: 0;\n}\n\n.nav-btn:hover {\n background: var(--bv-color-secondary);\n color: var(--bv-color-neutral-800);\n}\n\n/* \u2500\u2500 Weekdays row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.weekdays {\n display: grid;\n grid-template-columns: repeat(7, 36px);\n gap: 0;\n margin-bottom: var(--bv-spacing-xs);\n}\n\n.weekday {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 28px;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-500);\n}\n\n/* \u2500\u2500 Days grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.days-grid {\n display: grid;\n grid-template-columns: repeat(7, 36px);\n gap: 0;\n}\n\n/* \u2500\u2500 Day cell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.day {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n padding: 0;\n border: none;\n background: none;\n cursor: pointer;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n border-radius: 0;\n transition: background var(--bv-transition-fast);\n}\n\n.day:hover:not(.start):not(.end) .day-inner {\n background: var(--bv-color-secondary);\n color: var(--bv-color-neutral-900);\n}\n\n.day--blank {\n pointer-events: none;\n}\n\n.day.today:not(.start):not(.end) .day-inner::after {\n content: '';\n position: absolute;\n bottom: 2px;\n left: 50%;\n transform: translateX(-50%);\n width: 4px;\n height: 4px;\n border-radius: var(--bv-radius-full);\n background: var(--bv-color-primary);\n}\n\n/* \u2500\u2500 Range band \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.day.in-range {\n background: var(--bv-color-primary-light);\n}\n\n.day.in-range.week-start,\n.day.range-end.week-start {\n border-radius: var(--bv-radius-full) 0 0 var(--bv-radius-full);\n}\n\n.day.in-range.week-end,\n.day.range-start.week-end {\n border-radius: 0 var(--bv-radius-full) var(--bv-radius-full) 0;\n}\n\n.day.range-start {\n background: linear-gradient(to right, transparent 50%, var(--bv-color-primary-light) 50%);\n}\n\n.day.range-end {\n background: linear-gradient(to left, transparent 50%, var(--bv-color-primary-light) 50%);\n}\n\n/* \u2500\u2500 Day inner (circle) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.day-inner {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border-radius: var(--bv-radius-full);\n z-index: 1;\n transition:\n background var(--bv-transition-fast),\n color var(--bv-transition-fast);\n}\n\n.day.start .day-inner,\n.day.end .day-inner {\n background: var(--bv-color-primary);\n color: var(--bv-color-neutral-0);\n font-weight: var(--bv-font-weight-semibold);\n}\n\n.day.start:hover .day-inner,\n.day.end:hover .day-inner {\n background: var(--bv-color-primary-dark);\n}\n\n/* \u2500\u2500 5-year warning banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.banner-wrap {\n display: none;\n padding: var(--bv-spacing-lg);\n}\n\n.picker--with-banner .banner-wrap {\n display: block;\n}\n\n/* Footer loses its top padding when the banner is shown above it */\n.picker--with-banner .footer {\n padding-top: 0;\n}\n\n/* \u2500\u2500 Footer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--bv-spacing-lg);\n gap: var(--bv-spacing-md);\n}\n\n/* \u2500\u2500 Date inputs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.date-inputs {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n}\n\n.date-input {\n width: 112px;\n height: 36px;\n padding: 0 var(--bv-spacing-sm);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-lg);\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-700);\n text-align: center;\n outline: none;\n transition:\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n.date-input:focus {\n border-color: var(--bv-color-primary);\n box-shadow: 0 0 0 3px var(--bv-color-primary-light);\n}\n\n.date-input::placeholder {\n color: var(--bv-color-neutral-400);\n}\n\n.date-sep {\n color: var(--bv-color-neutral-400);\n font-size: var(--bv-font-size-sm);\n}\n\n/* \u2500\u2500 Action 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\u2500\u2500 */\n\n.footer-actions {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-sm);\n flex-shrink: 0;\n}\n\n.btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 0 var(--bv-spacing-md);\n border-radius: var(--bv-radius-lg);\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n cursor: pointer;\n white-space: nowrap;\n transition:\n background var(--bv-transition-fast),\n border-color var(--bv-transition-fast),\n color var(--bv-transition-fast);\n}\n\n.btn-cancel {\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-300);\n color: var(--bv-color-neutral-700);\n}\n\n.btn-cancel:hover {\n background: var(--bv-color-secondary);\n border-color: var(--bv-color-neutral-400);\n}\n\n.btn-apply {\n background: var(--bv-color-primary);\n border: 1px solid var(--bv-color-primary);\n color: var(--bv-color-neutral-0);\n}\n\n.btn-apply:hover:not(:disabled) {\n background: var(--bv-color-primary-dark);\n border-color: var(--bv-color-primary-dark);\n}\n\n.btn-apply:disabled {\n background: var(--bv-color-neutral-300);\n border-color: var(--bv-color-neutral-300);\n cursor: not-allowed;\n}\n";
6
+
7
+ // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-alert-banner/bv-alert-banner.css
8
+ var bv_alert_banner_default = ":host {\n --banner-bg: var(--bv-color-neutral-0);\n --banner-border: var(--bv-color-neutral-200);\n --banner-color: var(--bv-color-neutral-700);\n --banner-color-subtle: var(--bv-color-neutral-500);\n --banner-icon-color: var(--bv-color-neutral-500);\n\n display: block;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host([variant='primary']) {\n --banner-bg: var(--bv-color-primary-50);\n --banner-border: color-mix(in srgb, var(--bv-color-primary) 40%, var(--bv-color-neutral-0));\n --banner-color: var(--bv-color-primary);\n --banner-color-subtle: var(--bv-color-primary);\n --banner-icon-color: var(--bv-color-primary);\n}\n\n:host([variant='error']) {\n --banner-bg: color-mix(in srgb, var(--bv-color-danger-light) 35%, var(--bv-color-neutral-0));\n --banner-border: color-mix(in srgb, var(--bv-color-danger) 45%, var(--bv-color-neutral-0));\n --banner-color: var(--bv-color-danger-dark);\n --banner-color-subtle: var(--bv-color-danger-dark);\n --banner-icon-color: var(--bv-color-danger);\n}\n\n:host([variant='warning']) {\n --banner-bg: color-mix(in srgb, var(--bv-color-warning-light) 35%, var(--bv-color-neutral-0));\n --banner-border: color-mix(in srgb, var(--bv-color-warning) 50%, var(--bv-color-neutral-0));\n --banner-color: var(--bv-color-warning-dark);\n --banner-color-subtle: var(--bv-color-warning-dark);\n --banner-icon-color: var(--bv-color-warning);\n}\n\n:host([variant='success']) {\n --banner-bg: color-mix(in srgb, var(--bv-color-success-light) 30%, var(--bv-color-neutral-0));\n --banner-border: color-mix(in srgb, var(--bv-color-success) 40%, var(--bv-color-neutral-0));\n --banner-color: var(--bv-color-success-dark);\n --banner-color-subtle: var(--bv-color-success-dark);\n --banner-icon-color: var(--bv-color-success);\n}\n\n/* \u2500\u2500 Banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.banner {\n display: flex;\n align-items: flex-start;\n gap: var(--bv-spacing-md);\n padding: var(--bv-spacing-md);\n background: var(--banner-bg);\n border: 1px solid var(--banner-border);\n border-radius: var(--bv-radius-xl);\n}\n\n/* \u2500\u2500 Icon \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.banner-icon {\n display: flex;\n flex-shrink: 0;\n margin-top: 0;\n color: var(--banner-icon-color);\n line-height: 0;\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 */\n\n.banner-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-xs);\n min-width: 0;\n}\n\n.banner-heading {\n margin: 0;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n line-height: 20px;\n color: var(--banner-color);\n}\n\n.banner-heading[hidden] {\n display: none;\n}\n\n.banner-message {\n margin: 0;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n line-height: 20px;\n color: var(--banner-color);\n}\n\n.banner-message[hidden] {\n display: none;\n}\n\n/* \u2500\u2500 Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.banner-actions {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-md);\n margin-top: var(--bv-spacing-xs);\n}\n\n.banner-actions[hidden] {\n display: none;\n}\n\n.action-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-semibold);\n line-height: 20px;\n color: var(--banner-color);\n transition: opacity 0.15s;\n}\n\n.action-btn[hidden] {\n display: none;\n}\n\n.action-btn:hover {\n opacity: 0.75;\n}\n\n.action-btn:focus-visible {\n outline: 2px solid var(--banner-color);\n outline-offset: 2px;\n border-radius: var(--bv-radius-sm);\n}\n\n/* \u2500\u2500 Close button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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.close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n margin: -6px -6px 0 0;\n background: none;\n border: none;\n border-radius: var(--bv-radius-lg);\n cursor: pointer;\n color: var(--banner-icon-color);\n transition: background 0.15s;\n padding: 0;\n}\n\n.close-btn[hidden] {\n display: none;\n}\n\n.close-btn:hover {\n background: color-mix(in srgb, var(--banner-border) 60%, var(--banner-bg));\n}\n\n.close-btn:focus-visible {\n outline: 2px solid var(--banner-color);\n outline-offset: 2px;\n}\n";
9
+
10
+ // components/bv-alert-banner/bv-alert-banner.ts
11
+ var ICON_INFO = `<svg width="20" height="20" 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"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>`;
12
+ var ICON_ALERT_CIRCLE = `<svg width="20" height="20" 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"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>`;
13
+ var ICON_ALERT_TRIANGLE = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>`;
14
+ var ICON_CHECK_CIRCLE = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>`;
15
+ var ICON_X = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`;
16
+ var ICON_ARROW_RIGHT = `<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"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>`;
17
+ var VARIANT_ICONS = {
18
+ default: ICON_INFO,
19
+ primary: ICON_INFO,
20
+ error: ICON_ALERT_CIRCLE,
21
+ warning: ICON_ALERT_TRIANGLE,
22
+ success: ICON_CHECK_CIRCLE
23
+ };
24
+ var _sheet = null;
25
+ function getSheet() {
26
+ if (!_sheet) {
27
+ _sheet = new CSSStyleSheet();
28
+ _sheet.replaceSync(bv_alert_banner_default);
29
+ }
30
+ return _sheet;
31
+ }
32
+ var BvAlertBanner = class extends HTMLElement {
33
+ static observedAttributes = [
34
+ "variant",
35
+ "heading",
36
+ "message",
37
+ "dismissable",
38
+ "action-label",
39
+ "secondary-action-label"
40
+ ];
41
+ _rendered = false;
42
+ _iconEl = null;
43
+ _headingEl = null;
44
+ _messageEl = null;
45
+ _actionsEl = null;
46
+ _primaryActionBtn = null;
47
+ _secondaryActionBtn = null;
48
+ _closeBtn = null;
49
+ constructor() {
50
+ super();
51
+ const shadow = this.attachShadow({ mode: "open" });
52
+ if ("adoptedStyleSheets" in ShadowRoot.prototype) {
53
+ shadow.adoptedStyleSheets = [getSheet()];
54
+ }
55
+ }
56
+ get variant() {
57
+ return this.getAttribute("variant") ?? "default";
58
+ }
59
+ set variant(v) {
60
+ this.setAttribute("variant", v);
61
+ }
62
+ get heading() {
63
+ return this.getAttribute("heading") ?? "";
64
+ }
65
+ set heading(v) {
66
+ this.setAttribute("heading", v);
67
+ }
68
+ get message() {
69
+ return this.getAttribute("message") ?? "";
70
+ }
71
+ set message(v) {
72
+ this.setAttribute("message", v);
73
+ }
74
+ get dismissable() {
75
+ return this.hasAttribute("dismissable");
76
+ }
77
+ set dismissable(v) {
78
+ if (v) this.setAttribute("dismissable", "");
79
+ else this.removeAttribute("dismissable");
80
+ }
81
+ get actionLabel() {
82
+ return this.getAttribute("action-label") ?? "";
83
+ }
84
+ set actionLabel(v) {
85
+ this.setAttribute("action-label", v);
86
+ }
87
+ get secondaryActionLabel() {
88
+ return this.getAttribute("secondary-action-label") ?? "";
89
+ }
90
+ set secondaryActionLabel(v) {
91
+ this.setAttribute("secondary-action-label", v);
92
+ }
93
+ connectedCallback() {
94
+ this._render();
95
+ }
96
+ attributeChangedCallback(name, _old, _val) {
97
+ if (!this._rendered) return;
98
+ if (name === "variant") this._syncVariant();
99
+ if (name === "heading") this._syncHeading();
100
+ if (name === "message") this._syncMessage();
101
+ if (name === "dismissable") this._syncClose();
102
+ if (name === "action-label" || name === "secondary-action-label") this._syncActions();
103
+ }
104
+ _render() {
105
+ if (this._rendered) return;
106
+ this._rendered = true;
107
+ const shadow = this.shadowRoot;
108
+ if (!shadow.adoptedStyleSheets.length) {
109
+ const s = document.createElement("style");
110
+ s.textContent = bv_alert_banner_default;
111
+ shadow.appendChild(s);
112
+ }
113
+ const banner = document.createElement("div");
114
+ banner.className = "banner";
115
+ banner.setAttribute("role", "alert");
116
+ const iconWrap = document.createElement("span");
117
+ iconWrap.className = "banner-icon";
118
+ this._iconEl = iconWrap;
119
+ const content = document.createElement("div");
120
+ content.className = "banner-content";
121
+ const heading = document.createElement("p");
122
+ heading.className = "banner-heading";
123
+ this._headingEl = heading;
124
+ const message = document.createElement("p");
125
+ message.className = "banner-message";
126
+ this._messageEl = message;
127
+ const actions = document.createElement("div");
128
+ actions.className = "banner-actions";
129
+ this._actionsEl = actions;
130
+ const primaryBtn = document.createElement("button");
131
+ primaryBtn.type = "button";
132
+ primaryBtn.className = "action-btn action-btn--primary";
133
+ primaryBtn.addEventListener("click", () => {
134
+ this.dispatchEvent(
135
+ new CustomEvent("bv-action", {
136
+ bubbles: true,
137
+ composed: true,
138
+ detail: { action: "primary" }
139
+ })
140
+ );
141
+ });
142
+ this._primaryActionBtn = primaryBtn;
143
+ const secondaryBtn = document.createElement("button");
144
+ secondaryBtn.type = "button";
145
+ secondaryBtn.className = "action-btn action-btn--secondary";
146
+ secondaryBtn.addEventListener("click", () => {
147
+ this.dispatchEvent(
148
+ new CustomEvent("bv-action", {
149
+ bubbles: true,
150
+ composed: true,
151
+ detail: { action: "secondary" }
152
+ })
153
+ );
154
+ });
155
+ this._secondaryActionBtn = secondaryBtn;
156
+ actions.append(primaryBtn, secondaryBtn);
157
+ content.append(heading, message, actions);
158
+ const closeBtn = document.createElement("button");
159
+ closeBtn.type = "button";
160
+ closeBtn.className = "close-btn";
161
+ closeBtn.setAttribute("aria-label", "Dismiss");
162
+ closeBtn.innerHTML = ICON_X;
163
+ closeBtn.addEventListener("click", () => {
164
+ this.dispatchEvent(new CustomEvent("bv-dismiss", { bubbles: true, composed: true }));
165
+ });
166
+ this._closeBtn = closeBtn;
167
+ banner.append(iconWrap, content, closeBtn);
168
+ shadow.appendChild(banner);
169
+ this._syncVariant();
170
+ this._syncHeading();
171
+ this._syncMessage();
172
+ this._syncActions();
173
+ this._syncClose();
174
+ }
175
+ _syncVariant() {
176
+ if (!this._iconEl) return;
177
+ const v = this.variant;
178
+ this._iconEl.innerHTML = VARIANT_ICONS[v] ?? ICON_INFO;
179
+ }
180
+ _syncHeading() {
181
+ if (!this._headingEl) return;
182
+ const text = this.heading;
183
+ this._headingEl.textContent = text;
184
+ this._headingEl.hidden = !text;
185
+ }
186
+ _syncMessage() {
187
+ if (!this._messageEl) return;
188
+ const text = this.message;
189
+ this._messageEl.textContent = text;
190
+ this._messageEl.hidden = !text;
191
+ }
192
+ _syncActions() {
193
+ if (!this._actionsEl || !this._primaryActionBtn || !this._secondaryActionBtn) return;
194
+ const primary = this.actionLabel;
195
+ const secondary = this.secondaryActionLabel;
196
+ this._primaryActionBtn.textContent = primary;
197
+ this._primaryActionBtn.hidden = !primary;
198
+ this._secondaryActionBtn.innerHTML = secondary ? `<span>${secondary}</span>${ICON_ARROW_RIGHT}` : "";
199
+ this._secondaryActionBtn.hidden = !secondary;
200
+ this._actionsEl.hidden = !primary && !secondary;
201
+ }
202
+ _syncClose() {
203
+ if (!this._closeBtn) return;
204
+ this._closeBtn.hidden = !this.dismissable;
205
+ }
206
+ };
207
+ if (!customElements.get("bv-alert-banner")) {
208
+ customElements.define("bv-alert-banner", BvAlertBanner);
209
+ }
210
+
211
+ // components/bv-date-range-picker/bv-date-range-picker.ts
212
+ var PRESETS = [
213
+ { key: "last-30-days", label: "Last 30 Days" },
214
+ { key: "last-90-days", label: "Last 90 Days" },
215
+ { key: "last-365-days", label: "Last 365 Days", separator: true },
216
+ { key: "last-month", label: "Last Month" },
217
+ { key: "last-quarter", label: "Last Quarter" },
218
+ { key: "last-year", label: "Last Year" },
219
+ { key: "year-to-date", label: "Year to Date", separator: true },
220
+ { key: "custom", label: "Custom Range" }
221
+ ];
222
+ var MONTH_NAMES = [
223
+ "January",
224
+ "February",
225
+ "March",
226
+ "April",
227
+ "May",
228
+ "June",
229
+ "July",
230
+ "August",
231
+ "September",
232
+ "October",
233
+ "November",
234
+ "December"
235
+ ];
236
+ var WEEKDAYS = ["Mo", "Tu", "We", "Th", "Fr", "Sat", "Su"];
237
+ var CHEVRON_LEFT = `<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"><path d="M15 18l-6-6 6-6"/></svg>`;
238
+ var CHEVRON_RIGHT = `<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"><path d="M9 18l6-6-6-6"/></svg>`;
239
+ var _sheet2 = null;
240
+ function getSheet2() {
241
+ if (!_sheet2) {
242
+ _sheet2 = new CSSStyleSheet();
243
+ _sheet2.replaceSync(bv_date_range_picker_default);
244
+ }
245
+ return _sheet2;
246
+ }
247
+ function dateToIso(d) {
248
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
249
+ }
250
+ function formatDisplay(iso) {
251
+ if (!iso) return "";
252
+ const [y, m, d] = iso.split("-");
253
+ return `${m}/${d}/${y}`;
254
+ }
255
+ function parseDisplay(str) {
256
+ const match = str.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
257
+ if (!match) return "";
258
+ const m = match[1].padStart(2, "0");
259
+ const d = match[2].padStart(2, "0");
260
+ return `${match[3]}-${m}-${d}`;
261
+ }
262
+ function getPresetDates(key) {
263
+ const now = /* @__PURE__ */ new Date();
264
+ now.setHours(0, 0, 0, 0);
265
+ const today = dateToIso(now);
266
+ switch (key) {
267
+ case "last-30-days": {
268
+ const s = new Date(now);
269
+ s.setDate(s.getDate() - 29);
270
+ return { start: dateToIso(s), end: today };
271
+ }
272
+ case "last-90-days": {
273
+ const s = new Date(now);
274
+ s.setDate(s.getDate() - 89);
275
+ return { start: dateToIso(s), end: today };
276
+ }
277
+ case "last-365-days": {
278
+ const s = new Date(now);
279
+ s.setDate(s.getDate() - 364);
280
+ return { start: dateToIso(s), end: today };
281
+ }
282
+ case "last-month": {
283
+ const s = new Date(now.getFullYear(), now.getMonth() - 1, 1);
284
+ const e = new Date(now.getFullYear(), now.getMonth(), 0);
285
+ return { start: dateToIso(s), end: dateToIso(e) };
286
+ }
287
+ case "last-quarter": {
288
+ const q = Math.floor(now.getMonth() / 3);
289
+ const qs = q === 0 ? new Date(now.getFullYear() - 1, 9, 1) : new Date(now.getFullYear(), (q - 1) * 3, 1);
290
+ const qe = new Date(qs.getFullYear(), qs.getMonth() + 3, 0);
291
+ return { start: dateToIso(qs), end: dateToIso(qe) };
292
+ }
293
+ case "last-year": {
294
+ const y = now.getFullYear() - 1;
295
+ return { start: `${y}-01-01`, end: `${y}-12-31` };
296
+ }
297
+ case "year-to-date":
298
+ return { start: `${now.getFullYear()}-01-01`, end: today };
299
+ default:
300
+ return { start: "", end: "" };
301
+ }
302
+ }
303
+ var BvDateRangePicker = class extends HTMLElement {
304
+ static observedAttributes = ["start", "end", "preset"];
305
+ _rendered = false;
306
+ _today;
307
+ _start = "";
308
+ _end = "";
309
+ _preset = "";
310
+ _picking = false;
311
+ _hover = "";
312
+ _leftYear;
313
+ _leftMonth;
314
+ _leftGrid = null;
315
+ _rightGrid = null;
316
+ _leftTitle = null;
317
+ _rightTitle = null;
318
+ _startInput = null;
319
+ _endInput = null;
320
+ _applyBtn = null;
321
+ _bannerEl = null;
322
+ _leftDayMap = /* @__PURE__ */ new Map();
323
+ _rightDayMap = /* @__PURE__ */ new Map();
324
+ constructor() {
325
+ super();
326
+ const now = /* @__PURE__ */ new Date();
327
+ now.setHours(0, 0, 0, 0);
328
+ this._today = dateToIso(now);
329
+ this._leftYear = now.getFullYear();
330
+ this._leftMonth = now.getMonth();
331
+ const shadow = this.attachShadow({ mode: "open" });
332
+ if ("adoptedStyleSheets" in ShadowRoot.prototype) {
333
+ shadow.adoptedStyleSheets = [getSheet2()];
334
+ }
335
+ }
336
+ get start() {
337
+ return this._start;
338
+ }
339
+ set start(v) {
340
+ this.setAttribute("start", v);
341
+ }
342
+ get end() {
343
+ return this._end;
344
+ }
345
+ set end(v) {
346
+ this.setAttribute("end", v);
347
+ }
348
+ get preset() {
349
+ return this._preset;
350
+ }
351
+ set preset(v) {
352
+ this.setAttribute("preset", v);
353
+ }
354
+ connectedCallback() {
355
+ this._render();
356
+ }
357
+ attributeChangedCallback(name, _old, val) {
358
+ if (name === "start") this._start = val ?? "";
359
+ if (name === "end") this._end = val ?? "";
360
+ if (name === "preset") this._preset = val ?? "";
361
+ if (!this._rendered) return;
362
+ this._syncCalendars();
363
+ this._syncInputs();
364
+ this._syncPresets();
365
+ this._syncApply();
366
+ }
367
+ _render() {
368
+ if (this._rendered) return;
369
+ this._rendered = true;
370
+ this._start = this.getAttribute("start") ?? "";
371
+ this._end = this.getAttribute("end") ?? "";
372
+ this._preset = this.getAttribute("preset") ?? "";
373
+ if (this._start) {
374
+ const parts = this._start.split("-");
375
+ const y = parseInt(parts[0], 10);
376
+ const m = parseInt(parts[1], 10) - 1;
377
+ if (!isNaN(y) && !isNaN(m)) {
378
+ this._leftYear = y;
379
+ this._leftMonth = m;
380
+ }
381
+ }
382
+ const shadow = this.shadowRoot;
383
+ if (!shadow.adoptedStyleSheets.length) {
384
+ const s = document.createElement("style");
385
+ s.textContent = bv_date_range_picker_default;
386
+ shadow.appendChild(s);
387
+ }
388
+ const picker = document.createElement("div");
389
+ picker.className = "picker";
390
+ const sidebar = document.createElement("div");
391
+ sidebar.className = "sidebar";
392
+ for (const p of PRESETS) {
393
+ const btn = document.createElement("button");
394
+ btn.type = "button";
395
+ btn.className = "preset-btn";
396
+ btn.dataset["preset"] = p.key;
397
+ btn.textContent = p.label;
398
+ btn.addEventListener("click", () => this._selectPreset(p.key));
399
+ sidebar.appendChild(btn);
400
+ if (p.separator) {
401
+ const hr = document.createElement("hr");
402
+ hr.className = "sidebar-sep";
403
+ sidebar.appendChild(hr);
404
+ }
405
+ }
406
+ const main = document.createElement("div");
407
+ main.className = "main";
408
+ const calsWrap = document.createElement("div");
409
+ calsWrap.className = "calendars";
410
+ calsWrap.append(this._buildCalendarShell("left"), this._buildCalendarShell("right"));
411
+ const footer = document.createElement("div");
412
+ footer.className = "footer";
413
+ const inputsWrap = document.createElement("div");
414
+ inputsWrap.className = "date-inputs";
415
+ const startInput = document.createElement("input");
416
+ startInput.type = "text";
417
+ startInput.className = "date-input";
418
+ startInput.placeholder = "MM/DD/YYYY";
419
+ startInput.setAttribute("aria-label", "Start date");
420
+ startInput.addEventListener("blur", () => this._onInputBlur(startInput, "start"));
421
+ this._setupDateMask(startInput, "start");
422
+ this._startInput = startInput;
423
+ const sep = document.createElement("span");
424
+ sep.className = "date-sep";
425
+ sep.textContent = "\u2013";
426
+ sep.setAttribute("aria-hidden", "true");
427
+ const endInput = document.createElement("input");
428
+ endInput.type = "text";
429
+ endInput.className = "date-input";
430
+ endInput.placeholder = "MM/DD/YYYY";
431
+ endInput.setAttribute("aria-label", "End date");
432
+ endInput.addEventListener("blur", () => this._onInputBlur(endInput, "end"));
433
+ this._setupDateMask(endInput, "end");
434
+ this._endInput = endInput;
435
+ inputsWrap.append(startInput, sep, endInput);
436
+ const actions = document.createElement("div");
437
+ actions.className = "footer-actions";
438
+ const cancelBtn = document.createElement("button");
439
+ cancelBtn.type = "button";
440
+ cancelBtn.className = "btn btn-cancel";
441
+ cancelBtn.textContent = "Cancel";
442
+ cancelBtn.setAttribute("part", "cancel-button");
443
+ cancelBtn.addEventListener("click", () => {
444
+ this.dispatchEvent(new CustomEvent("bv-cancel", { bubbles: true, composed: true }));
445
+ });
446
+ const applyBtn = document.createElement("button");
447
+ applyBtn.type = "button";
448
+ applyBtn.className = "btn btn-apply";
449
+ applyBtn.textContent = "Apply";
450
+ applyBtn.setAttribute("part", "apply-button");
451
+ applyBtn.addEventListener("click", () => this._apply());
452
+ this._applyBtn = applyBtn;
453
+ actions.append(cancelBtn, applyBtn);
454
+ footer.append(inputsWrap, actions);
455
+ const bannerWrap = document.createElement("div");
456
+ bannerWrap.className = "banner-wrap";
457
+ const banner = document.createElement("bv-alert-banner");
458
+ banner.setAttribute("variant", "warning");
459
+ banner.setAttribute("heading", "Date range exceeds 5 years");
460
+ banner.setAttribute(
461
+ "message",
462
+ "Only CSV download is available for this date range. Live report generation is not supported."
463
+ );
464
+ banner.hidden = true;
465
+ this._bannerEl = banner;
466
+ bannerWrap.appendChild(banner);
467
+ main.append(calsWrap, bannerWrap, footer);
468
+ picker.append(sidebar, main);
469
+ shadow.appendChild(picker);
470
+ this._syncCalendars();
471
+ this._syncInputs();
472
+ this._syncPresets();
473
+ this._syncApply();
474
+ this._syncBanner();
475
+ }
476
+ _buildCalendarShell(side) {
477
+ const cal = document.createElement("div");
478
+ cal.className = `calendar calendar--${side}`;
479
+ const header = document.createElement("div");
480
+ header.className = "calendar-header";
481
+ const prevBtn = document.createElement("button");
482
+ prevBtn.type = "button";
483
+ prevBtn.className = "nav-btn";
484
+ prevBtn.setAttribute("aria-label", "Previous month");
485
+ prevBtn.innerHTML = CHEVRON_LEFT;
486
+ prevBtn.addEventListener("click", () => this._navigate(-1));
487
+ const title = document.createElement("span");
488
+ title.className = "calendar-title";
489
+ const nextBtn = document.createElement("button");
490
+ nextBtn.type = "button";
491
+ nextBtn.className = "nav-btn";
492
+ nextBtn.setAttribute("aria-label", "Next month");
493
+ nextBtn.innerHTML = CHEVRON_RIGHT;
494
+ nextBtn.addEventListener("click", () => this._navigate(1));
495
+ header.append(prevBtn, title, nextBtn);
496
+ const weekdaysRow = document.createElement("div");
497
+ weekdaysRow.className = "weekdays";
498
+ for (const d of WEEKDAYS) {
499
+ const wd = document.createElement("span");
500
+ wd.className = "weekday";
501
+ wd.textContent = d;
502
+ weekdaysRow.appendChild(wd);
503
+ }
504
+ const grid = document.createElement("div");
505
+ grid.className = "days-grid";
506
+ cal.append(header, weekdaysRow, grid);
507
+ if (side === "left") {
508
+ this._leftTitle = title;
509
+ this._leftGrid = grid;
510
+ } else {
511
+ this._rightTitle = title;
512
+ this._rightGrid = grid;
513
+ }
514
+ return cal;
515
+ }
516
+ _navigate(delta) {
517
+ this._leftMonth += delta;
518
+ if (this._leftMonth > 11) {
519
+ this._leftMonth = 0;
520
+ this._leftYear++;
521
+ } else if (this._leftMonth < 0) {
522
+ this._leftMonth = 11;
523
+ this._leftYear--;
524
+ }
525
+ this._syncCalendars();
526
+ }
527
+ _getRightMonth() {
528
+ const m = this._leftMonth + 1;
529
+ return m > 11 ? { year: this._leftYear + 1, month: 0 } : { year: this._leftYear, month: m };
530
+ }
531
+ _syncCalendars() {
532
+ if (!this._leftGrid || !this._rightGrid) return;
533
+ const right = this._getRightMonth();
534
+ if (this._leftTitle) {
535
+ this._leftTitle.textContent = `${MONTH_NAMES[this._leftMonth]} ${this._leftYear}`;
536
+ }
537
+ if (this._rightTitle) {
538
+ this._rightTitle.textContent = `${MONTH_NAMES[right.month]} ${right.year}`;
539
+ }
540
+ this._buildDaysGrid(this._leftGrid, this._leftYear, this._leftMonth, this._leftDayMap);
541
+ this._buildDaysGrid(this._rightGrid, right.year, right.month, this._rightDayMap);
542
+ }
543
+ _buildDaysGrid(container, year, month, map) {
544
+ container.innerHTML = "";
545
+ map.clear();
546
+ const firstDow = new Date(year, month, 1).getDay();
547
+ const offset = firstDow === 0 ? 6 : firstDow - 1;
548
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
549
+ const totalCells = Math.ceil((offset + daysInMonth) / 7) * 7;
550
+ for (let i = 0; i < totalCells; i++) {
551
+ let iso;
552
+ let dayNum;
553
+ if (i < offset) {
554
+ const blank = document.createElement("span");
555
+ blank.className = "day day--blank";
556
+ container.appendChild(blank);
557
+ continue;
558
+ } else if (i >= offset + daysInMonth) {
559
+ const blank = document.createElement("span");
560
+ blank.className = "day day--blank";
561
+ container.appendChild(blank);
562
+ continue;
563
+ } else {
564
+ dayNum = i - offset + 1;
565
+ iso = `${year}-${String(month + 1).padStart(2, "0")}-${String(dayNum).padStart(2, "0")}`;
566
+ }
567
+ const btn = document.createElement("button");
568
+ btn.type = "button";
569
+ btn.dataset["date"] = iso;
570
+ btn.dataset["weekPos"] = String(i % 7);
571
+ btn.dataset["otherMonth"] = "0";
572
+ btn.dataset["dayNum"] = String(dayNum);
573
+ btn.dataset["daysInMonth"] = String(daysInMonth);
574
+ const inner = document.createElement("span");
575
+ inner.className = "day-inner";
576
+ inner.textContent = String(dayNum);
577
+ btn.appendChild(inner);
578
+ btn.addEventListener("click", () => this._selectDate(iso));
579
+ btn.addEventListener("mouseenter", () => this._onHover(iso));
580
+ this._applyDayClasses(btn, iso, false, i % 7, daysInMonth, dayNum);
581
+ map.set(iso, btn);
582
+ container.appendChild(btn);
583
+ }
584
+ }
585
+ _applyDayClasses(btn, iso, isOtherMonth, weekPos, daysInMonth, dayNum) {
586
+ const classes = ["day"];
587
+ if (isOtherMonth) classes.push("other-month");
588
+ if (iso === this._today) classes.push("today");
589
+ if (iso === this._start) classes.push("start");
590
+ if (iso === this._end) classes.push("end");
591
+ if (weekPos === 0 || dayNum === 1) classes.push("week-start");
592
+ if (weekPos === 6 || dayNum === daysInMonth) classes.push("week-end");
593
+ const effectiveEnd = this._picking && this._hover ? this._hover : this._end;
594
+ if (this._start && effectiveEnd) {
595
+ const [s, e] = this._start <= effectiveEnd ? [this._start, effectiveEnd] : [effectiveEnd, this._start];
596
+ if (iso > s && iso < e) classes.push("in-range");
597
+ if (iso === s && s !== e) classes.push("range-start");
598
+ if (iso === e && s !== e) classes.push("range-end");
599
+ }
600
+ btn.className = classes.join(" ");
601
+ }
602
+ _onHover(iso) {
603
+ if (!this._picking || this._hover === iso) return;
604
+ this._hover = iso;
605
+ this._updateDayClasses();
606
+ }
607
+ _updateDayClasses() {
608
+ const right = this._getRightMonth();
609
+ const rightDaysInMonth = new Date(right.year, right.month + 1, 0).getDate();
610
+ const leftDaysInMonth = new Date(this._leftYear, this._leftMonth + 1, 0).getDate();
611
+ this._leftDayMap.forEach((btn, iso) => {
612
+ this._applyDayClasses(
613
+ btn,
614
+ iso,
615
+ btn.dataset["otherMonth"] === "1",
616
+ parseInt(btn.dataset["weekPos"] ?? "0", 10),
617
+ leftDaysInMonth,
618
+ parseInt(btn.dataset["dayNum"] ?? "1", 10)
619
+ );
620
+ });
621
+ this._rightDayMap.forEach((btn, iso) => {
622
+ this._applyDayClasses(
623
+ btn,
624
+ iso,
625
+ btn.dataset["otherMonth"] === "1",
626
+ parseInt(btn.dataset["weekPos"] ?? "0", 10),
627
+ rightDaysInMonth,
628
+ parseInt(btn.dataset["dayNum"] ?? "1", 10)
629
+ );
630
+ });
631
+ }
632
+ _selectDate(iso) {
633
+ if (!this._picking) {
634
+ this._start = iso;
635
+ this._end = "";
636
+ this._preset = "custom";
637
+ this._picking = true;
638
+ this._hover = "";
639
+ } else {
640
+ if (iso < this._start) {
641
+ this._end = this._start;
642
+ this._start = iso;
643
+ } else {
644
+ this._end = iso;
645
+ }
646
+ this._picking = false;
647
+ this._hover = "";
648
+ this._preset = "custom";
649
+ }
650
+ this._syncCalendars();
651
+ this._syncInputs();
652
+ this._syncPresets();
653
+ this._syncApply();
654
+ this._syncBanner();
655
+ }
656
+ _selectPreset(key) {
657
+ if (key === "custom") {
658
+ this._preset = "custom";
659
+ this._picking = false;
660
+ this._hover = "";
661
+ this._syncPresets();
662
+ return;
663
+ }
664
+ const { start, end } = getPresetDates(key);
665
+ this._start = start;
666
+ this._end = end;
667
+ this._preset = key;
668
+ this._picking = false;
669
+ this._hover = "";
670
+ if (start) {
671
+ const parts = start.split("-");
672
+ const y = parseInt(parts[0], 10);
673
+ const m = parseInt(parts[1], 10) - 1;
674
+ if (!isNaN(y) && !isNaN(m)) {
675
+ this._leftYear = y;
676
+ this._leftMonth = m;
677
+ }
678
+ }
679
+ this._syncCalendars();
680
+ this._syncInputs();
681
+ this._syncPresets();
682
+ this._syncApply();
683
+ this._syncBanner();
684
+ }
685
+ _onInputBlur(input, field) {
686
+ const iso = parseDisplay(input.value);
687
+ if (iso) {
688
+ if (field === "start") this._start = iso;
689
+ else this._end = iso;
690
+ this._picking = false;
691
+ this._hover = "";
692
+ this._preset = "custom";
693
+ this._syncCalendars();
694
+ this._syncPresets();
695
+ this._syncApply();
696
+ this._syncBanner();
697
+ } else {
698
+ input.value = formatDisplay(field === "start" ? this._start : this._end);
699
+ }
700
+ }
701
+ _syncInputs() {
702
+ if (this._startInput) this._startInput.value = formatDisplay(this._start);
703
+ if (this._endInput) this._endInput.value = formatDisplay(this._end);
704
+ }
705
+ _syncPresets() {
706
+ this.shadowRoot.querySelectorAll(".preset-btn").forEach((el) => {
707
+ const btn = el;
708
+ btn.classList.toggle("active", btn.dataset["preset"] === this._preset);
709
+ });
710
+ }
711
+ _syncApply() {
712
+ if (this._applyBtn) {
713
+ this._applyBtn.disabled = !this._start || !this._end;
714
+ }
715
+ }
716
+ _syncBanner() {
717
+ if (!this._bannerEl) return;
718
+ const pickerEl = this.shadowRoot.querySelector(".picker");
719
+ if (!this._start) {
720
+ this._bannerEl.hidden = true;
721
+ pickerEl == null ? void 0 : pickerEl.classList.remove("picker--with-banner");
722
+ return;
723
+ }
724
+ const startDate = /* @__PURE__ */ new Date(this._start + "T00:00:00");
725
+ const fiveYearsAgo = /* @__PURE__ */ new Date();
726
+ fiveYearsAgo.setFullYear(fiveYearsAgo.getFullYear() - 5);
727
+ const show = startDate < fiveYearsAgo;
728
+ this._bannerEl.hidden = !show;
729
+ pickerEl == null ? void 0 : pickerEl.classList.toggle("picker--with-banner", show);
730
+ }
731
+ // Auto-insert slashes after MM and DD digits while the user types forward.
732
+ // Also syncs the banner live once the date is fully typed.
733
+ _setupDateMask(input, field) {
734
+ input.addEventListener("input", (e) => {
735
+ var _a;
736
+ const ev = e;
737
+ if ((_a = ev.inputType) == null ? void 0 : _a.startsWith("delete")) return;
738
+ const digits = input.value.replace(/[^\d]/g, "");
739
+ let formatted;
740
+ if (digits.length <= 2) {
741
+ formatted = digits.length === 2 ? digits + "/" : digits;
742
+ } else if (digits.length <= 4) {
743
+ const part = digits.slice(0, 2) + "/" + digits.slice(2);
744
+ formatted = digits.length === 4 ? part + "/" : part;
745
+ } else {
746
+ formatted = digits.slice(0, 2) + "/" + digits.slice(2, 4) + "/" + digits.slice(4, 8);
747
+ }
748
+ input.value = formatted;
749
+ if (formatted.length === 10) {
750
+ const iso = parseDisplay(formatted);
751
+ if (iso) {
752
+ if (field === "start") this._start = iso;
753
+ else this._end = iso;
754
+ this._syncBanner();
755
+ }
756
+ } else if (field === "start" && formatted.length < 10) {
757
+ this._start = "";
758
+ this._syncBanner();
759
+ }
760
+ });
761
+ }
762
+ _apply() {
763
+ if (!this._start || !this._end) return;
764
+ this.setAttribute("start", this._start);
765
+ this.setAttribute("end", this._end);
766
+ if (this._preset) this.setAttribute("preset", this._preset);
767
+ this.dispatchEvent(
768
+ new CustomEvent("bv-change", {
769
+ bubbles: true,
770
+ composed: true,
771
+ detail: { start: this._start, end: this._end, preset: this._preset }
772
+ })
773
+ );
774
+ }
775
+ };
776
+ if (!customElements.get("bv-date-range-picker")) {
777
+ customElements.define("bv-date-range-picker", BvDateRangePicker);
778
+ }
779
+
780
+ // components/bv-date-range-input/bv-date-range-input.ts
781
+ var CALENDAR_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>`;
782
+ var _sheet3 = null;
783
+ function getSheet3() {
784
+ if (!_sheet3) {
785
+ _sheet3 = new CSSStyleSheet();
786
+ _sheet3.replaceSync(bv_date_range_input_default);
787
+ }
788
+ return _sheet3;
789
+ }
790
+ function isoToDisplay(iso) {
791
+ if (!iso) return "";
792
+ const [y, m, d] = iso.split("-");
793
+ return `${m}/${d}/${y}`;
794
+ }
795
+ var BvDateRangeInput = class extends HTMLElement {
796
+ static observedAttributes = [
797
+ "label",
798
+ "start",
799
+ "end",
800
+ "placeholder",
801
+ "required"
802
+ ];
803
+ _rendered = false;
804
+ _labelEl = null;
805
+ _displayEl = null;
806
+ _pickerEl = null;
807
+ _offClick = null;
808
+ constructor() {
809
+ super();
810
+ const shadow = this.attachShadow({ mode: "open" });
811
+ if ("adoptedStyleSheets" in ShadowRoot.prototype) {
812
+ shadow.adoptedStyleSheets = [getSheet3()];
813
+ }
814
+ }
815
+ get start() {
816
+ return this.getAttribute("start") ?? "";
817
+ }
818
+ set start(v) {
819
+ this.setAttribute("start", v);
820
+ }
821
+ get end() {
822
+ return this.getAttribute("end") ?? "";
823
+ }
824
+ set end(v) {
825
+ this.setAttribute("end", v);
826
+ }
827
+ connectedCallback() {
828
+ this._render();
829
+ }
830
+ disconnectedCallback() {
831
+ if (this._offClick) document.removeEventListener("click", this._offClick);
832
+ }
833
+ attributeChangedCallback(name, _old, _val) {
834
+ if (!this._rendered) return;
835
+ if (name === "label" || name === "required") this._syncLabel();
836
+ if (name === "start" || name === "end") this._syncDisplay();
837
+ if (name === "placeholder") this._syncDisplay();
838
+ }
839
+ _render() {
840
+ if (this._rendered) return;
841
+ this._rendered = true;
842
+ const shadow = this.shadowRoot;
843
+ if (!shadow.adoptedStyleSheets.length) {
844
+ const s = document.createElement("style");
845
+ s.textContent = bv_date_range_input_default;
846
+ shadow.appendChild(s);
847
+ }
848
+ const label = document.createElement("label");
849
+ label.className = "field-label";
850
+ this._labelEl = label;
851
+ const trigger = document.createElement("button");
852
+ trigger.type = "button";
853
+ trigger.className = "trigger";
854
+ trigger.setAttribute("aria-haspopup", "dialog");
855
+ trigger.setAttribute("aria-expanded", "false");
856
+ trigger.setAttribute("part", "trigger");
857
+ const display = document.createElement("span");
858
+ display.className = "trigger-display";
859
+ this._displayEl = display;
860
+ const icon = document.createElement("span");
861
+ icon.className = "trigger-icon";
862
+ icon.innerHTML = CALENDAR_ICON;
863
+ trigger.append(display, icon);
864
+ trigger.addEventListener("click", (e) => {
865
+ e.stopPropagation();
866
+ this._toggle();
867
+ });
868
+ const popup = document.createElement("div");
869
+ popup.className = "picker-popup";
870
+ const picker = document.createElement("bv-date-range-picker");
871
+ picker.setAttribute("start", this.getAttribute("start") ?? "");
872
+ picker.setAttribute("end", this.getAttribute("end") ?? "");
873
+ this._pickerEl = picker;
874
+ picker.addEventListener("bv-change", (e) => {
875
+ const detail = e.detail;
876
+ this.setAttribute("start", detail.start);
877
+ this.setAttribute("end", detail.end);
878
+ this._close();
879
+ this.dispatchEvent(
880
+ new CustomEvent("bv-change", {
881
+ bubbles: true,
882
+ composed: true,
883
+ detail
884
+ })
885
+ );
886
+ });
887
+ picker.addEventListener("bv-cancel", () => {
888
+ this._close();
889
+ });
890
+ popup.appendChild(picker);
891
+ shadow.append(label, trigger, popup);
892
+ this._syncLabel();
893
+ this._syncDisplay();
894
+ this._offClick = (e) => {
895
+ if (!this.contains(e.target) && !shadow.contains(e.target)) {
896
+ this._close();
897
+ }
898
+ };
899
+ document.addEventListener("click", this._offClick);
900
+ }
901
+ _toggle() {
902
+ if (this.hasAttribute("open")) this._close();
903
+ else this._open();
904
+ }
905
+ _open() {
906
+ var _a;
907
+ this.setAttribute("open", "");
908
+ (_a = this.shadowRoot.querySelector(".trigger")) == null ? void 0 : _a.setAttribute("aria-expanded", "true");
909
+ if (this._pickerEl) {
910
+ this._pickerEl.setAttribute("start", this.getAttribute("start") ?? "");
911
+ this._pickerEl.setAttribute("end", this.getAttribute("end") ?? "");
912
+ }
913
+ }
914
+ _close() {
915
+ var _a;
916
+ this.removeAttribute("open");
917
+ (_a = this.shadowRoot.querySelector(".trigger")) == null ? void 0 : _a.setAttribute("aria-expanded", "false");
918
+ }
919
+ _syncLabel() {
920
+ if (!this._labelEl) return;
921
+ const labelText = this.getAttribute("label") ?? "";
922
+ this._labelEl.textContent = labelText;
923
+ if (this.hasAttribute("required")) {
924
+ const mark = document.createElement("span");
925
+ mark.className = "required-mark";
926
+ mark.setAttribute("aria-hidden", "true");
927
+ mark.textContent = "*";
928
+ this._labelEl.appendChild(mark);
929
+ }
930
+ this._labelEl.hidden = !labelText;
931
+ }
932
+ _syncDisplay() {
933
+ if (!this._displayEl) return;
934
+ const start = this.getAttribute("start") ?? "";
935
+ const end = this.getAttribute("end") ?? "";
936
+ if (start && end) {
937
+ this._displayEl.textContent = `${isoToDisplay(start)} - ${isoToDisplay(end)}`;
938
+ this._displayEl.classList.remove("is-placeholder");
939
+ } else {
940
+ this._displayEl.textContent = this.getAttribute("placeholder") ?? "Select date range";
941
+ this._displayEl.classList.add("is-placeholder");
942
+ }
943
+ }
944
+ };
945
+ if (!customElements.get("bv-date-range-input")) {
946
+ customElements.define("bv-date-range-input", BvDateRangeInput);
947
+ }
948
+ export {
949
+ BvDateRangeInput
950
+ };