@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
@@ -0,0 +1,778 @@
1
+ // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-date-range-picker/bv-date-range-picker.css
2
+ 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";
3
+
4
+ // css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-alert-banner/bv-alert-banner.css
5
+ 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";
6
+
7
+ // components/bv-alert-banner/bv-alert-banner.ts
8
+ 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>`;
9
+ 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>`;
10
+ 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>`;
11
+ 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>`;
12
+ 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>`;
13
+ 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>`;
14
+ var VARIANT_ICONS = {
15
+ default: ICON_INFO,
16
+ primary: ICON_INFO,
17
+ error: ICON_ALERT_CIRCLE,
18
+ warning: ICON_ALERT_TRIANGLE,
19
+ success: ICON_CHECK_CIRCLE
20
+ };
21
+ var _sheet = null;
22
+ function getSheet() {
23
+ if (!_sheet) {
24
+ _sheet = new CSSStyleSheet();
25
+ _sheet.replaceSync(bv_alert_banner_default);
26
+ }
27
+ return _sheet;
28
+ }
29
+ var BvAlertBanner = class extends HTMLElement {
30
+ static observedAttributes = [
31
+ "variant",
32
+ "heading",
33
+ "message",
34
+ "dismissable",
35
+ "action-label",
36
+ "secondary-action-label"
37
+ ];
38
+ _rendered = false;
39
+ _iconEl = null;
40
+ _headingEl = null;
41
+ _messageEl = null;
42
+ _actionsEl = null;
43
+ _primaryActionBtn = null;
44
+ _secondaryActionBtn = null;
45
+ _closeBtn = null;
46
+ constructor() {
47
+ super();
48
+ const shadow = this.attachShadow({ mode: "open" });
49
+ if ("adoptedStyleSheets" in ShadowRoot.prototype) {
50
+ shadow.adoptedStyleSheets = [getSheet()];
51
+ }
52
+ }
53
+ get variant() {
54
+ return this.getAttribute("variant") ?? "default";
55
+ }
56
+ set variant(v) {
57
+ this.setAttribute("variant", v);
58
+ }
59
+ get heading() {
60
+ return this.getAttribute("heading") ?? "";
61
+ }
62
+ set heading(v) {
63
+ this.setAttribute("heading", v);
64
+ }
65
+ get message() {
66
+ return this.getAttribute("message") ?? "";
67
+ }
68
+ set message(v) {
69
+ this.setAttribute("message", v);
70
+ }
71
+ get dismissable() {
72
+ return this.hasAttribute("dismissable");
73
+ }
74
+ set dismissable(v) {
75
+ if (v) this.setAttribute("dismissable", "");
76
+ else this.removeAttribute("dismissable");
77
+ }
78
+ get actionLabel() {
79
+ return this.getAttribute("action-label") ?? "";
80
+ }
81
+ set actionLabel(v) {
82
+ this.setAttribute("action-label", v);
83
+ }
84
+ get secondaryActionLabel() {
85
+ return this.getAttribute("secondary-action-label") ?? "";
86
+ }
87
+ set secondaryActionLabel(v) {
88
+ this.setAttribute("secondary-action-label", v);
89
+ }
90
+ connectedCallback() {
91
+ this._render();
92
+ }
93
+ attributeChangedCallback(name, _old, _val) {
94
+ if (!this._rendered) return;
95
+ if (name === "variant") this._syncVariant();
96
+ if (name === "heading") this._syncHeading();
97
+ if (name === "message") this._syncMessage();
98
+ if (name === "dismissable") this._syncClose();
99
+ if (name === "action-label" || name === "secondary-action-label") this._syncActions();
100
+ }
101
+ _render() {
102
+ if (this._rendered) return;
103
+ this._rendered = true;
104
+ const shadow = this.shadowRoot;
105
+ if (!shadow.adoptedStyleSheets.length) {
106
+ const s = document.createElement("style");
107
+ s.textContent = bv_alert_banner_default;
108
+ shadow.appendChild(s);
109
+ }
110
+ const banner = document.createElement("div");
111
+ banner.className = "banner";
112
+ banner.setAttribute("role", "alert");
113
+ const iconWrap = document.createElement("span");
114
+ iconWrap.className = "banner-icon";
115
+ this._iconEl = iconWrap;
116
+ const content = document.createElement("div");
117
+ content.className = "banner-content";
118
+ const heading = document.createElement("p");
119
+ heading.className = "banner-heading";
120
+ this._headingEl = heading;
121
+ const message = document.createElement("p");
122
+ message.className = "banner-message";
123
+ this._messageEl = message;
124
+ const actions = document.createElement("div");
125
+ actions.className = "banner-actions";
126
+ this._actionsEl = actions;
127
+ const primaryBtn = document.createElement("button");
128
+ primaryBtn.type = "button";
129
+ primaryBtn.className = "action-btn action-btn--primary";
130
+ primaryBtn.addEventListener("click", () => {
131
+ this.dispatchEvent(
132
+ new CustomEvent("bv-action", {
133
+ bubbles: true,
134
+ composed: true,
135
+ detail: { action: "primary" }
136
+ })
137
+ );
138
+ });
139
+ this._primaryActionBtn = primaryBtn;
140
+ const secondaryBtn = document.createElement("button");
141
+ secondaryBtn.type = "button";
142
+ secondaryBtn.className = "action-btn action-btn--secondary";
143
+ secondaryBtn.addEventListener("click", () => {
144
+ this.dispatchEvent(
145
+ new CustomEvent("bv-action", {
146
+ bubbles: true,
147
+ composed: true,
148
+ detail: { action: "secondary" }
149
+ })
150
+ );
151
+ });
152
+ this._secondaryActionBtn = secondaryBtn;
153
+ actions.append(primaryBtn, secondaryBtn);
154
+ content.append(heading, message, actions);
155
+ const closeBtn = document.createElement("button");
156
+ closeBtn.type = "button";
157
+ closeBtn.className = "close-btn";
158
+ closeBtn.setAttribute("aria-label", "Dismiss");
159
+ closeBtn.innerHTML = ICON_X;
160
+ closeBtn.addEventListener("click", () => {
161
+ this.dispatchEvent(new CustomEvent("bv-dismiss", { bubbles: true, composed: true }));
162
+ });
163
+ this._closeBtn = closeBtn;
164
+ banner.append(iconWrap, content, closeBtn);
165
+ shadow.appendChild(banner);
166
+ this._syncVariant();
167
+ this._syncHeading();
168
+ this._syncMessage();
169
+ this._syncActions();
170
+ this._syncClose();
171
+ }
172
+ _syncVariant() {
173
+ if (!this._iconEl) return;
174
+ const v = this.variant;
175
+ this._iconEl.innerHTML = VARIANT_ICONS[v] ?? ICON_INFO;
176
+ }
177
+ _syncHeading() {
178
+ if (!this._headingEl) return;
179
+ const text = this.heading;
180
+ this._headingEl.textContent = text;
181
+ this._headingEl.hidden = !text;
182
+ }
183
+ _syncMessage() {
184
+ if (!this._messageEl) return;
185
+ const text = this.message;
186
+ this._messageEl.textContent = text;
187
+ this._messageEl.hidden = !text;
188
+ }
189
+ _syncActions() {
190
+ if (!this._actionsEl || !this._primaryActionBtn || !this._secondaryActionBtn) return;
191
+ const primary = this.actionLabel;
192
+ const secondary = this.secondaryActionLabel;
193
+ this._primaryActionBtn.textContent = primary;
194
+ this._primaryActionBtn.hidden = !primary;
195
+ this._secondaryActionBtn.innerHTML = secondary ? `<span>${secondary}</span>${ICON_ARROW_RIGHT}` : "";
196
+ this._secondaryActionBtn.hidden = !secondary;
197
+ this._actionsEl.hidden = !primary && !secondary;
198
+ }
199
+ _syncClose() {
200
+ if (!this._closeBtn) return;
201
+ this._closeBtn.hidden = !this.dismissable;
202
+ }
203
+ };
204
+ if (!customElements.get("bv-alert-banner")) {
205
+ customElements.define("bv-alert-banner", BvAlertBanner);
206
+ }
207
+
208
+ // components/bv-date-range-picker/bv-date-range-picker.ts
209
+ var PRESETS = [
210
+ { key: "last-30-days", label: "Last 30 Days" },
211
+ { key: "last-90-days", label: "Last 90 Days" },
212
+ { key: "last-365-days", label: "Last 365 Days", separator: true },
213
+ { key: "last-month", label: "Last Month" },
214
+ { key: "last-quarter", label: "Last Quarter" },
215
+ { key: "last-year", label: "Last Year" },
216
+ { key: "year-to-date", label: "Year to Date", separator: true },
217
+ { key: "custom", label: "Custom Range" }
218
+ ];
219
+ var MONTH_NAMES = [
220
+ "January",
221
+ "February",
222
+ "March",
223
+ "April",
224
+ "May",
225
+ "June",
226
+ "July",
227
+ "August",
228
+ "September",
229
+ "October",
230
+ "November",
231
+ "December"
232
+ ];
233
+ var WEEKDAYS = ["Mo", "Tu", "We", "Th", "Fr", "Sat", "Su"];
234
+ 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>`;
235
+ 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>`;
236
+ var _sheet2 = null;
237
+ function getSheet2() {
238
+ if (!_sheet2) {
239
+ _sheet2 = new CSSStyleSheet();
240
+ _sheet2.replaceSync(bv_date_range_picker_default);
241
+ }
242
+ return _sheet2;
243
+ }
244
+ function dateToIso(d) {
245
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
246
+ }
247
+ function formatDisplay(iso) {
248
+ if (!iso) return "";
249
+ const [y, m, d] = iso.split("-");
250
+ return `${m}/${d}/${y}`;
251
+ }
252
+ function parseDisplay(str) {
253
+ const match = str.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
254
+ if (!match) return "";
255
+ const m = match[1].padStart(2, "0");
256
+ const d = match[2].padStart(2, "0");
257
+ return `${match[3]}-${m}-${d}`;
258
+ }
259
+ function getPresetDates(key) {
260
+ const now = /* @__PURE__ */ new Date();
261
+ now.setHours(0, 0, 0, 0);
262
+ const today = dateToIso(now);
263
+ switch (key) {
264
+ case "last-30-days": {
265
+ const s = new Date(now);
266
+ s.setDate(s.getDate() - 29);
267
+ return { start: dateToIso(s), end: today };
268
+ }
269
+ case "last-90-days": {
270
+ const s = new Date(now);
271
+ s.setDate(s.getDate() - 89);
272
+ return { start: dateToIso(s), end: today };
273
+ }
274
+ case "last-365-days": {
275
+ const s = new Date(now);
276
+ s.setDate(s.getDate() - 364);
277
+ return { start: dateToIso(s), end: today };
278
+ }
279
+ case "last-month": {
280
+ const s = new Date(now.getFullYear(), now.getMonth() - 1, 1);
281
+ const e = new Date(now.getFullYear(), now.getMonth(), 0);
282
+ return { start: dateToIso(s), end: dateToIso(e) };
283
+ }
284
+ case "last-quarter": {
285
+ const q = Math.floor(now.getMonth() / 3);
286
+ const qs = q === 0 ? new Date(now.getFullYear() - 1, 9, 1) : new Date(now.getFullYear(), (q - 1) * 3, 1);
287
+ const qe = new Date(qs.getFullYear(), qs.getMonth() + 3, 0);
288
+ return { start: dateToIso(qs), end: dateToIso(qe) };
289
+ }
290
+ case "last-year": {
291
+ const y = now.getFullYear() - 1;
292
+ return { start: `${y}-01-01`, end: `${y}-12-31` };
293
+ }
294
+ case "year-to-date":
295
+ return { start: `${now.getFullYear()}-01-01`, end: today };
296
+ default:
297
+ return { start: "", end: "" };
298
+ }
299
+ }
300
+ var BvDateRangePicker = class extends HTMLElement {
301
+ static observedAttributes = ["start", "end", "preset"];
302
+ _rendered = false;
303
+ _today;
304
+ _start = "";
305
+ _end = "";
306
+ _preset = "";
307
+ _picking = false;
308
+ _hover = "";
309
+ _leftYear;
310
+ _leftMonth;
311
+ _leftGrid = null;
312
+ _rightGrid = null;
313
+ _leftTitle = null;
314
+ _rightTitle = null;
315
+ _startInput = null;
316
+ _endInput = null;
317
+ _applyBtn = null;
318
+ _bannerEl = null;
319
+ _leftDayMap = /* @__PURE__ */ new Map();
320
+ _rightDayMap = /* @__PURE__ */ new Map();
321
+ constructor() {
322
+ super();
323
+ const now = /* @__PURE__ */ new Date();
324
+ now.setHours(0, 0, 0, 0);
325
+ this._today = dateToIso(now);
326
+ this._leftYear = now.getFullYear();
327
+ this._leftMonth = now.getMonth();
328
+ const shadow = this.attachShadow({ mode: "open" });
329
+ if ("adoptedStyleSheets" in ShadowRoot.prototype) {
330
+ shadow.adoptedStyleSheets = [getSheet2()];
331
+ }
332
+ }
333
+ get start() {
334
+ return this._start;
335
+ }
336
+ set start(v) {
337
+ this.setAttribute("start", v);
338
+ }
339
+ get end() {
340
+ return this._end;
341
+ }
342
+ set end(v) {
343
+ this.setAttribute("end", v);
344
+ }
345
+ get preset() {
346
+ return this._preset;
347
+ }
348
+ set preset(v) {
349
+ this.setAttribute("preset", v);
350
+ }
351
+ connectedCallback() {
352
+ this._render();
353
+ }
354
+ attributeChangedCallback(name, _old, val) {
355
+ if (name === "start") this._start = val ?? "";
356
+ if (name === "end") this._end = val ?? "";
357
+ if (name === "preset") this._preset = val ?? "";
358
+ if (!this._rendered) return;
359
+ this._syncCalendars();
360
+ this._syncInputs();
361
+ this._syncPresets();
362
+ this._syncApply();
363
+ }
364
+ _render() {
365
+ if (this._rendered) return;
366
+ this._rendered = true;
367
+ this._start = this.getAttribute("start") ?? "";
368
+ this._end = this.getAttribute("end") ?? "";
369
+ this._preset = this.getAttribute("preset") ?? "";
370
+ if (this._start) {
371
+ const parts = this._start.split("-");
372
+ const y = parseInt(parts[0], 10);
373
+ const m = parseInt(parts[1], 10) - 1;
374
+ if (!isNaN(y) && !isNaN(m)) {
375
+ this._leftYear = y;
376
+ this._leftMonth = m;
377
+ }
378
+ }
379
+ const shadow = this.shadowRoot;
380
+ if (!shadow.adoptedStyleSheets.length) {
381
+ const s = document.createElement("style");
382
+ s.textContent = bv_date_range_picker_default;
383
+ shadow.appendChild(s);
384
+ }
385
+ const picker = document.createElement("div");
386
+ picker.className = "picker";
387
+ const sidebar = document.createElement("div");
388
+ sidebar.className = "sidebar";
389
+ for (const p of PRESETS) {
390
+ const btn = document.createElement("button");
391
+ btn.type = "button";
392
+ btn.className = "preset-btn";
393
+ btn.dataset["preset"] = p.key;
394
+ btn.textContent = p.label;
395
+ btn.addEventListener("click", () => this._selectPreset(p.key));
396
+ sidebar.appendChild(btn);
397
+ if (p.separator) {
398
+ const hr = document.createElement("hr");
399
+ hr.className = "sidebar-sep";
400
+ sidebar.appendChild(hr);
401
+ }
402
+ }
403
+ const main = document.createElement("div");
404
+ main.className = "main";
405
+ const calsWrap = document.createElement("div");
406
+ calsWrap.className = "calendars";
407
+ calsWrap.append(this._buildCalendarShell("left"), this._buildCalendarShell("right"));
408
+ const footer = document.createElement("div");
409
+ footer.className = "footer";
410
+ const inputsWrap = document.createElement("div");
411
+ inputsWrap.className = "date-inputs";
412
+ const startInput = document.createElement("input");
413
+ startInput.type = "text";
414
+ startInput.className = "date-input";
415
+ startInput.placeholder = "MM/DD/YYYY";
416
+ startInput.setAttribute("aria-label", "Start date");
417
+ startInput.addEventListener("blur", () => this._onInputBlur(startInput, "start"));
418
+ this._setupDateMask(startInput, "start");
419
+ this._startInput = startInput;
420
+ const sep = document.createElement("span");
421
+ sep.className = "date-sep";
422
+ sep.textContent = "\u2013";
423
+ sep.setAttribute("aria-hidden", "true");
424
+ const endInput = document.createElement("input");
425
+ endInput.type = "text";
426
+ endInput.className = "date-input";
427
+ endInput.placeholder = "MM/DD/YYYY";
428
+ endInput.setAttribute("aria-label", "End date");
429
+ endInput.addEventListener("blur", () => this._onInputBlur(endInput, "end"));
430
+ this._setupDateMask(endInput, "end");
431
+ this._endInput = endInput;
432
+ inputsWrap.append(startInput, sep, endInput);
433
+ const actions = document.createElement("div");
434
+ actions.className = "footer-actions";
435
+ const cancelBtn = document.createElement("button");
436
+ cancelBtn.type = "button";
437
+ cancelBtn.className = "btn btn-cancel";
438
+ cancelBtn.textContent = "Cancel";
439
+ cancelBtn.setAttribute("part", "cancel-button");
440
+ cancelBtn.addEventListener("click", () => {
441
+ this.dispatchEvent(new CustomEvent("bv-cancel", { bubbles: true, composed: true }));
442
+ });
443
+ const applyBtn = document.createElement("button");
444
+ applyBtn.type = "button";
445
+ applyBtn.className = "btn btn-apply";
446
+ applyBtn.textContent = "Apply";
447
+ applyBtn.setAttribute("part", "apply-button");
448
+ applyBtn.addEventListener("click", () => this._apply());
449
+ this._applyBtn = applyBtn;
450
+ actions.append(cancelBtn, applyBtn);
451
+ footer.append(inputsWrap, actions);
452
+ const bannerWrap = document.createElement("div");
453
+ bannerWrap.className = "banner-wrap";
454
+ const banner = document.createElement("bv-alert-banner");
455
+ banner.setAttribute("variant", "warning");
456
+ banner.setAttribute("heading", "Date range exceeds 5 years");
457
+ banner.setAttribute(
458
+ "message",
459
+ "Only CSV download is available for this date range. Live report generation is not supported."
460
+ );
461
+ banner.hidden = true;
462
+ this._bannerEl = banner;
463
+ bannerWrap.appendChild(banner);
464
+ main.append(calsWrap, bannerWrap, footer);
465
+ picker.append(sidebar, main);
466
+ shadow.appendChild(picker);
467
+ this._syncCalendars();
468
+ this._syncInputs();
469
+ this._syncPresets();
470
+ this._syncApply();
471
+ this._syncBanner();
472
+ }
473
+ _buildCalendarShell(side) {
474
+ const cal = document.createElement("div");
475
+ cal.className = `calendar calendar--${side}`;
476
+ const header = document.createElement("div");
477
+ header.className = "calendar-header";
478
+ const prevBtn = document.createElement("button");
479
+ prevBtn.type = "button";
480
+ prevBtn.className = "nav-btn";
481
+ prevBtn.setAttribute("aria-label", "Previous month");
482
+ prevBtn.innerHTML = CHEVRON_LEFT;
483
+ prevBtn.addEventListener("click", () => this._navigate(-1));
484
+ const title = document.createElement("span");
485
+ title.className = "calendar-title";
486
+ const nextBtn = document.createElement("button");
487
+ nextBtn.type = "button";
488
+ nextBtn.className = "nav-btn";
489
+ nextBtn.setAttribute("aria-label", "Next month");
490
+ nextBtn.innerHTML = CHEVRON_RIGHT;
491
+ nextBtn.addEventListener("click", () => this._navigate(1));
492
+ header.append(prevBtn, title, nextBtn);
493
+ const weekdaysRow = document.createElement("div");
494
+ weekdaysRow.className = "weekdays";
495
+ for (const d of WEEKDAYS) {
496
+ const wd = document.createElement("span");
497
+ wd.className = "weekday";
498
+ wd.textContent = d;
499
+ weekdaysRow.appendChild(wd);
500
+ }
501
+ const grid = document.createElement("div");
502
+ grid.className = "days-grid";
503
+ cal.append(header, weekdaysRow, grid);
504
+ if (side === "left") {
505
+ this._leftTitle = title;
506
+ this._leftGrid = grid;
507
+ } else {
508
+ this._rightTitle = title;
509
+ this._rightGrid = grid;
510
+ }
511
+ return cal;
512
+ }
513
+ _navigate(delta) {
514
+ this._leftMonth += delta;
515
+ if (this._leftMonth > 11) {
516
+ this._leftMonth = 0;
517
+ this._leftYear++;
518
+ } else if (this._leftMonth < 0) {
519
+ this._leftMonth = 11;
520
+ this._leftYear--;
521
+ }
522
+ this._syncCalendars();
523
+ }
524
+ _getRightMonth() {
525
+ const m = this._leftMonth + 1;
526
+ return m > 11 ? { year: this._leftYear + 1, month: 0 } : { year: this._leftYear, month: m };
527
+ }
528
+ _syncCalendars() {
529
+ if (!this._leftGrid || !this._rightGrid) return;
530
+ const right = this._getRightMonth();
531
+ if (this._leftTitle) {
532
+ this._leftTitle.textContent = `${MONTH_NAMES[this._leftMonth]} ${this._leftYear}`;
533
+ }
534
+ if (this._rightTitle) {
535
+ this._rightTitle.textContent = `${MONTH_NAMES[right.month]} ${right.year}`;
536
+ }
537
+ this._buildDaysGrid(this._leftGrid, this._leftYear, this._leftMonth, this._leftDayMap);
538
+ this._buildDaysGrid(this._rightGrid, right.year, right.month, this._rightDayMap);
539
+ }
540
+ _buildDaysGrid(container, year, month, map) {
541
+ container.innerHTML = "";
542
+ map.clear();
543
+ const firstDow = new Date(year, month, 1).getDay();
544
+ const offset = firstDow === 0 ? 6 : firstDow - 1;
545
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
546
+ const totalCells = Math.ceil((offset + daysInMonth) / 7) * 7;
547
+ for (let i = 0; i < totalCells; i++) {
548
+ let iso;
549
+ let dayNum;
550
+ if (i < offset) {
551
+ const blank = document.createElement("span");
552
+ blank.className = "day day--blank";
553
+ container.appendChild(blank);
554
+ continue;
555
+ } else if (i >= offset + daysInMonth) {
556
+ const blank = document.createElement("span");
557
+ blank.className = "day day--blank";
558
+ container.appendChild(blank);
559
+ continue;
560
+ } else {
561
+ dayNum = i - offset + 1;
562
+ iso = `${year}-${String(month + 1).padStart(2, "0")}-${String(dayNum).padStart(2, "0")}`;
563
+ }
564
+ const btn = document.createElement("button");
565
+ btn.type = "button";
566
+ btn.dataset["date"] = iso;
567
+ btn.dataset["weekPos"] = String(i % 7);
568
+ btn.dataset["otherMonth"] = "0";
569
+ btn.dataset["dayNum"] = String(dayNum);
570
+ btn.dataset["daysInMonth"] = String(daysInMonth);
571
+ const inner = document.createElement("span");
572
+ inner.className = "day-inner";
573
+ inner.textContent = String(dayNum);
574
+ btn.appendChild(inner);
575
+ btn.addEventListener("click", () => this._selectDate(iso));
576
+ btn.addEventListener("mouseenter", () => this._onHover(iso));
577
+ this._applyDayClasses(btn, iso, false, i % 7, daysInMonth, dayNum);
578
+ map.set(iso, btn);
579
+ container.appendChild(btn);
580
+ }
581
+ }
582
+ _applyDayClasses(btn, iso, isOtherMonth, weekPos, daysInMonth, dayNum) {
583
+ const classes = ["day"];
584
+ if (isOtherMonth) classes.push("other-month");
585
+ if (iso === this._today) classes.push("today");
586
+ if (iso === this._start) classes.push("start");
587
+ if (iso === this._end) classes.push("end");
588
+ if (weekPos === 0 || dayNum === 1) classes.push("week-start");
589
+ if (weekPos === 6 || dayNum === daysInMonth) classes.push("week-end");
590
+ const effectiveEnd = this._picking && this._hover ? this._hover : this._end;
591
+ if (this._start && effectiveEnd) {
592
+ const [s, e] = this._start <= effectiveEnd ? [this._start, effectiveEnd] : [effectiveEnd, this._start];
593
+ if (iso > s && iso < e) classes.push("in-range");
594
+ if (iso === s && s !== e) classes.push("range-start");
595
+ if (iso === e && s !== e) classes.push("range-end");
596
+ }
597
+ btn.className = classes.join(" ");
598
+ }
599
+ _onHover(iso) {
600
+ if (!this._picking || this._hover === iso) return;
601
+ this._hover = iso;
602
+ this._updateDayClasses();
603
+ }
604
+ _updateDayClasses() {
605
+ const right = this._getRightMonth();
606
+ const rightDaysInMonth = new Date(right.year, right.month + 1, 0).getDate();
607
+ const leftDaysInMonth = new Date(this._leftYear, this._leftMonth + 1, 0).getDate();
608
+ this._leftDayMap.forEach((btn, iso) => {
609
+ this._applyDayClasses(
610
+ btn,
611
+ iso,
612
+ btn.dataset["otherMonth"] === "1",
613
+ parseInt(btn.dataset["weekPos"] ?? "0", 10),
614
+ leftDaysInMonth,
615
+ parseInt(btn.dataset["dayNum"] ?? "1", 10)
616
+ );
617
+ });
618
+ this._rightDayMap.forEach((btn, iso) => {
619
+ this._applyDayClasses(
620
+ btn,
621
+ iso,
622
+ btn.dataset["otherMonth"] === "1",
623
+ parseInt(btn.dataset["weekPos"] ?? "0", 10),
624
+ rightDaysInMonth,
625
+ parseInt(btn.dataset["dayNum"] ?? "1", 10)
626
+ );
627
+ });
628
+ }
629
+ _selectDate(iso) {
630
+ if (!this._picking) {
631
+ this._start = iso;
632
+ this._end = "";
633
+ this._preset = "custom";
634
+ this._picking = true;
635
+ this._hover = "";
636
+ } else {
637
+ if (iso < this._start) {
638
+ this._end = this._start;
639
+ this._start = iso;
640
+ } else {
641
+ this._end = iso;
642
+ }
643
+ this._picking = false;
644
+ this._hover = "";
645
+ this._preset = "custom";
646
+ }
647
+ this._syncCalendars();
648
+ this._syncInputs();
649
+ this._syncPresets();
650
+ this._syncApply();
651
+ this._syncBanner();
652
+ }
653
+ _selectPreset(key) {
654
+ if (key === "custom") {
655
+ this._preset = "custom";
656
+ this._picking = false;
657
+ this._hover = "";
658
+ this._syncPresets();
659
+ return;
660
+ }
661
+ const { start, end } = getPresetDates(key);
662
+ this._start = start;
663
+ this._end = end;
664
+ this._preset = key;
665
+ this._picking = false;
666
+ this._hover = "";
667
+ if (start) {
668
+ const parts = start.split("-");
669
+ const y = parseInt(parts[0], 10);
670
+ const m = parseInt(parts[1], 10) - 1;
671
+ if (!isNaN(y) && !isNaN(m)) {
672
+ this._leftYear = y;
673
+ this._leftMonth = m;
674
+ }
675
+ }
676
+ this._syncCalendars();
677
+ this._syncInputs();
678
+ this._syncPresets();
679
+ this._syncApply();
680
+ this._syncBanner();
681
+ }
682
+ _onInputBlur(input, field) {
683
+ const iso = parseDisplay(input.value);
684
+ if (iso) {
685
+ if (field === "start") this._start = iso;
686
+ else this._end = iso;
687
+ this._picking = false;
688
+ this._hover = "";
689
+ this._preset = "custom";
690
+ this._syncCalendars();
691
+ this._syncPresets();
692
+ this._syncApply();
693
+ this._syncBanner();
694
+ } else {
695
+ input.value = formatDisplay(field === "start" ? this._start : this._end);
696
+ }
697
+ }
698
+ _syncInputs() {
699
+ if (this._startInput) this._startInput.value = formatDisplay(this._start);
700
+ if (this._endInput) this._endInput.value = formatDisplay(this._end);
701
+ }
702
+ _syncPresets() {
703
+ this.shadowRoot.querySelectorAll(".preset-btn").forEach((el) => {
704
+ const btn = el;
705
+ btn.classList.toggle("active", btn.dataset["preset"] === this._preset);
706
+ });
707
+ }
708
+ _syncApply() {
709
+ if (this._applyBtn) {
710
+ this._applyBtn.disabled = !this._start || !this._end;
711
+ }
712
+ }
713
+ _syncBanner() {
714
+ if (!this._bannerEl) return;
715
+ const pickerEl = this.shadowRoot.querySelector(".picker");
716
+ if (!this._start) {
717
+ this._bannerEl.hidden = true;
718
+ pickerEl == null ? void 0 : pickerEl.classList.remove("picker--with-banner");
719
+ return;
720
+ }
721
+ const startDate = /* @__PURE__ */ new Date(this._start + "T00:00:00");
722
+ const fiveYearsAgo = /* @__PURE__ */ new Date();
723
+ fiveYearsAgo.setFullYear(fiveYearsAgo.getFullYear() - 5);
724
+ const show = startDate < fiveYearsAgo;
725
+ this._bannerEl.hidden = !show;
726
+ pickerEl == null ? void 0 : pickerEl.classList.toggle("picker--with-banner", show);
727
+ }
728
+ // Auto-insert slashes after MM and DD digits while the user types forward.
729
+ // Also syncs the banner live once the date is fully typed.
730
+ _setupDateMask(input, field) {
731
+ input.addEventListener("input", (e) => {
732
+ var _a;
733
+ const ev = e;
734
+ if ((_a = ev.inputType) == null ? void 0 : _a.startsWith("delete")) return;
735
+ const digits = input.value.replace(/[^\d]/g, "");
736
+ let formatted;
737
+ if (digits.length <= 2) {
738
+ formatted = digits.length === 2 ? digits + "/" : digits;
739
+ } else if (digits.length <= 4) {
740
+ const part = digits.slice(0, 2) + "/" + digits.slice(2);
741
+ formatted = digits.length === 4 ? part + "/" : part;
742
+ } else {
743
+ formatted = digits.slice(0, 2) + "/" + digits.slice(2, 4) + "/" + digits.slice(4, 8);
744
+ }
745
+ input.value = formatted;
746
+ if (formatted.length === 10) {
747
+ const iso = parseDisplay(formatted);
748
+ if (iso) {
749
+ if (field === "start") this._start = iso;
750
+ else this._end = iso;
751
+ this._syncBanner();
752
+ }
753
+ } else if (field === "start" && formatted.length < 10) {
754
+ this._start = "";
755
+ this._syncBanner();
756
+ }
757
+ });
758
+ }
759
+ _apply() {
760
+ if (!this._start || !this._end) return;
761
+ this.setAttribute("start", this._start);
762
+ this.setAttribute("end", this._end);
763
+ if (this._preset) this.setAttribute("preset", this._preset);
764
+ this.dispatchEvent(
765
+ new CustomEvent("bv-change", {
766
+ bubbles: true,
767
+ composed: true,
768
+ detail: { start: this._start, end: this._end, preset: this._preset }
769
+ })
770
+ );
771
+ }
772
+ };
773
+ if (!customElements.get("bv-date-range-picker")) {
774
+ customElements.define("bv-date-range-picker", BvDateRangePicker);
775
+ }
776
+ export {
777
+ BvDateRangePicker
778
+ };