@reliability-design/web 1.4.4 → 1.4.5

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 (39) hide show
  1. package/dist/components/rel-accordion/rel-accordion.ts +13 -1
  2. package/dist/components/rel-button/rel-button.ts +18 -2
  3. package/dist/components/rel-calendar/rel-calendar.ts +23 -1
  4. package/dist/components/rel-carousel/rel-carousel.ts +20 -0
  5. package/dist/components/rel-checkbox/rel-checkbox.ts +4 -1
  6. package/dist/components/rel-chip/rel-chip.ts +29 -0
  7. package/dist/components/rel-date-picker/rel-date-picker.ts +156 -13
  8. package/dist/components/rel-drawer/rel-drawer.ts +22 -58
  9. package/dist/components/rel-menu/rel-menu.ts +124 -15
  10. package/dist/components/rel-menubar/rel-menubar.ts +221 -63
  11. package/dist/components/rel-nav-menu/rel-nav-menu.ts +39 -3
  12. package/dist/components/rel-otp/rel-otp.ts +3 -3
  13. package/dist/components/rel-popover/rel-popover.ts +31 -3
  14. package/dist/components/rel-range-picker/rel-range-picker.ts +134 -1
  15. package/dist/components/rel-resizable/rel-resizable-group.ts +20 -0
  16. package/dist/components/rel-segmented-button/rel-segmented-button.ts +50 -12
  17. package/dist/components/rel-select/rel-select.ts +159 -11
  18. package/dist/components/rel-sheet/rel-sheet.ts +22 -1
  19. package/dist/components/rel-sidebar/rel-sidebar.ts +43 -39
  20. package/dist/components/rel-stepper/rel-stepper.ts +44 -1
  21. package/dist/components/rel-tab/rel-tab.ts +32 -7
  22. package/dist/components/rel-time-picker/rel-time-picker.ts +338 -206
  23. package/dist/components/rel-tooltip/rel-tooltip.ts +30 -0
  24. package/dist/components/rel-topbar/rel-topbar-actions.ts +1 -1
  25. package/dist/components/rel-topbar/rel-topbar-brand.ts +1 -1
  26. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +1 -1
  27. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +1 -1
  28. package/dist/components/rel-topbar/rel-topbar-item.ts +318 -319
  29. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +1 -1
  30. package/dist/components/rel-topbar/rel-topbar-profile.ts +224 -224
  31. package/dist/components/rel-topbar/rel-topbar-utilities.ts +1 -1
  32. package/dist/components/rel-topbar/rel-topbar.ts +440 -440
  33. package/dist/index.d.mts +225 -17
  34. package/dist/index.d.ts +225 -17
  35. package/dist/index.js +1468 -344
  36. package/dist/index.js.map +1 -1
  37. package/dist/index.mjs +1721 -607
  38. package/dist/index.mjs.map +1 -1
  39. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -24,6 +24,8 @@ var RelAccordion = class extends LitElement {
24
24
  this.size = "md";
25
25
  this.type = "default";
26
26
  this.appearance = "shadow";
27
+ /** Stable id prefix wiring the header to its panel. */
28
+ this.accordionId = `rel-accordion-${Math.random().toString(36).slice(2)}`;
27
29
  }
28
30
  toggle() {
29
31
  this.open = !this.open;
@@ -40,9 +42,11 @@ var RelAccordion = class extends LitElement {
40
42
  <div part="base" class="accordion">
41
43
  <div
42
44
  part="trigger" class="header"
45
+ id="${this.accordionId}-header"
43
46
  role="button"
44
47
  tabindex="0"
45
48
  aria-expanded="${this.open}"
49
+ aria-controls="${this.accordionId}-body"
46
50
  @click=${this.toggle}
47
51
  @keydown=${(e) => {
48
52
  if (e.key === "Enter" || e.key === " ") {
@@ -65,7 +69,14 @@ var RelAccordion = class extends LitElement {
65
69
  </slot>
66
70
  </div>
67
71
  </div>
68
- <div part="content" class="body ${this.open ? "open" : "closed"}">
72
+ <div
73
+ part="content"
74
+ class="body ${this.open ? "open" : "closed"}"
75
+ id="${this.accordionId}-body"
76
+ role="region"
77
+ aria-labelledby="${this.accordionId}-header"
78
+ ?inert=${!this.open}
79
+ >
69
80
  <slot></slot>
70
81
  </div>
71
82
  </div>
@@ -2755,9 +2766,12 @@ RelButton.styles = css8`
2755
2766
  }
2756
2767
  }
2757
2768
 
2758
- /* Sizes */
2769
+ /* Sizes. Min-widths come from the Figma Button master (S/M/L =
2770
+ 80/100/120) so short labels like "OK" keep a proper pill shape;
2771
+ --rel-button-min-width lets a consumer override per instance. */
2759
2772
  .size-small {
2760
2773
  height: 32px;
2774
+ min-width: var(--rel-button-min-width, 80px);
2761
2775
  padding: 0 var(--rel-spacing-sm);
2762
2776
  font-family: var(--rel-action-md-font-family);
2763
2777
  font-weight: var(--rel-action-md-font-weight);
@@ -2768,6 +2782,7 @@ RelButton.styles = css8`
2768
2782
 
2769
2783
  .size-medium {
2770
2784
  height: 40px;
2785
+ min-width: var(--rel-button-min-width, 100px);
2771
2786
  gap: var(--rel-spacing-xs);
2772
2787
  padding: 0 var(--rel-spacing-md);
2773
2788
  font-family: var(--rel-action-lg-font-family);
@@ -2779,6 +2794,7 @@ RelButton.styles = css8`
2779
2794
 
2780
2795
  .size-large {
2781
2796
  height: 48px;
2797
+ min-width: var(--rel-button-min-width, 120px);
2782
2798
  padding: 0 var(--rel-spacing-lg);
2783
2799
  font-family: var(--rel-action-xl-font-family);
2784
2800
  font-weight: var(--rel-action-xl-font-weight);
@@ -2885,6 +2901,11 @@ RelButton.styles = css8`
2885
2901
  color: var(--rel-action-neutral-label-icons-ghost);
2886
2902
  }
2887
2903
 
2904
+ /* Figma master: ghost S has a narrower 56px min than primary/outline. */
2905
+ .btn-text.size-small {
2906
+ min-width: var(--rel-button-min-width, 56px);
2907
+ }
2908
+
2888
2909
  .btn-text.tone-critical {
2889
2910
  color: var(--rel-action-danger-label-icons-ghost);
2890
2911
  }
@@ -2893,6 +2914,8 @@ RelButton.styles = css8`
2893
2914
  background: transparent;
2894
2915
  color: var(--rel-action-neutral-label-icons-link);
2895
2916
  text-decoration: underline;
2917
+ /* Links are inline actions — no minimum footprint in the Figma master. */
2918
+ min-width: 0;
2896
2919
  }
2897
2920
 
2898
2921
  button.btn-link:hover:not(:disabled) {
@@ -2921,6 +2944,7 @@ RelButton.styles = css8`
2921
2944
  /* Icon Only as an independent axis: square button of the current style */
2922
2945
  .btn-icon-only {
2923
2946
  padding: 0;
2947
+ min-width: 0;
2924
2948
  }
2925
2949
 
2926
2950
  .btn-icon-only.size-small {
@@ -2939,6 +2963,7 @@ RelButton.styles = css8`
2939
2963
  width: 40px;
2940
2964
  height: 40px;
2941
2965
  padding: 0;
2966
+ min-width: 0;
2942
2967
  border-radius: 50%;
2943
2968
  }
2944
2969
  .btn-icon.tone-default {
@@ -2983,7 +3008,9 @@ RelButton.styles = css8`
2983
3008
  .btn-text: ghost gets tone-accent hovers below (this generic grey overlay
2984
3009
  has higher specificity than the per-tone ghost rules and was overriding
2985
3010
  them, which is why every ghost hover looked grey). */
2986
- button:hover:not(:disabled):not(.btn-primary):not(.btn-default):not(.btn-icon):not(.btn-secondary):not(.btn-static):not(.btn-text) {
3011
+ /* Link buttons change label color only (rule above) — the overlay fill
3012
+ here would make a hovered link read as a ghost button. */
3013
+ button:hover:not(:disabled):not(.btn-primary):not(.btn-default):not(.btn-icon):not(.btn-secondary):not(.btn-static):not(.btn-text):not(.btn-link) {
2987
3014
  background: var(--rel-action-overlay-hover);
2988
3015
  }
2989
3016
 
@@ -3335,9 +3362,28 @@ var RelCalendar = class extends LitElement9 {
3335
3362
  });
3336
3363
  }
3337
3364
  }
3365
+ /**
3366
+ * Index of the single grid cell carrying tabindex="0". The old expression
3367
+ * (`isSelected || (index === 0 && !focusedDate)`) left the grid with ZERO
3368
+ * tab stops once the user arrowed around without a selection — Tab could
3369
+ * never re-enter the calendar.
3370
+ */
3371
+ getRovingIndex(days) {
3372
+ const candidates = [
3373
+ this.focusedDate ? days.findIndex(
3374
+ (d) => d.isCurrentMonth && this.isSameDay(d.date, this.focusedDate)
3375
+ ) : -1,
3376
+ days.findIndex((d) => d.isSelected),
3377
+ days.findIndex((d) => d.isCurrentMonth && d.isToday),
3378
+ days.findIndex((d) => d.isCurrentMonth && !d.isDisabled)
3379
+ ];
3380
+ const found = candidates.find((i) => i >= 0);
3381
+ return found ?? 0;
3382
+ }
3338
3383
  render() {
3339
3384
  const days = this.getCalendarDays();
3340
3385
  const weekdayLabels = this.getWeekdayLabels();
3386
+ const rovingIndex = this.getRovingIndex(days);
3341
3387
  return html9`
3342
3388
  <div role="grid" aria-label="Calendar">
3343
3389
  <div part="header" class="header">
@@ -3390,7 +3436,7 @@ var RelCalendar = class extends LitElement9 {
3390
3436
  ?disabled=${day.isDisabled}
3391
3437
  @click=${() => this.selectDay(day)}
3392
3438
  @keydown=${(e) => this.handleKeyDown(e, day, index)}
3393
- tabindex="${day.isSelected || index === 0 && !this.focusedDate ? 0 : -1}"
3439
+ tabindex="${index === rovingIndex ? 0 : -1}"
3394
3440
  >
3395
3441
  ${day.day}
3396
3442
  </button>
@@ -3690,12 +3736,23 @@ var RelCarousel = class extends LitElement11 {
3690
3736
  // Number of clone slides prepended before the real slides
3691
3737
  this.clonesBefore = 0;
3692
3738
  this._silentJumping = false;
3739
+ this.handleFocusIn = () => {
3740
+ if (this.autoplay) this.stopAutoplay();
3741
+ };
3742
+ this.handleFocusOut = (e) => {
3743
+ if (!this.autoplay) return;
3744
+ const next = e.relatedTarget;
3745
+ if (next && (this.contains(next) || this.shadowRoot?.contains(next))) return;
3746
+ this.startAutoplay();
3747
+ };
3693
3748
  }
3694
3749
  connectedCallback() {
3695
3750
  super.connectedCallback();
3696
3751
  this.prefersReducedMotion = window.matchMedia(
3697
3752
  "(prefers-reduced-motion: reduce)"
3698
3753
  ).matches;
3754
+ this.addEventListener("focusin", this.handleFocusIn);
3755
+ this.addEventListener("focusout", this.handleFocusOut);
3699
3756
  if (this.autoplay) {
3700
3757
  this.startAutoplay();
3701
3758
  }
@@ -3727,6 +3784,8 @@ var RelCarousel = class extends LitElement11 {
3727
3784
  }
3728
3785
  disconnectedCallback() {
3729
3786
  super.disconnectedCallback();
3787
+ this.removeEventListener("focusin", this.handleFocusIn);
3788
+ this.removeEventListener("focusout", this.handleFocusOut);
3730
3789
  this._ro?.disconnect();
3731
3790
  this.stopAutoplay();
3732
3791
  if (this.animationId) {
@@ -4041,6 +4100,7 @@ var RelCarousel = class extends LitElement11 {
4041
4100
  class="dot ${i === this.value ? "active" : ""}"
4042
4101
  part="dot"
4043
4102
  aria-label="Go to slide ${i + 1}"
4103
+ aria-current="${i === this.value ? "true" : nothing5}"
4044
4104
  @click=${() => this.goToSlide(i)}
4045
4105
  ></button>
4046
4106
  `) : nothing5}
@@ -4421,7 +4481,7 @@ RelCardMedia = __decorateClass([
4421
4481
  ], RelCardMedia);
4422
4482
 
4423
4483
  // src/components/rel-checkbox/rel-checkbox.ts
4424
- import { LitElement as LitElement13, html as html13, css as css13 } from "lit";
4484
+ import { LitElement as LitElement13, html as html13, css as css13, nothing as nothing6 } from "lit";
4425
4485
  import { customElement as customElement13, property as property13 } from "lit/decorators.js";
4426
4486
  import "@reliability-design/icons/rel-icon";
4427
4487
  var RelCheckbox = class extends LitElement13 {
@@ -4488,6 +4548,9 @@ var RelCheckbox = class extends LitElement13 {
4488
4548
  <label class="row">
4489
4549
  <input
4490
4550
  type="checkbox"
4551
+ .checked=${this.status === "checked"}
4552
+ .indeterminate=${this.status === "indeterminate"}
4553
+ aria-checked="${this.status === "indeterminate" ? "mixed" : nothing6}"
4491
4554
  @click=${this.toggle}
4492
4555
  @blur=${() => this._onTouched()}
4493
4556
  ?disabled=${this.state === "disabled"}
@@ -4801,7 +4864,7 @@ RelCheckbox = __decorateClass([
4801
4864
  ], RelCheckbox);
4802
4865
 
4803
4866
  // src/components/rel-date-picker/rel-date-picker.ts
4804
- import { LitElement as LitElement14, html as html14, css as css14, nothing as nothing6 } from "lit";
4867
+ import { LitElement as LitElement14, html as html14, css as css14, nothing as nothing7 } from "lit";
4805
4868
  import { customElement as customElement14, property as property14, state as state5, query as query3 } from "lit/decorators.js";
4806
4869
 
4807
4870
  // src/components/rel-date-picker/date-format.ts
@@ -4826,6 +4889,109 @@ function formatDatePattern(date, pattern, locale = "en-US") {
4826
4889
  );
4827
4890
  }
4828
4891
 
4892
+ // src/utils/focus.ts
4893
+ var FOCUSABLE_SELECTOR = [
4894
+ 'a[href]:not([tabindex="-1"])',
4895
+ 'button:not([disabled]):not([tabindex="-1"])',
4896
+ 'input:not([disabled]):not([tabindex="-1"])',
4897
+ 'select:not([disabled]):not([tabindex="-1"])',
4898
+ 'textarea:not([disabled]):not([tabindex="-1"])',
4899
+ 'audio[controls]:not([tabindex="-1"])',
4900
+ 'video[controls]:not([tabindex="-1"])',
4901
+ '[contenteditable]:not([contenteditable="false"]):not([tabindex="-1"])',
4902
+ '[tabindex]:not([tabindex="-1"])'
4903
+ ].join(",");
4904
+ function isVisible(el) {
4905
+ return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
4906
+ }
4907
+ function getFocusableElements(root) {
4908
+ const out = [];
4909
+ const visit = (el) => {
4910
+ if (el instanceof HTMLElement && el.matches(FOCUSABLE_SELECTOR) && isVisible(el)) {
4911
+ out.push(el);
4912
+ }
4913
+ if (el instanceof HTMLSlotElement) {
4914
+ el.assignedElements({ flatten: true }).forEach(visit);
4915
+ } else if (el.shadowRoot) {
4916
+ Array.from(el.shadowRoot.children).forEach(visit);
4917
+ } else {
4918
+ Array.from(el.children).forEach(visit);
4919
+ }
4920
+ };
4921
+ const start = root instanceof ShadowRoot ? Array.from(root.children) : root.shadowRoot ? Array.from(root.shadowRoot.children) : Array.from(root.children);
4922
+ start.forEach(visit);
4923
+ return out;
4924
+ }
4925
+ function getDeepActiveElement() {
4926
+ let active = document.activeElement;
4927
+ while (active?.shadowRoot?.activeElement) {
4928
+ active = active.shadowRoot.activeElement;
4929
+ }
4930
+ return active instanceof HTMLElement ? active : null;
4931
+ }
4932
+ function trapTabKey(e, container) {
4933
+ if (e.key !== "Tab") return;
4934
+ const focusable = getFocusableElements(container);
4935
+ if (focusable.length === 0) {
4936
+ e.preventDefault();
4937
+ return;
4938
+ }
4939
+ const first = focusable[0];
4940
+ const last = focusable[focusable.length - 1];
4941
+ const active = getDeepActiveElement();
4942
+ const inside = active ? focusable.includes(active) : false;
4943
+ if (e.shiftKey) {
4944
+ if (!inside || active === first) {
4945
+ e.preventDefault();
4946
+ last.focus();
4947
+ }
4948
+ } else {
4949
+ if (!inside || active === last) {
4950
+ e.preventDefault();
4951
+ first.focus();
4952
+ }
4953
+ }
4954
+ }
4955
+ var FocusTrap = class {
4956
+ constructor(getContainer) {
4957
+ this.getContainer = getContainer;
4958
+ this.previousFocus = null;
4959
+ this.active = false;
4960
+ this.onKeyDown = (e) => {
4961
+ const container = this.getContainer();
4962
+ if (container) trapTabKey(e, container);
4963
+ };
4964
+ }
4965
+ activate(options) {
4966
+ if (this.active) return;
4967
+ this.active = true;
4968
+ this.previousFocus = getDeepActiveElement();
4969
+ document.addEventListener("keydown", this.onKeyDown, true);
4970
+ requestAnimationFrame(() => {
4971
+ if (!this.active) return;
4972
+ const container = this.getContainer();
4973
+ if (!container) return;
4974
+ const target = options?.initialFocus ?? getFocusableElements(container)[0] ?? null;
4975
+ if (target) {
4976
+ target.focus();
4977
+ } else if (container instanceof HTMLElement) {
4978
+ container.tabIndex = -1;
4979
+ container.focus();
4980
+ }
4981
+ });
4982
+ }
4983
+ deactivate(options) {
4984
+ if (!this.active) return;
4985
+ this.active = false;
4986
+ document.removeEventListener("keydown", this.onKeyDown, true);
4987
+ const previous = this.previousFocus;
4988
+ this.previousFocus = null;
4989
+ if (options?.restoreFocus !== false && previous?.isConnected) {
4990
+ requestAnimationFrame(() => previous.focus());
4991
+ }
4992
+ }
4993
+ };
4994
+
4829
4995
  // src/components/rel-date-picker/rel-date-picker.ts
4830
4996
  var RelDatePicker = class extends LitElement14 {
4831
4997
  constructor() {
@@ -4863,9 +5029,58 @@ var RelDatePicker = class extends LitElement14 {
4863
5029
  }
4864
5030
  };
4865
5031
  this.handleEscapeKey = (e) => {
4866
- if (e.key === "Escape" && this.open) {
5032
+ if (!this.open) return;
5033
+ if (e.key === "Escape") {
4867
5034
  this.closeCalendarPopover();
5035
+ return;
5036
+ }
5037
+ if (e.key === "Tab") {
5038
+ const popover = this.renderRoot.querySelector(".popover");
5039
+ if (popover) trapTabKey(e, popover);
5040
+ }
5041
+ };
5042
+ this.handleDropdownKeydown = (e) => {
5043
+ const menu = e.currentTarget;
5044
+ const items = Array.from(
5045
+ menu.querySelectorAll(".dropdown-item")
5046
+ );
5047
+ if (items.length === 0) return;
5048
+ if (e.key === "Escape") {
5049
+ e.preventDefault();
5050
+ e.stopPropagation();
5051
+ const trigger = menu.closest(".dropdown-container")?.querySelector(".dropdown-trigger");
5052
+ this.monthDropdownOpen = false;
5053
+ this.yearDropdownOpen = false;
5054
+ trigger?.focus();
5055
+ return;
5056
+ }
5057
+ if (e.key === "Tab") {
5058
+ this.monthDropdownOpen = false;
5059
+ this.yearDropdownOpen = false;
5060
+ return;
5061
+ }
5062
+ const idx = items.indexOf(getDeepActiveElement());
5063
+ let target;
5064
+ switch (e.key) {
5065
+ case "ArrowDown":
5066
+ target = Math.min(items.length - 1, idx + 1);
5067
+ break;
5068
+ case "ArrowUp":
5069
+ target = Math.max(0, idx - 1);
5070
+ break;
5071
+ case "Home":
5072
+ target = 0;
5073
+ break;
5074
+ case "End":
5075
+ target = items.length - 1;
5076
+ break;
5077
+ default:
5078
+ return;
4868
5079
  }
5080
+ e.preventDefault();
5081
+ e.stopPropagation();
5082
+ items[target]?.focus();
5083
+ items[target]?.scrollIntoView({ block: "nearest" });
4869
5084
  };
4870
5085
  }
4871
5086
  // minDate/maxDate supersede the deprecated min/max aliases
@@ -4902,10 +5117,12 @@ var RelDatePicker = class extends LitElement14 {
4902
5117
  }
4903
5118
  if (changedProperties.has("open") && this.open) {
4904
5119
  setTimeout(() => {
4905
- const firstDay = this.calendarGrid?.querySelector(
5120
+ const target = this.calendarGrid?.querySelector(
5121
+ '.day-button[tabindex="0"]:not(:disabled)'
5122
+ ) ?? this.calendarGrid?.querySelector(
4906
5123
  ".day-button:not(:disabled)"
4907
5124
  );
4908
- firstDay?.focus();
5125
+ target?.focus();
4909
5126
  }, 100);
4910
5127
  }
4911
5128
  }
@@ -5203,27 +5420,67 @@ var RelDatePicker = class extends LitElement14 {
5203
5420
  e.stopPropagation();
5204
5421
  this.monthDropdownOpen = !this.monthDropdownOpen;
5205
5422
  this.yearDropdownOpen = false;
5423
+ if (this.monthDropdownOpen) this.focusOpenDropdownSelection();
5206
5424
  }
5207
5425
  toggleYearDropdown(e) {
5208
5426
  e.stopPropagation();
5209
5427
  this.yearDropdownOpen = !this.yearDropdownOpen;
5210
5428
  this.monthDropdownOpen = false;
5429
+ if (this.yearDropdownOpen) this.focusOpenDropdownSelection();
5430
+ }
5431
+ handleDropdownTriggerKeydown(e, kind) {
5432
+ if (e.key !== "ArrowDown") return;
5433
+ e.preventDefault();
5434
+ e.stopPropagation();
5435
+ this.monthDropdownOpen = kind === "month";
5436
+ this.yearDropdownOpen = kind === "year";
5437
+ this.focusOpenDropdownSelection();
5438
+ }
5439
+ async focusOpenDropdownSelection() {
5440
+ await this.updateComplete;
5441
+ const menu = this.renderRoot.querySelector(".dropdown-menu.open");
5442
+ if (!menu) return;
5443
+ const target = menu.querySelector(".dropdown-item.selected") ?? menu.querySelector(".dropdown-item");
5444
+ target?.focus();
5445
+ target?.scrollIntoView({ block: "nearest" });
5211
5446
  }
5212
5447
  selectMonth(month, e) {
5213
5448
  e.stopPropagation();
5449
+ const trigger = e.target.closest(".dropdown-container")?.querySelector(".dropdown-trigger");
5214
5450
  this.viewMonth = month;
5215
5451
  this.monthDropdownOpen = false;
5452
+ this.updateComplete.then(() => trigger?.focus());
5216
5453
  }
5217
5454
  selectYear(year, e) {
5218
5455
  e.stopPropagation();
5456
+ const trigger = e.target.closest(".dropdown-container")?.querySelector(".dropdown-trigger");
5219
5457
  this.viewYear = year;
5220
5458
  this.yearDropdownOpen = false;
5459
+ this.updateComplete.then(() => trigger?.focus());
5460
+ }
5461
+ /**
5462
+ * Index of the single grid cell carrying tabindex="0". The old expression
5463
+ * (`isSelected || (index === 0 && !value)`) left the grid with ZERO tab
5464
+ * stops once the user arrowed around without a selection.
5465
+ */
5466
+ getRovingIndex(days) {
5467
+ const candidates = [
5468
+ this.focusedDate ? days.findIndex(
5469
+ (d) => d.isCurrentMonth && this.isSameDay(d.date, this.focusedDate)
5470
+ ) : -1,
5471
+ days.findIndex((d) => d.isSelected),
5472
+ days.findIndex((d) => d.isCurrentMonth && d.isToday),
5473
+ days.findIndex((d) => d.isCurrentMonth && !d.isDisabled)
5474
+ ];
5475
+ const found = candidates.find((i) => i >= 0);
5476
+ return found ?? 0;
5221
5477
  }
5222
5478
  render() {
5223
5479
  const days = this.getCalendarDays();
5224
5480
  const weekdayLabels = this.getWeekdayLabels();
5225
5481
  const months = this.getMonthsList();
5226
5482
  const years = this.getYearsList();
5483
+ const rovingIndex = this.getRovingIndex(days);
5227
5484
  const isError = this.error;
5228
5485
  const belowText = isError && this.errorMessage ? this.errorMessage : this.helperText;
5229
5486
  const describedById = belowText ? "date-picker-desc" : void 0;
@@ -5236,10 +5493,10 @@ var RelDatePicker = class extends LitElement14 {
5236
5493
  return html14`
5237
5494
  <div part="base" class="${wrapperClasses}">
5238
5495
  ${this.label ? html14`<label part="label" class="label" id="date-picker-label"
5239
- >${this.label}${this.required ? html14`<span class="required-mark" aria-hidden="true">*</span>` : nothing6}</label
5240
- >` : nothing6}
5496
+ >${this.label}${this.required ? html14`<span class="required-mark" aria-hidden="true">*</span>` : nothing7}</label
5497
+ >` : nothing7}
5241
5498
 
5242
- ${this.name ? html14`<input type="hidden" name=${this.name} .value=${this.value ?? ""} />` : nothing6}
5499
+ ${this.name ? html14`<input type="hidden" name=${this.name} .value=${this.value ?? ""} />` : nothing7}
5243
5500
 
5244
5501
  <button
5245
5502
  class="trigger-button ${isError ? "error" : ""}"
@@ -5253,8 +5510,8 @@ var RelDatePicker = class extends LitElement14 {
5253
5510
  aria-required=${this.required}
5254
5511
  aria-invalid=${isError}
5255
5512
  aria-readonly=${this.readonly}
5256
- aria-describedby=${describedById ?? nothing6}
5257
- aria-labelledby=${this.label ? "date-picker-label" : nothing6}
5513
+ aria-describedby=${describedById ?? nothing7}
5514
+ aria-labelledby=${this.label ? "date-picker-label" : nothing7}
5258
5515
  >
5259
5516
  <span class="trigger-content ${this.value ? "" : "placeholder"}">
5260
5517
  ${this.value ? this.formatDisplayDate(this.value) : this.placeholder}
@@ -5276,7 +5533,7 @@ var RelDatePicker = class extends LitElement14 {
5276
5533
  />
5277
5534
  </svg>
5278
5535
  </button>
5279
- ` : nothing6}
5536
+ ` : nothing7}
5280
5537
  <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
5281
5538
  <path
5282
5539
  d="M4 2h1V1h2v1h2V1h2v1h1a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2zm8 3H4v7h8V5z"
@@ -5310,22 +5567,31 @@ var RelDatePicker = class extends LitElement14 {
5310
5567
  class="dropdown-trigger"
5311
5568
  type="button"
5312
5569
  @click=${this.toggleMonthDropdown}
5570
+ @keydown=${(e) => this.handleDropdownTriggerKeydown(e, "month")}
5313
5571
  aria-label="Select month"
5572
+ aria-haspopup="listbox"
5314
5573
  aria-expanded=${this.monthDropdownOpen}
5315
5574
  >
5316
5575
  ${this.getMonthName()}
5317
5576
  </button>
5318
- <div class="dropdown-menu ${this.monthDropdownOpen ? "open" : ""}">
5577
+ <div
5578
+ class="dropdown-menu ${this.monthDropdownOpen ? "open" : ""}"
5579
+ role="listbox"
5580
+ aria-label="Month"
5581
+ @keydown=${this.handleDropdownKeydown}
5582
+ >
5319
5583
  ${months.map(
5320
5584
  (m) => html14`
5321
- <div
5585
+ <button
5322
5586
  class="dropdown-item ${m.value === this.viewMonth ? "selected" : ""}"
5587
+ type="button"
5588
+ tabindex="-1"
5323
5589
  @click=${(e) => this.selectMonth(m.value, e)}
5324
5590
  role="option"
5325
5591
  aria-selected=${m.value === this.viewMonth}
5326
5592
  >
5327
5593
  ${m.label}
5328
- </div>
5594
+ </button>
5329
5595
  `
5330
5596
  )}
5331
5597
  </div>
@@ -5336,22 +5602,31 @@ var RelDatePicker = class extends LitElement14 {
5336
5602
  class="dropdown-trigger"
5337
5603
  type="button"
5338
5604
  @click=${this.toggleYearDropdown}
5605
+ @keydown=${(e) => this.handleDropdownTriggerKeydown(e, "year")}
5339
5606
  aria-label="Select year"
5607
+ aria-haspopup="listbox"
5340
5608
  aria-expanded=${this.yearDropdownOpen}
5341
5609
  >
5342
5610
  ${this.viewYear}
5343
5611
  </button>
5344
- <div class="dropdown-menu ${this.yearDropdownOpen ? "open" : ""}">
5612
+ <div
5613
+ class="dropdown-menu ${this.yearDropdownOpen ? "open" : ""}"
5614
+ role="listbox"
5615
+ aria-label="Year"
5616
+ @keydown=${this.handleDropdownKeydown}
5617
+ >
5345
5618
  ${years.map(
5346
5619
  (y) => html14`
5347
- <div
5620
+ <button
5348
5621
  class="dropdown-item ${y === this.viewYear ? "selected" : ""}"
5622
+ type="button"
5623
+ tabindex="-1"
5349
5624
  @click=${(e) => this.selectYear(y, e)}
5350
5625
  role="option"
5351
5626
  aria-selected=${y === this.viewYear}
5352
5627
  >
5353
5628
  ${y}
5354
- </div>
5629
+ </button>
5355
5630
  `
5356
5631
  )}
5357
5632
  </div>
@@ -5394,7 +5669,7 @@ var RelDatePicker = class extends LitElement14 {
5394
5669
  ?disabled=${day.isDisabled}
5395
5670
  @click=${() => this.selectDay(day)}
5396
5671
  @keydown=${(e) => this.handleDayKeydown(e, day, index)}
5397
- tabindex="${day.isSelected || index === 0 && !this.value ? 0 : -1}"
5672
+ tabindex="${index === rovingIndex ? 0 : -1}"
5398
5673
  >
5399
5674
  ${day.day}
5400
5675
  </button>
@@ -5405,7 +5680,7 @@ var RelDatePicker = class extends LitElement14 {
5405
5680
 
5406
5681
  ${belowText ? html14`<div class="date-picker-support ${isError ? "error" : ""}" id=${describedById}>
5407
5682
  ${belowText}
5408
- </div>` : nothing6}
5683
+ </div>` : nothing7}
5409
5684
  </div>
5410
5685
  `;
5411
5686
  }
@@ -5688,6 +5963,11 @@ RelDatePicker.styles = css14`
5688
5963
  }
5689
5964
 
5690
5965
  .dropdown-item {
5966
+ display: block;
5967
+ width: 100%;
5968
+ border: none;
5969
+ background: transparent;
5970
+ text-align: left;
5691
5971
  padding: var(--rel-spacing-xs) var(--rel-spacing-sm);
5692
5972
  cursor: pointer;
5693
5973
  color: var(--rel-text-default);
@@ -5699,6 +5979,11 @@ RelDatePicker.styles = css14`
5699
5979
  letter-spacing: var(--rel-body-sm-regular-letter-spacing);
5700
5980
  }
5701
5981
 
5982
+ .dropdown-item:focus-visible {
5983
+ outline: 2px solid var(--rel-border-focus);
5984
+ outline-offset: -2px;
5985
+ }
5986
+
5702
5987
  .dropdown-item:hover {
5703
5988
  background: var(--rel-bg-surface-elevated);
5704
5989
  }
@@ -5897,7 +6182,7 @@ RelDatePicker = __decorateClass([
5897
6182
  ], RelDatePicker);
5898
6183
 
5899
6184
  // src/components/rel-range-picker/rel-range-picker.ts
5900
- import { LitElement as LitElement15, html as html15, css as css15, nothing as nothing7 } from "lit";
6185
+ import { LitElement as LitElement15, html as html15, css as css15, nothing as nothing8 } from "lit";
5901
6186
  import { customElement as customElement15, property as property15, state as state6, query as query4 } from "lit/decorators.js";
5902
6187
  import "@reliability-design/icons/rel-icon";
5903
6188
  var RelRangePicker = class extends LitElement15 {
@@ -5927,6 +6212,7 @@ var RelRangePicker = class extends LitElement15 {
5927
6212
  this.viewMonth = (/* @__PURE__ */ new Date()).getMonth();
5928
6213
  this.isSelectingRange = false;
5929
6214
  this.hoverDate = null;
6215
+ this.focusedDate = null;
5930
6216
  this.onReposition = () => {
5931
6217
  if (this.open && this.mode === "popover") this.updatePopoverPosition();
5932
6218
  };
@@ -5983,6 +6269,69 @@ var RelRangePicker = class extends LitElement15 {
5983
6269
  const qs = this.getQuickSelects().find((q) => q.label === label);
5984
6270
  if (qs) this.selectQuickSelect(qs);
5985
6271
  };
6272
+ this.handleGridKeydown = (e) => {
6273
+ const cell = e.target.closest?.(".day-cell");
6274
+ const iso = cell?.dataset.iso;
6275
+ if (!iso) return;
6276
+ const date = this.parseISODate(iso);
6277
+ if (!date) return;
6278
+ if (e.key === "Enter" || e.key === " ") {
6279
+ e.preventDefault();
6280
+ const isDisabled = this.isDateDisabled(date);
6281
+ if (!isDisabled) {
6282
+ this.handleDayClick({
6283
+ date,
6284
+ day: date.getDate(),
6285
+ isCurrentMonth: true,
6286
+ isToday: false,
6287
+ isDraftFrom: false,
6288
+ isDraftTo: false,
6289
+ isInRange: false,
6290
+ isDisabled,
6291
+ isWeekend: false
6292
+ });
6293
+ }
6294
+ return;
6295
+ }
6296
+ const next = new Date(date);
6297
+ const dow = next.getDay();
6298
+ switch (e.key) {
6299
+ case "ArrowLeft":
6300
+ next.setDate(next.getDate() - 1);
6301
+ break;
6302
+ case "ArrowRight":
6303
+ next.setDate(next.getDate() + 1);
6304
+ break;
6305
+ case "ArrowUp":
6306
+ next.setDate(next.getDate() - 7);
6307
+ break;
6308
+ case "ArrowDown":
6309
+ next.setDate(next.getDate() + 7);
6310
+ break;
6311
+ case "Home":
6312
+ next.setDate(
6313
+ next.getDate() - (this.weekStart === "mon" ? dow === 0 ? 6 : dow - 1 : dow)
6314
+ );
6315
+ break;
6316
+ case "End":
6317
+ next.setDate(
6318
+ next.getDate() + (this.weekStart === "mon" ? dow === 0 ? 0 : 7 - dow : 6 - dow)
6319
+ );
6320
+ break;
6321
+ case "PageUp":
6322
+ if (e.shiftKey) next.setFullYear(next.getFullYear() - 1);
6323
+ else next.setMonth(next.getMonth() - 1);
6324
+ break;
6325
+ case "PageDown":
6326
+ if (e.shiftKey) next.setFullYear(next.getFullYear() + 1);
6327
+ else next.setMonth(next.getMonth() + 1);
6328
+ break;
6329
+ default:
6330
+ return;
6331
+ }
6332
+ e.preventDefault();
6333
+ this.moveGridFocusTo(next);
6334
+ };
5986
6335
  }
5987
6336
  // ── Lifecycle ──
5988
6337
  connectedCallback() {
@@ -6067,6 +6416,7 @@ var RelRangePicker = class extends LitElement15 {
6067
6416
  this.draftActivePreset = null;
6068
6417
  this.isSelectingRange = false;
6069
6418
  this.hoverDate = null;
6419
+ this.focusedDate = null;
6070
6420
  if (this.draftFrom) {
6071
6421
  const date = this.parseISODate(this.draftFrom);
6072
6422
  if (date) {
@@ -6365,10 +6715,45 @@ var RelRangePicker = class extends LitElement15 {
6365
6715
  if (!this.isSelectingRange || day.isDisabled) return;
6366
6716
  this.hoverDate = this.formatISODate(day.date);
6367
6717
  }
6718
+ // ── Grid keyboard navigation (APG grid pattern) ──
6719
+ /**
6720
+ * The cell that carries tabindex="0". Prefers the last roved date, then the
6721
+ * draft start, then today, then the first selectable day — always exactly
6722
+ * one Tab stop, even after arrowing away with nothing selected.
6723
+ */
6724
+ getRovingIso(days) {
6725
+ const inView = days.filter((d) => d.isCurrentMonth);
6726
+ if (inView.length === 0) return "";
6727
+ const candidates = [
6728
+ this.focusedDate,
6729
+ this.draftFrom,
6730
+ this.formatISODate(/* @__PURE__ */ new Date())
6731
+ ];
6732
+ for (const iso of candidates) {
6733
+ if (iso && inView.some((d) => this.formatISODate(d.date) === iso)) {
6734
+ return iso;
6735
+ }
6736
+ }
6737
+ const firstEnabled = inView.find((d) => !d.isDisabled) ?? inView[0];
6738
+ return this.formatISODate(firstEnabled.date);
6739
+ }
6740
+ async moveGridFocusTo(date) {
6741
+ this.focusedDate = this.formatISODate(date);
6742
+ if (date.getMonth() !== this.viewMonth || date.getFullYear() !== this.viewYear) {
6743
+ this.viewMonth = date.getMonth();
6744
+ this.viewYear = date.getFullYear();
6745
+ }
6746
+ if (this.isSelectingRange && !this.isDateDisabled(date)) {
6747
+ this.hoverDate = this.focusedDate;
6748
+ }
6749
+ await this.updateComplete;
6750
+ this.renderRoot.querySelector(`.day-cell[data-iso="${this.focusedDate}"]`)?.focus();
6751
+ }
6368
6752
  // ── Render ──
6369
6753
  render() {
6370
6754
  const quickSelects = this.getQuickSelects();
6371
6755
  const days = this.getCalendarDays();
6756
+ const rovingIso = this.getRovingIso(days);
6372
6757
  const weekdayLabels = this.getWeekdayLabels();
6373
6758
  const draftFromDisplay = this.draftFrom ? this.formatDisplayDate(this.draftFrom) : "";
6374
6759
  const draftToDisplay = this.draftTo ? this.formatDisplayDate(this.draftTo) : "";
@@ -6407,7 +6792,7 @@ var RelRangePicker = class extends LitElement15 {
6407
6792
  </button>
6408
6793
  `}
6409
6794
 
6410
- ${isPopup && this.open ? html15`<div part="overlay" class="backdrop" popover="manual" @click=${this.cancelPopover}></div>` : nothing7}
6795
+ ${isPopup && this.open ? html15`<div part="overlay" class="backdrop" popover="manual" @click=${this.cancelPopover}></div>` : nothing8}
6411
6796
 
6412
6797
  <div
6413
6798
  part="panel" class="popover ${this.open ? "open" : ""} ${isPopup ? "popup" : ""}"
@@ -6435,7 +6820,7 @@ var RelRangePicker = class extends LitElement15 {
6435
6820
  <circle cx="12" cy="12" r="12" fill="var(--rel-bg-brand)"/>
6436
6821
  <path d="M7 12.5l3.5 3.5 6.5-7" stroke="var(--rel-text-static-dark)" stroke-width="2"
6437
6822
  stroke-linecap="round" stroke-linejoin="round"/>
6438
- </svg>` : nothing7}
6823
+ </svg>` : nothing8}
6439
6824
  </button>
6440
6825
  `
6441
6826
  )}
@@ -6497,8 +6882,10 @@ var RelRangePicker = class extends LitElement15 {
6497
6882
  @mouseleave=${() => {
6498
6883
  this.hoverDate = null;
6499
6884
  }}
6885
+ @keydown=${this.handleGridKeydown}
6500
6886
  >
6501
6887
  ${days.map((day) => {
6888
+ const iso = this.formatISODate(day.date);
6502
6889
  const cellClasses = [
6503
6890
  "day-cell",
6504
6891
  day.isInRange ? "in-range" : "",
@@ -6513,8 +6900,11 @@ var RelRangePicker = class extends LitElement15 {
6513
6900
  <div
6514
6901
  class="${cellClasses}"
6515
6902
  role="gridcell"
6516
- aria-label="${this.formatISODate(day.date)}"
6903
+ tabindex="${day.isCurrentMonth && iso === rovingIso ? 0 : -1}"
6904
+ data-iso="${iso}"
6905
+ aria-label="${iso}"
6517
6906
  aria-selected="${day.isDraftFrom || day.isDraftTo || day.isInRange}"
6907
+ aria-disabled="${day.isDisabled ? "true" : nothing8}"
6518
6908
  @click=${() => this.handleDayClick(day)}
6519
6909
  @mouseenter=${() => this.handleDayHover(day)}
6520
6910
  >
@@ -6859,6 +7249,12 @@ RelRangePicker.styles = css15`
6859
7249
  cursor: pointer;
6860
7250
  }
6861
7251
 
7252
+ .day-cell:focus-visible {
7253
+ outline: 2px solid var(--rel-border-focus);
7254
+ outline-offset: -2px;
7255
+ z-index: 2;
7256
+ }
7257
+
6862
7258
  .day-cell.other-month {
6863
7259
  opacity: 0.35;
6864
7260
  pointer-events: none;
@@ -7034,6 +7430,9 @@ __decorateClass([
7034
7430
  __decorateClass([
7035
7431
  state6()
7036
7432
  ], RelRangePicker.prototype, "hoverDate", 2);
7433
+ __decorateClass([
7434
+ state6()
7435
+ ], RelRangePicker.prototype, "focusedDate", 2);
7037
7436
  __decorateClass([
7038
7437
  query4(".trigger-button")
7039
7438
  ], RelRangePicker.prototype, "triggerButton", 2);
@@ -7063,6 +7462,33 @@ var RelChip = class extends LitElement16 {
7063
7462
  this.removed = false;
7064
7463
  this.draggableChip = false;
7065
7464
  this.dragging = false;
7465
+ /** The chip body is announced as a button, so it must also act on keys:
7466
+ * Enter/Space re-dispatch as a host click (consumers' @click handlers
7467
+ * fire), Delete/Backspace remove when removable, and arrow keys ask the
7468
+ * container to reorder a draggable chip (`chip-move`) — the keyboard
7469
+ * alternative to pointer drag-and-drop. */
7470
+ this.handleKeydown = (e) => {
7471
+ if (e.key === "Enter" || e.key === " ") {
7472
+ e.preventDefault();
7473
+ this.click();
7474
+ return;
7475
+ }
7476
+ if ((e.key === "Delete" || e.key === "Backspace") && this.removable) {
7477
+ e.preventDefault();
7478
+ this.handleRemove(e);
7479
+ return;
7480
+ }
7481
+ if (this.draggableChip && (e.key === "ArrowLeft" || e.key === "ArrowRight")) {
7482
+ e.preventDefault();
7483
+ this.dispatchEvent(
7484
+ new CustomEvent("chip-move", {
7485
+ detail: { direction: e.key === "ArrowLeft" ? -1 : 1 },
7486
+ bubbles: true,
7487
+ composed: true
7488
+ })
7489
+ );
7490
+ }
7491
+ };
7066
7492
  this.onDragStart = (e) => {
7067
7493
  if (!this.draggableChip) return;
7068
7494
  this.dragging = true;
@@ -7116,6 +7542,7 @@ var RelChip = class extends LitElement16 {
7116
7542
  role="button"
7117
7543
  tabindex="0"
7118
7544
  aria-label="${this.label}"
7545
+ @keydown=${this.handleKeydown}
7119
7546
  >
7120
7547
  ${showAvatar ? html16`<rel-avatar type="text" text=${this.avatar} size="xs"></rel-avatar>` : null}
7121
7548
  ${showLeadingIcon ? html16`<rel-icon part="icon" class="chip-icon" name="${this.leadingIcon}"></rel-icon>` : null}
@@ -7707,26 +8134,8 @@ var RelDrawer = class extends LitElement20 {
7707
8134
  this.close("escape");
7708
8135
  return;
7709
8136
  }
7710
- if (e.key === "Tab" && this.modal) {
7711
- const focusable = this.getFocusableElements();
7712
- if (focusable.length === 0) {
7713
- e.preventDefault();
7714
- return;
7715
- }
7716
- const firstFocusable = focusable[0];
7717
- const lastFocusable = focusable[focusable.length - 1];
7718
- const activeElement = document.activeElement;
7719
- if (e.shiftKey) {
7720
- if (activeElement === firstFocusable) {
7721
- e.preventDefault();
7722
- lastFocusable.focus();
7723
- }
7724
- } else {
7725
- if (activeElement === lastFocusable) {
7726
- e.preventDefault();
7727
- firstFocusable.focus();
7728
- }
7729
- }
8137
+ if (e.key === "Tab" && this.modal && this.panelElement) {
8138
+ trapTabKey(e, this.panelElement);
7730
8139
  }
7731
8140
  };
7732
8141
  // Drag-to-close handlers
@@ -7785,12 +8194,19 @@ var RelDrawer = class extends LitElement20 {
7785
8194
  }
7786
8195
  }
7787
8196
  handleOpen() {
7788
- this.previousFocus = document.activeElement;
8197
+ this.previousFocus = getDeepActiveElement();
7789
8198
  this.lockScroll();
7790
8199
  if (this.modal) {
7791
8200
  this.updateComplete.then(() => {
7792
- const focusTarget = this.querySelector("[autofocus]") ?? this.querySelector(".close-button") ?? this.querySelector(".panel");
7793
- focusTarget?.focus();
8201
+ const panel = this.panelElement;
8202
+ if (!panel) return;
8203
+ const focusTarget = getFocusableElements(panel)[0];
8204
+ if (focusTarget) {
8205
+ focusTarget.focus();
8206
+ } else {
8207
+ panel.tabIndex = -1;
8208
+ panel.focus();
8209
+ }
7794
8210
  });
7795
8211
  }
7796
8212
  document.addEventListener("keydown", this.handleKeydown);
@@ -7852,29 +8268,6 @@ var RelDrawer = class extends LitElement20 {
7852
8268
  document.body.style.overflow = this.originalBodyOverflow;
7853
8269
  document.body.style.paddingRight = this.originalBodyPaddingRight;
7854
8270
  }
7855
- getFocusableElements() {
7856
- if (!this.panelElement) return [];
7857
- const selectors = [
7858
- "a[href]",
7859
- "button:not([disabled])",
7860
- "textarea:not([disabled])",
7861
- "input:not([disabled])",
7862
- "select:not([disabled])",
7863
- '[tabindex]:not([tabindex="-1"])'
7864
- ].join(",");
7865
- const elements = Array.from(
7866
- this.panelElement.querySelectorAll(selectors)
7867
- );
7868
- const slots = this.panelElement.querySelectorAll("slot");
7869
- slots.forEach((slot) => {
7870
- const assigned = slot.assignedElements({ flatten: true });
7871
- assigned.forEach((el) => {
7872
- const focusableInSlot = el.querySelectorAll(selectors);
7873
- elements.push(...Array.from(focusableInSlot));
7874
- });
7875
- });
7876
- return elements;
7877
- }
7878
8271
  handleOverlayClick(e) {
7879
8272
  if (!this.dismissible || !this.closeOnBackdrop) return;
7880
8273
  if (e.target === this.overlayElement) {
@@ -8282,7 +8675,7 @@ RelDrawer = __decorateClass([
8282
8675
  ], RelDrawer);
8283
8676
 
8284
8677
  // src/components/rel-kbd/rel-kbd.ts
8285
- import { LitElement as LitElement21, html as html21, css as css21, nothing as nothing8 } from "lit";
8678
+ import { LitElement as LitElement21, html as html21, css as css21, nothing as nothing9 } from "lit";
8286
8679
  import { customElement as customElement21, property as property20 } from "lit/decorators.js";
8287
8680
  var RelKbd = class extends LitElement21 {
8288
8681
  constructor() {
@@ -8436,7 +8829,7 @@ var RelKbdGroup = class extends LitElement21 {
8436
8829
  return html21`
8437
8830
  ${this.items.map(
8438
8831
  (key, i) => html21`
8439
- ${i > 0 ? html21`<span part="label" class="separator" aria-hidden="true">+</span>` : nothing8}
8832
+ ${i > 0 ? html21`<span part="label" class="separator" aria-hidden="true">+</span>` : nothing9}
8440
8833
  <rel-kbd part="item" size=${this.size} variant=${this.variant}>${key}</rel-kbd>
8441
8834
  `
8442
8835
  )}
@@ -8536,7 +8929,7 @@ RelLayout = __decorateClass([
8536
8929
  ], RelLayout);
8537
8930
 
8538
8931
  // src/components/rel-menu/rel-menu.ts
8539
- import { LitElement as LitElement24, html as html24 } from "lit";
8932
+ import { LitElement as LitElement24, html as html24, nothing as nothing10 } from "lit";
8540
8933
  import { customElement as customElement24, property as property23, state as state9 } from "lit/decorators.js";
8541
8934
  import "@reliability-design/icons/rel-icon";
8542
8935
 
@@ -8885,12 +9278,16 @@ var RelMenu = class extends LitElement24 {
8885
9278
  this.type = "default";
8886
9279
  this.items = [];
8887
9280
  this.focusedIndex = 0;
9281
+ this.subFocusedIndex = -1;
8888
9282
  this._items = [];
9283
+ /** Stable id prefix for aria-activedescendant targets. */
9284
+ this.menuId = `rel-menu-${Math.random().toString(36).slice(2)}`;
8889
9285
  /** Index of a submenu locked open by a click (survives hover-out). -1 = none. */
8890
9286
  this.lockedIndex = -1;
8891
9287
  this.handleDocumentClick = (e) => {
8892
9288
  if (!e.composedPath().includes(this)) {
8893
9289
  this.lockedIndex = -1;
9290
+ this.subFocusedIndex = -1;
8894
9291
  this._items = this._items.map((i) => ({ ...i, open: false }));
8895
9292
  }
8896
9293
  };
@@ -8977,35 +9374,95 @@ var RelMenu = class extends LitElement24 {
8977
9374
  })
8978
9375
  );
8979
9376
  }
9377
+ /** Keyboard-open locks the submenu (no hover-out to close it) and moves
9378
+ * virtual focus onto its first entry. */
9379
+ openSubmenuAt(index) {
9380
+ this.lockedIndex = index;
9381
+ this.subFocusedIndex = 0;
9382
+ this._items = this._items.map((i, idx) => ({ ...i, open: idx === index }));
9383
+ }
9384
+ closeSubmenus() {
9385
+ this.lockedIndex = -1;
9386
+ this.subFocusedIndex = -1;
9387
+ this._items = this._items.map((i) => ({ ...i, open: false }));
9388
+ }
8980
9389
  onKeydown(ev) {
8981
9390
  const last = this._items.length - 1;
9391
+ const focusedItem = this._items[this.focusedIndex];
9392
+ if (this.subFocusedIndex >= 0 && this.type === "arrow" && focusedItem?.open && focusedItem.submenu?.length) {
9393
+ const subLast = focusedItem.submenu.length - 1;
9394
+ switch (ev.key) {
9395
+ case "ArrowDown":
9396
+ this.subFocusedIndex = Math.min(subLast, this.subFocusedIndex + 1);
9397
+ ev.preventDefault();
9398
+ return;
9399
+ case "ArrowUp":
9400
+ this.subFocusedIndex = Math.max(0, this.subFocusedIndex - 1);
9401
+ ev.preventDefault();
9402
+ return;
9403
+ case "Home":
9404
+ this.subFocusedIndex = 0;
9405
+ ev.preventDefault();
9406
+ return;
9407
+ case "End":
9408
+ this.subFocusedIndex = subLast;
9409
+ ev.preventDefault();
9410
+ return;
9411
+ case "ArrowLeft":
9412
+ case "Escape":
9413
+ this.closeSubmenus();
9414
+ ev.preventDefault();
9415
+ ev.stopPropagation();
9416
+ return;
9417
+ case "Enter":
9418
+ case " ":
9419
+ this.onSubClick(this.focusedIndex, this.subFocusedIndex);
9420
+ ev.preventDefault();
9421
+ return;
9422
+ default:
9423
+ return;
9424
+ }
9425
+ }
8982
9426
  if (ev.key === "ArrowDown") {
8983
9427
  this.focusedIndex = Math.min(last, this.focusedIndex + 1);
8984
9428
  ev.preventDefault();
8985
9429
  } else if (ev.key === "ArrowUp") {
8986
9430
  this.focusedIndex = Math.max(0, this.focusedIndex - 1);
8987
9431
  ev.preventDefault();
9432
+ } else if (ev.key === "Home") {
9433
+ this.focusedIndex = 0;
9434
+ ev.preventDefault();
9435
+ } else if (ev.key === "End") {
9436
+ this.focusedIndex = last;
9437
+ ev.preventDefault();
8988
9438
  } else if (ev.key === "ArrowRight") {
8989
9439
  const item = this._items[this.focusedIndex];
8990
- if (this.type === "arrow" && item?.submenu?.length) {
8991
- this.lockedIndex = this.focusedIndex;
8992
- this._items = this._items.map((i, idx) => ({
8993
- ...i,
8994
- open: idx === this.focusedIndex ? true : i.open
8995
- }));
9440
+ if (this.type === "arrow" && item?.submenu?.length && !item.disabled) {
9441
+ this.openSubmenuAt(this.focusedIndex);
9442
+ ev.preventDefault();
8996
9443
  }
8997
9444
  } else if (ev.key === "ArrowLeft" || ev.key === "Escape") {
8998
- this.lockedIndex = -1;
8999
- this._items = this._items.map((i) => ({ ...i, open: false }));
9445
+ const anyOpen = this._items.some((i) => i.open);
9446
+ if (anyOpen) {
9447
+ this.closeSubmenus();
9448
+ ev.preventDefault();
9449
+ if (ev.key === "Escape") ev.stopPropagation();
9450
+ }
9000
9451
  } else if (ev.key === "Enter" || ev.key === " ") {
9001
9452
  const item = this._items[this.focusedIndex];
9002
- this.onItemClick(item, this.focusedIndex);
9453
+ if (this.type === "arrow" && item?.submenu?.length && !item.disabled) {
9454
+ this.openSubmenuAt(this.focusedIndex);
9455
+ } else {
9456
+ this.onItemClick(item, this.focusedIndex);
9457
+ }
9003
9458
  ev.preventDefault();
9004
9459
  }
9005
9460
  }
9006
9461
  renderMenuItem(item, index) {
9007
- const isFocused = this.focusedIndex === index;
9462
+ const isFocused = this.focusedIndex === index && this.subFocusedIndex < 0;
9008
9463
  const hasSubmenu = this.type === "arrow" && !!item.submenu?.length;
9464
+ const role = this.type === "checkbox" ? "menuitemcheckbox" : this.type === "select-option" ? "menuitemradio" : "menuitem";
9465
+ const ariaChecked = this.type === "checkbox" ? String(!!item.checked) : this.type === "select-option" ? String(!!item.active) : nothing10;
9009
9466
  const control = this.type === "checkbox" ? html24`<rel-checkbox
9010
9467
  class="menu-control"
9011
9468
  label="${item.label}"
@@ -9023,8 +9480,13 @@ var RelMenu = class extends LitElement24 {
9023
9480
  `;
9024
9481
  return html24`
9025
9482
  <div
9483
+ id="${this.menuId}-item-${index}"
9026
9484
  class="rel-menu-item ${item.active ? "active" : ""} ${item.disabled ? "disabled" : ""}"
9027
- role="menuitem"
9485
+ role="${role}"
9486
+ aria-checked="${ariaChecked}"
9487
+ aria-disabled="${item.disabled ? "true" : nothing10}"
9488
+ aria-haspopup="${hasSubmenu ? "menu" : nothing10}"
9489
+ aria-expanded="${hasSubmenu ? String(!!item.open) : nothing10}"
9028
9490
  ?data-focused="${isFocused}"
9029
9491
  @mouseenter="${() => this.onItemEnter(item, index)}"
9030
9492
  @mouseleave="${() => this.onItemLeave(item, index)}"
@@ -9033,12 +9495,16 @@ var RelMenu = class extends LitElement24 {
9033
9495
  ${hasSubmenu ? html24`
9034
9496
  <div
9035
9497
  part="panel" class="rel-submenu ${item.open ? "visible" : ""}"
9498
+ role="menu"
9036
9499
  @click="${(e) => e.stopPropagation()}">
9037
9500
  ${item.submenu.map(
9038
9501
  (sub, subIndex) => html24`
9039
9502
  <div
9040
- class="rel-menu-item ${sub.active ? "active" : ""}"
9503
+ id="${this.menuId}-item-${index}-sub-${subIndex}"
9504
+ class="rel-menu-item ${sub.active ? "active" : ""} ${sub.disabled ? "disabled" : ""}"
9041
9505
  role="menuitem"
9506
+ aria-disabled="${sub.disabled ? "true" : nothing10}"
9507
+ ?data-focused="${this.focusedIndex === index && this.subFocusedIndex === subIndex}"
9042
9508
  @click="${(e) => this.onSubClick(index, subIndex, e)}">
9043
9509
  <span class="menu-label">${sub.label}</span>
9044
9510
  </div>
@@ -9050,12 +9516,14 @@ var RelMenu = class extends LitElement24 {
9050
9516
  `;
9051
9517
  }
9052
9518
  render() {
9519
+ const activeDescendant = this._items.length === 0 ? nothing10 : this.subFocusedIndex >= 0 ? `${this.menuId}-item-${this.focusedIndex}-sub-${this.subFocusedIndex}` : `${this.menuId}-item-${this.focusedIndex}`;
9053
9520
  return html24`
9054
9521
  <style>${RelMenu._css}</style>
9055
9522
  <div
9056
9523
  part="list" class="rel-menu ${this.type === "fixed" || this.type === "fit" ? this.type : ""}"
9057
9524
  role="menu"
9058
9525
  tabindex="0"
9526
+ aria-activedescendant="${activeDescendant}"
9059
9527
  @keydown="${this.onKeydown}"
9060
9528
  @click="${(e) => e.stopPropagation()}">
9061
9529
  ${this._items.map((item, index) => this.renderMenuItem(item, index))}
@@ -9145,7 +9613,10 @@ RelMenu._css = `
9145
9613
  cursor: not-allowed;
9146
9614
  }
9147
9615
 
9148
- .rel-menu-item[data-focused="true"] {
9616
+ /* [data-focused] (presence, not ="true"): the ?data-focused boolean
9617
+ binding renders the attribute with an EMPTY value, so a ="true"
9618
+ selector never matches. */
9619
+ .rel-menu-item[data-focused] {
9149
9620
  outline: 2px solid var(--rel-border-focus);
9150
9621
  outline-offset: -2px;
9151
9622
  }
@@ -9236,6 +9707,9 @@ __decorateClass([
9236
9707
  __decorateClass([
9237
9708
  state9()
9238
9709
  ], RelMenu.prototype, "focusedIndex", 2);
9710
+ __decorateClass([
9711
+ state9()
9712
+ ], RelMenu.prototype, "subFocusedIndex", 2);
9239
9713
  __decorateClass([
9240
9714
  state9()
9241
9715
  ], RelMenu.prototype, "_items", 2);
@@ -9244,18 +9718,161 @@ RelMenu = __decorateClass([
9244
9718
  ], RelMenu);
9245
9719
 
9246
9720
  // src/components/rel-menubar/rel-menubar.ts
9247
- import { LitElement as LitElement25, html as html25 } from "lit";
9248
- import { customElement as customElement25, state as state10 } from "lit/decorators.js";
9721
+ import { LitElement as LitElement25, html as html25, nothing as nothing11 } from "lit";
9722
+ import { customElement as customElement25, property as property24, state as state10 } from "lit/decorators.js";
9723
+
9724
+ // src/utils/shortcuts.ts
9725
+ function isApplePlatform() {
9726
+ if (typeof navigator === "undefined") return false;
9727
+ return /Mac|iPhone|iPad|iPod/i.test(navigator.platform || navigator.userAgent);
9728
+ }
9729
+ var KEY_ALIASES = {
9730
+ esc: "escape",
9731
+ space: " ",
9732
+ plus: "+",
9733
+ return: "enter",
9734
+ up: "arrowup",
9735
+ down: "arrowdown",
9736
+ left: "arrowleft",
9737
+ right: "arrowright"
9738
+ };
9739
+ function parseShortcut(shortcut) {
9740
+ const parsed = {
9741
+ key: "",
9742
+ ctrl: false,
9743
+ meta: false,
9744
+ alt: false,
9745
+ shift: false
9746
+ };
9747
+ const tokens = shortcut.split("+").map((t) => t.trim().toLowerCase()).filter(Boolean);
9748
+ if (shortcut.endsWith("+") && !shortcut.endsWith("++")) tokens.push("+");
9749
+ for (const token of tokens) {
9750
+ switch (token) {
9751
+ case "mod":
9752
+ if (isApplePlatform()) parsed.meta = true;
9753
+ else parsed.ctrl = true;
9754
+ break;
9755
+ case "ctrl":
9756
+ case "control":
9757
+ parsed.ctrl = true;
9758
+ break;
9759
+ case "meta":
9760
+ case "cmd":
9761
+ case "command":
9762
+ case "win":
9763
+ parsed.meta = true;
9764
+ break;
9765
+ case "alt":
9766
+ case "option":
9767
+ parsed.alt = true;
9768
+ break;
9769
+ case "shift":
9770
+ parsed.shift = true;
9771
+ break;
9772
+ default:
9773
+ parsed.key = KEY_ALIASES[token] ?? token;
9774
+ }
9775
+ }
9776
+ return parsed;
9777
+ }
9778
+ function matchesShortcut(e, shortcut) {
9779
+ const parsed = parseShortcut(shortcut);
9780
+ if (!parsed.key) return false;
9781
+ return e.key.toLowerCase() === parsed.key && e.ctrlKey === parsed.ctrl && e.metaKey === parsed.meta && e.altKey === parsed.alt && e.shiftKey === parsed.shift;
9782
+ }
9783
+ function isEditableTarget(e) {
9784
+ const target = e.composedPath()[0];
9785
+ if (!(target instanceof HTMLElement)) return false;
9786
+ if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement) {
9787
+ return true;
9788
+ }
9789
+ return target.isContentEditable;
9790
+ }
9791
+ function bindShortcut(shortcut, handler, options = {}) {
9792
+ const target = options.target ?? document;
9793
+ const listener = (event) => {
9794
+ const e = event;
9795
+ if (!matchesShortcut(e, shortcut)) return;
9796
+ if (!options.allowInEditable && isEditableTarget(e)) return;
9797
+ if (options.preventDefault !== false) e.preventDefault();
9798
+ handler(e);
9799
+ };
9800
+ target.addEventListener("keydown", listener);
9801
+ return () => target.removeEventListener("keydown", listener);
9802
+ }
9803
+ var APPLE_LABELS = {
9804
+ mod: "\u2318",
9805
+ meta: "\u2318",
9806
+ cmd: "\u2318",
9807
+ command: "\u2318",
9808
+ ctrl: "\u2303",
9809
+ control: "\u2303",
9810
+ alt: "\u2325",
9811
+ option: "\u2325",
9812
+ shift: "\u21E7"
9813
+ };
9814
+ var GENERIC_LABELS = {
9815
+ mod: "Ctrl",
9816
+ meta: "Win",
9817
+ cmd: "Win",
9818
+ command: "Win",
9819
+ ctrl: "Ctrl",
9820
+ control: "Ctrl",
9821
+ alt: "Alt",
9822
+ option: "Alt",
9823
+ shift: "Shift"
9824
+ };
9825
+ var KEY_LABELS = {
9826
+ arrowup: "\u2191",
9827
+ arrowdown: "\u2193",
9828
+ arrowleft: "\u2190",
9829
+ arrowright: "\u2192",
9830
+ escape: "Esc",
9831
+ " ": "Space"
9832
+ };
9833
+ function formatShortcutParts(shortcut) {
9834
+ const labels = isApplePlatform() ? APPLE_LABELS : GENERIC_LABELS;
9835
+ return shortcut.split("+").map((t) => t.trim()).filter(Boolean).map((token) => {
9836
+ const lower = token.toLowerCase();
9837
+ if (labels[lower]) return labels[lower];
9838
+ const key = KEY_ALIASES[lower] ?? lower;
9839
+ if (KEY_LABELS[key]) return KEY_LABELS[key];
9840
+ return key.length === 1 ? key.toUpperCase() : key[0].toUpperCase() + key.slice(1);
9841
+ });
9842
+ }
9843
+
9844
+ // src/components/rel-menubar/rel-menubar.ts
9249
9845
  import "@reliability-design/icons/rel-icon";
9250
9846
  var RelMenubar = class extends LitElement25 {
9251
9847
  constructor() {
9252
9848
  super(...arguments);
9849
+ this.bindShortcuts = false;
9253
9850
  this.menus = [];
9254
9851
  this.openMenuIndex = -1;
9255
9852
  this.focusedTriggerIndex = 0;
9256
9853
  this.focusedItemIndex = -1;
9854
+ this.focusedSubItemIndex = -1;
9257
9855
  this.openSubmenuElement = null;
9258
9856
  this.hoverSwitchEnabled = false;
9857
+ /** Stable id prefix for aria-activedescendant targets (light DOM, so ids
9858
+ * must be unique per menubar instance on the page). */
9859
+ this.menubarId = `rel-menubar-${Math.random().toString(36).slice(2)}`;
9860
+ this.handleShortcutKeyDown = (e) => {
9861
+ if (!this.bindShortcuts || e.defaultPrevented) return;
9862
+ if (isEditableTarget(e)) return;
9863
+ for (const { menu } of this.menus) {
9864
+ for (const item of this.getFocusableItems(menu)) {
9865
+ const shortcut = item.getAttribute("data-shortcut");
9866
+ if (!shortcut) continue;
9867
+ if (item.disabled) continue;
9868
+ if (matchesShortcut(e, shortcut)) {
9869
+ e.preventDefault();
9870
+ this.handleItemClick(item);
9871
+ return;
9872
+ }
9873
+ }
9874
+ }
9875
+ };
9259
9876
  this.handleOutsideClick = (e) => {
9260
9877
  if (!e.composedPath().includes(this)) {
9261
9878
  this.closeAllMenus();
@@ -9269,6 +9886,7 @@ var RelMenubar = class extends LitElement25 {
9269
9886
  super.connectedCallback();
9270
9887
  this.discoverMenus();
9271
9888
  document.addEventListener("click", this.handleOutsideClick);
9889
+ document.addEventListener("keydown", this.handleShortcutKeyDown);
9272
9890
  this._onScroll = () => {
9273
9891
  this._repositionOpenMenu();
9274
9892
  this._repositionOpenSubmenu();
@@ -9278,6 +9896,7 @@ var RelMenubar = class extends LitElement25 {
9278
9896
  disconnectedCallback() {
9279
9897
  super.disconnectedCallback();
9280
9898
  document.removeEventListener("click", this.handleOutsideClick);
9899
+ document.removeEventListener("keydown", this.handleShortcutKeyDown);
9281
9900
  if (this._onScroll) {
9282
9901
  window.removeEventListener("scroll", this._onScroll, { capture: true });
9283
9902
  }
@@ -9311,12 +9930,26 @@ var RelMenubar = class extends LitElement25 {
9311
9930
  closeAllMenus() {
9312
9931
  this.openMenuIndex = -1;
9313
9932
  this.openSubmenuElement = null;
9933
+ this.focusedItemIndex = -1;
9934
+ this.focusedSubItemIndex = -1;
9314
9935
  this.hoverSwitchEnabled = false;
9315
9936
  this.requestUpdate();
9316
9937
  }
9938
+ /** Close everything and put DOM focus back on the trigger that owned the
9939
+ * open menu. (Capturing the index BEFORE closing — closeAllMenus resets
9940
+ * openMenuIndex to -1, which used to drop focus to <body>.) */
9941
+ closeAllMenusAndRefocusTrigger() {
9942
+ const idx = this.openMenuIndex;
9943
+ this.closeAllMenus();
9944
+ if (idx !== -1) {
9945
+ this.focusedTriggerIndex = idx;
9946
+ this.focusTrigger(idx);
9947
+ }
9948
+ }
9317
9949
  openMenu(index, triggerElement) {
9318
9950
  this.openMenuIndex = index;
9319
9951
  this.focusedItemIndex = -1;
9952
+ this.focusedSubItemIndex = -1;
9320
9953
  this.openSubmenuElement = null;
9321
9954
  this.requestUpdate();
9322
9955
  this.updateComplete.then(() => {
@@ -9358,27 +9991,20 @@ var RelMenubar = class extends LitElement25 {
9358
9991
  event.preventDefault();
9359
9992
  this.focusedTriggerIndex = Math.max(0, this.focusedTriggerIndex - 1);
9360
9993
  this.focusTrigger(this.focusedTriggerIndex);
9361
- } else if (key === "Enter" || key === " ") {
9994
+ } else if (key === "Enter" || key === " " || key === "ArrowDown") {
9362
9995
  event.preventDefault();
9363
9996
  const trigger = this.querySelector(
9364
9997
  `.menubar-trigger[data-index="${this.focusedTriggerIndex}"]`
9365
9998
  );
9366
9999
  if (trigger) {
9367
- this.openMenu(this.focusedTriggerIndex, trigger);
9368
- this.updateComplete.then(() => {
9369
- const focusTarget = this.querySelector(
9370
- "[autofocus], [role='menuitem']"
9371
- );
9372
- if (focusTarget) {
9373
- focusTarget.focus();
9374
- } else {
9375
- this.focusMenuItem(0);
9376
- }
9377
- });
10000
+ if (this.openMenuIndex !== this.focusedTriggerIndex) {
10001
+ this.openMenu(this.focusedTriggerIndex, trigger);
10002
+ }
10003
+ this.updateComplete.then(() => this.focusMenuItem(0));
9378
10004
  }
9379
- } else if (key === "ArrowDown" && this.openMenuIndex !== -1) {
10005
+ } else if (key === "Escape" && this.openMenuIndex !== -1) {
9380
10006
  event.preventDefault();
9381
- this.focusMenuItem(0);
10007
+ this.closeAllMenusAndRefocusTrigger();
9382
10008
  }
9383
10009
  }
9384
10010
  focusTrigger(index) {
@@ -9391,6 +10017,36 @@ var RelMenubar = class extends LitElement25 {
9391
10017
  const { key } = event;
9392
10018
  const menuContent = this.menus[this.openMenuIndex]?.menu;
9393
10019
  if (!menuContent) return;
10020
+ if (this.openSubmenuElement) {
10021
+ const subItems = this.getSubmenuItems(this.openSubmenuElement);
10022
+ if (key === "ArrowDown") {
10023
+ event.preventDefault();
10024
+ this.focusedSubItemIndex = Math.min(
10025
+ subItems.length - 1,
10026
+ this.focusedSubItemIndex + 1
10027
+ );
10028
+ } else if (key === "ArrowUp") {
10029
+ event.preventDefault();
10030
+ this.focusedSubItemIndex = Math.max(0, this.focusedSubItemIndex - 1);
10031
+ } else if (key === "Home") {
10032
+ event.preventDefault();
10033
+ this.focusedSubItemIndex = 0;
10034
+ } else if (key === "End") {
10035
+ event.preventDefault();
10036
+ this.focusedSubItemIndex = subItems.length - 1;
10037
+ } else if (key === "ArrowLeft" || key === "Escape") {
10038
+ event.preventDefault();
10039
+ event.stopPropagation();
10040
+ this.openSubmenuElement = null;
10041
+ this.focusedSubItemIndex = -1;
10042
+ } else if (key === "Enter" || key === " ") {
10043
+ event.preventDefault();
10044
+ const subItem = subItems[this.focusedSubItemIndex];
10045
+ if (subItem) this.handleSubmenuItemClick(subItem);
10046
+ }
10047
+ this.requestUpdate();
10048
+ return;
10049
+ }
9394
10050
  const items = this.getFocusableItems(menuContent);
9395
10051
  if (key === "ArrowDown") {
9396
10052
  event.preventDefault();
@@ -9400,30 +10056,56 @@ var RelMenubar = class extends LitElement25 {
9400
10056
  event.preventDefault();
9401
10057
  this.focusedItemIndex = Math.max(0, this.focusedItemIndex - 1);
9402
10058
  this.requestUpdate();
10059
+ } else if (key === "Home") {
10060
+ event.preventDefault();
10061
+ this.focusedItemIndex = 0;
10062
+ this.requestUpdate();
10063
+ } else if (key === "End") {
10064
+ event.preventDefault();
10065
+ this.focusedItemIndex = items.length - 1;
10066
+ this.requestUpdate();
9403
10067
  } else if (key === "ArrowRight") {
9404
10068
  event.preventDefault();
9405
10069
  const currentItem = items[this.focusedItemIndex];
9406
10070
  if (currentItem?.hasAttribute("data-submenu")) {
9407
- this.openSubmenu(currentItem);
10071
+ const panel = this.querySelector(
10072
+ `.menubar-panel[data-menu-index="${this.openMenuIndex}"]`
10073
+ );
10074
+ const renderedTrigger = panel?.querySelector(
10075
+ `[data-focus-index="${this.focusedItemIndex}"]`
10076
+ );
10077
+ this.focusedSubItemIndex = 0;
10078
+ this.openSubmenu(currentItem, renderedTrigger ?? void 0);
9408
10079
  }
9409
10080
  } else if (key === "ArrowLeft") {
9410
10081
  event.preventDefault();
9411
- if (this.openSubmenuElement) {
9412
- this.openSubmenuElement = null;
9413
- this.requestUpdate();
9414
- }
9415
10082
  } else if (key === "Escape") {
9416
10083
  event.preventDefault();
9417
- this.closeAllMenus();
9418
- this.focusTrigger(this.openMenuIndex);
10084
+ this.closeAllMenusAndRefocusTrigger();
9419
10085
  } else if (key === "Enter" || key === " ") {
9420
10086
  event.preventDefault();
9421
10087
  const currentItem = items[this.focusedItemIndex];
9422
10088
  if (currentItem) {
9423
- this.handleItemClick(currentItem);
10089
+ if (currentItem.hasAttribute("data-submenu")) {
10090
+ const panel = this.querySelector(
10091
+ `.menubar-panel[data-menu-index="${this.openMenuIndex}"]`
10092
+ );
10093
+ const renderedTrigger = panel?.querySelector(
10094
+ `[data-focus-index="${this.focusedItemIndex}"]`
10095
+ );
10096
+ this.focusedSubItemIndex = 0;
10097
+ this.openSubmenu(currentItem, renderedTrigger ?? void 0);
10098
+ } else {
10099
+ this.handleItemClick(currentItem);
10100
+ }
9424
10101
  }
9425
10102
  }
9426
10103
  }
10104
+ getSubmenuItems(submenuElement) {
10105
+ return Array.from(submenuElement.children).filter(
10106
+ (el) => el.hasAttribute("data-item")
10107
+ );
10108
+ }
9427
10109
  getFocusableItems(menuContent) {
9428
10110
  return Array.from(menuContent.children).filter(
9429
10111
  (el) => el.hasAttribute("data-item") || el.hasAttribute("data-checkbox") || el.hasAttribute("data-radio") || el.hasAttribute("data-submenu")
@@ -9460,27 +10142,41 @@ var RelMenubar = class extends LitElement25 {
9460
10142
  } else if (item.hasAttribute("data-submenu")) {
9461
10143
  this.openSubmenu(item);
9462
10144
  } else {
9463
- this.closeAllMenus();
10145
+ this.dispatchSelectEvent(item);
10146
+ this.closeAllMenusAndRefocusTrigger();
9464
10147
  }
9465
10148
  }
9466
- openSubmenu(submenuTrigger, renderedTrigger, submenuIndex) {
9467
- this.openSubmenuElement = submenuTrigger;
9468
- this.requestUpdate();
9469
- this.updateComplete.then(() => {
9470
- const submenuId = `submenu-${submenuIndex ?? 0}`;
9471
- const submenuPanel = this.querySelector(
9472
- `.submenu-panel[data-submenu-id="${submenuId}"]`
9473
- );
9474
- if (submenuPanel) {
9475
- const positionTarget = renderedTrigger ?? submenuTrigger;
9476
- const rect = positionTarget.getBoundingClientRect();
9477
- submenuPanel.style.top = `${rect.top}px`;
9478
- submenuPanel.style.left = `${rect.right + 4}px`;
10149
+ dispatchSelectEvent(item) {
10150
+ this.dispatchEvent(
10151
+ new CustomEvent("rel-menubar-select", {
10152
+ detail: {
10153
+ label: item.textContent?.trim() ?? "",
10154
+ value: item.getAttribute("value") ?? void 0,
10155
+ shortcut: item.getAttribute("data-shortcut") ?? void 0
10156
+ },
10157
+ bubbles: true,
10158
+ composed: true
10159
+ })
10160
+ );
10161
+ }
10162
+ openSubmenu(submenuTrigger, renderedTrigger) {
10163
+ this.openSubmenuElement = submenuTrigger;
10164
+ this.requestUpdate();
10165
+ this.updateComplete.then(() => {
10166
+ const submenuPanel = this.querySelector(".submenu-panel.open");
10167
+ if (submenuPanel) {
10168
+ const positionTarget = renderedTrigger ?? submenuPanel.previousElementSibling;
10169
+ const rect = positionTarget?.getBoundingClientRect();
10170
+ if (rect) {
10171
+ submenuPanel.style.top = `${rect.top}px`;
10172
+ submenuPanel.style.left = `${rect.right + 4}px`;
10173
+ }
9479
10174
  }
9480
10175
  });
9481
10176
  }
9482
- handleSubmenuItemClick(_item) {
9483
- this.closeAllMenus();
10177
+ handleSubmenuItemClick(item) {
10178
+ this.dispatchSelectEvent(item);
10179
+ this.closeAllMenusAndRefocusTrigger();
9484
10180
  }
9485
10181
  dispatchChangeEvent(type, labelOrName, value) {
9486
10182
  const detail = type === "checkbox" ? { type, label: labelOrName, name: "", checked: value } : { type, label: "", name: labelOrName, value };
@@ -9492,16 +10188,21 @@ var RelMenubar = class extends LitElement25 {
9492
10188
  })
9493
10189
  );
9494
10190
  }
9495
- renderMenuItem(item, index) {
9496
- const isFocused = index === this.focusedItemIndex;
10191
+ renderMenuItem(item, focusIndex, menuIndex) {
10192
+ const isFocused = focusIndex >= 0 && focusIndex === this.focusedItemIndex;
10193
+ const itemId = focusIndex >= 0 ? `${this.menubarId}-m${menuIndex}-i${focusIndex}` : nothing11;
9497
10194
  if (item.hasAttribute("data-item")) {
9498
10195
  const button = item;
9499
10196
  const disabled = button.disabled;
9500
10197
  const shortcut = button.getAttribute("data-shortcut") || "";
9501
10198
  return html25`
9502
10199
  <div
10200
+ id="${itemId}"
9503
10201
  class="menu-item ${isFocused ? "focused" : ""}"
10202
+ role="menuitem"
10203
+ data-focus-index="${focusIndex}"
9504
10204
  data-disabled="${disabled}"
10205
+ aria-disabled="${disabled ? "true" : nothing11}"
9505
10206
  @click="${() => !disabled && this.handleItemClick(item)}"
9506
10207
  >
9507
10208
  <span>${button.textContent}</span>
@@ -9510,7 +10211,7 @@ var RelMenubar = class extends LitElement25 {
9510
10211
  `;
9511
10212
  }
9512
10213
  if (item.hasAttribute("data-separator")) {
9513
- return html25`<div class="menu-separator"></div>`;
10214
+ return html25`<div class="menu-separator" role="separator"></div>`;
9514
10215
  }
9515
10216
  if (item.hasAttribute("data-checkbox")) {
9516
10217
  const label = item;
@@ -9518,6 +10219,8 @@ var RelMenubar = class extends LitElement25 {
9518
10219
  const labelText = Array.from(label.childNodes).filter((n) => n.nodeType === Node.TEXT_NODE).map((n) => n.textContent?.trim()).filter(Boolean).join(" ") || label.getAttribute("label") || "";
9519
10220
  return html25`
9520
10221
  <rel-checkbox
10222
+ id="${itemId}"
10223
+ data-focus-index="${focusIndex}"
9521
10224
  label=${labelText}
9522
10225
  .status=${checkbox?.checked ? "checked" : "unchecked"}
9523
10226
  @rel-change=${(e) => {
@@ -9529,17 +10232,21 @@ var RelMenubar = class extends LitElement25 {
9529
10232
  }
9530
10233
  if (item.hasAttribute("data-submenu")) {
9531
10234
  const label = item.getAttribute("label") || item.textContent?.trim() || "";
9532
- const submenuId = `submenu-${index}`;
9533
10235
  return html25`
9534
10236
  <div
10237
+ id="${itemId}"
9535
10238
  class="menu-item menu-submenu-trigger ${isFocused ? "focused" : ""}"
9536
- @click="${(e) => this.openSubmenu(item, e.currentTarget, index)}"
9537
- @mouseenter="${(e) => this.openSubmenu(item, e.currentTarget, index)}"
10239
+ role="menuitem"
10240
+ data-focus-index="${focusIndex}"
10241
+ aria-haspopup="menu"
10242
+ aria-expanded="${this.openSubmenuElement === item}"
10243
+ @click="${(e) => this.openSubmenu(item, e.currentTarget)}"
10244
+ @mouseenter="${(e) => this.openSubmenu(item, e.currentTarget)}"
9538
10245
  >
9539
10246
  <span>${label}</span>
9540
10247
  <rel-icon name="chevron-right"></rel-icon>
9541
10248
  </div>
9542
- ${this.renderSubmenu(item, submenuId)}
10249
+ ${this.renderSubmenu(item)}
9543
10250
  `;
9544
10251
  }
9545
10252
  if (item.hasAttribute("data-radio-group")) {
@@ -9564,24 +10271,23 @@ var RelMenubar = class extends LitElement25 {
9564
10271
  }
9565
10272
  return null;
9566
10273
  }
9567
- renderSubmenu(submenuElement, submenuId) {
10274
+ renderSubmenu(submenuElement) {
9568
10275
  const isOpen = this.openSubmenuElement === submenuElement;
9569
- const submenuItems = Array.from(submenuElement.children);
10276
+ const submenuItems = this.getSubmenuItems(submenuElement);
9570
10277
  return html25`
9571
- <div class="submenu-panel ${isOpen ? "open" : ""}" data-submenu-id="${submenuId}">
9572
- ${submenuItems.map((subItem) => {
9573
- if (subItem.hasAttribute("data-item")) {
9574
- const button = subItem;
9575
- return html25`
9576
- <div
9577
- class="menu-item"
9578
- @click="${() => this.handleSubmenuItemClick(subItem)}"
9579
- >
9580
- <span>${button.textContent}</span>
9581
- </div>
9582
- `;
9583
- }
9584
- return null;
10278
+ <div class="submenu-panel ${isOpen ? "open" : ""}" role="menu">
10279
+ ${submenuItems.map((subItem, subIdx) => {
10280
+ const button = subItem;
10281
+ return html25`
10282
+ <div
10283
+ id="${isOpen ? `${this.menubarId}-sub-${subIdx}` : nothing11}"
10284
+ class="menu-item ${isOpen && subIdx === this.focusedSubItemIndex ? "focused" : ""}"
10285
+ role="menuitem"
10286
+ @click="${() => this.handleSubmenuItemClick(subItem)}"
10287
+ >
10288
+ <span>${button.textContent}</span>
10289
+ </div>
10290
+ `;
9585
10291
  })}
9586
10292
  </div>
9587
10293
  `;
@@ -9589,28 +10295,40 @@ var RelMenubar = class extends LitElement25 {
9589
10295
  renderMenuPanel(menuState, index) {
9590
10296
  const isOpen = index === this.openMenuIndex;
9591
10297
  const items = Array.from(menuState.menu.children);
10298
+ const focusables = this.getFocusableItems(menuState.menu);
10299
+ const activeDescendant = !isOpen ? nothing11 : this.focusedSubItemIndex >= 0 ? `${this.menubarId}-sub-${this.focusedSubItemIndex}` : this.focusedItemIndex >= 0 ? `${this.menubarId}-m${index}-i${this.focusedItemIndex}` : nothing11;
9592
10300
  return html25`
9593
10301
  <div
9594
10302
  class="menubar-panel ${isOpen ? "open" : ""}"
9595
10303
  data-menu-index="${index}"
9596
10304
  tabindex="-1"
10305
+ role="menu"
10306
+ aria-activedescendant="${activeDescendant}"
9597
10307
  @keydown="${this.handlePanelKeyDown}"
9598
10308
  >
9599
- ${items.map((item, idx) => this.renderMenuItem(item, idx))}
10309
+ ${items.map(
10310
+ (item) => this.renderMenuItem(item, focusables.indexOf(item), index)
10311
+ )}
9600
10312
  </div>
9601
10313
  `;
9602
10314
  }
9603
10315
  render() {
9604
10316
  return html25`
9605
10317
  <style>${RelMenubar._css}</style>
9606
- <div class="menubar-container">
10318
+ <div class="menubar-container" role="menubar">
9607
10319
  ${this.menus.map(
9608
10320
  (menuState, index) => html25`
9609
10321
  <button
9610
10322
  class="menubar-trigger ${index === this.openMenuIndex ? "active" : ""}"
9611
10323
  data-index="${index}"
10324
+ role="menuitem"
10325
+ aria-haspopup="menu"
10326
+ aria-expanded="${index === this.openMenuIndex}"
9612
10327
  @click="${(e) => this.handleTriggerClick(index, e)}"
9613
10328
  @mouseenter="${(e) => this.handleTriggerMouseEnter(index, e)}"
10329
+ @focus="${() => {
10330
+ this.focusedTriggerIndex = index;
10331
+ }}"
9614
10332
  @keydown="${this.handleTriggerKeyDown}"
9615
10333
  >
9616
10334
  ${menuState.menu.label}
@@ -9781,6 +10499,9 @@ RelMenubar._css = `
9781
10499
  cursor: pointer;
9782
10500
  }
9783
10501
  `;
10502
+ __decorateClass([
10503
+ property24({ type: Boolean, attribute: "bind-shortcuts" })
10504
+ ], RelMenubar.prototype, "bindShortcuts", 2);
9784
10505
  __decorateClass([
9785
10506
  state10()
9786
10507
  ], RelMenubar.prototype, "menus", 2);
@@ -9793,6 +10514,9 @@ __decorateClass([
9793
10514
  __decorateClass([
9794
10515
  state10()
9795
10516
  ], RelMenubar.prototype, "focusedItemIndex", 2);
10517
+ __decorateClass([
10518
+ state10()
10519
+ ], RelMenubar.prototype, "focusedSubItemIndex", 2);
9796
10520
  __decorateClass([
9797
10521
  state10()
9798
10522
  ], RelMenubar.prototype, "openSubmenuElement", 2);
@@ -9802,7 +10526,7 @@ RelMenubar = __decorateClass([
9802
10526
 
9803
10527
  // src/components/rel-menubar/rel-menubar-menu.ts
9804
10528
  import { LitElement as LitElement26, html as html26 } from "lit";
9805
- import { customElement as customElement26, property as property24 } from "lit/decorators.js";
10529
+ import { customElement as customElement26, property as property25 } from "lit/decorators.js";
9806
10530
  import "./rel-menubar-menu-BEEQDAXW.css";
9807
10531
  var RelMenubarMenu = class extends LitElement26 {
9808
10532
  constructor() {
@@ -9818,7 +10542,7 @@ var RelMenubarMenu = class extends LitElement26 {
9818
10542
  }
9819
10543
  };
9820
10544
  __decorateClass([
9821
- property24({ type: String })
10545
+ property25({ type: String })
9822
10546
  ], RelMenubarMenu.prototype, "label", 2);
9823
10547
  RelMenubarMenu = __decorateClass([
9824
10548
  customElement26("rel-menubar-menu")
@@ -9826,7 +10550,7 @@ RelMenubarMenu = __decorateClass([
9826
10550
 
9827
10551
  // src/components/rel-navbar/rel-navbar.ts
9828
10552
  import { LitElement as LitElement27, html as html27, css as css24 } from "lit";
9829
- import { customElement as customElement27, property as property25 } from "lit/decorators.js";
10553
+ import { customElement as customElement27, property as property26 } from "lit/decorators.js";
9830
10554
  var RelNavbar = class extends LitElement27 {
9831
10555
  constructor() {
9832
10556
  super();
@@ -9917,10 +10641,10 @@ RelNavbar.styles = css24`
9917
10641
  }
9918
10642
  `;
9919
10643
  __decorateClass([
9920
- property25({ type: Boolean, reflect: true })
10644
+ property26({ type: Boolean, reflect: true })
9921
10645
  ], RelNavbar.prototype, "sticky", 2);
9922
10646
  __decorateClass([
9923
- property25({ type: String })
10647
+ property26({ type: String })
9924
10648
  ], RelNavbar.prototype, "device", 2);
9925
10649
  RelNavbar = __decorateClass([
9926
10650
  customElement27("rel-navbar")
@@ -9928,12 +10652,12 @@ RelNavbar = __decorateClass([
9928
10652
 
9929
10653
  // src/components/rel-topbar/rel-topbar.ts
9930
10654
  import { LitElement as LitElement34, html as html34, css as css31 } from "lit";
9931
- import { customElement as customElement34, property as property28, state as state11 } from "lit/decorators.js";
10655
+ import { customElement as customElement34, property as property29, state as state11 } from "lit/decorators.js";
9932
10656
  import "@reliability-design/icons/rel-icon";
9933
10657
 
9934
10658
  // src/components/rel-topbar/rel-topbar-brand.ts
9935
10659
  import { LitElement as LitElement28, html as html28, css as css25 } from "lit";
9936
- import { customElement as customElement28, property as property26 } from "lit/decorators.js";
10660
+ import { customElement as customElement28, property as property27 } from "lit/decorators.js";
9937
10661
  var RelTopbarBrand = class extends LitElement28 {
9938
10662
  constructor() {
9939
10663
  super(...arguments);
@@ -9974,13 +10698,13 @@ RelTopbarBrand.styles = css25`
9974
10698
  }
9975
10699
  `;
9976
10700
  __decorateClass([
9977
- property26({ type: String })
10701
+ property27({ type: String })
9978
10702
  ], RelTopbarBrand.prototype, "src", 2);
9979
10703
  __decorateClass([
9980
- property26({ type: String })
10704
+ property27({ type: String })
9981
10705
  ], RelTopbarBrand.prototype, "href", 2);
9982
10706
  __decorateClass([
9983
- property26({ type: String })
10707
+ property27({ type: String })
9984
10708
  ], RelTopbarBrand.prototype, "label", 2);
9985
10709
  RelTopbarBrand = __decorateClass([
9986
10710
  customElement28("rel-topbar-brand")
@@ -10068,7 +10792,7 @@ RelTopbarDropdown = __decorateClass([
10068
10792
 
10069
10793
  // src/components/rel-topbar/rel-topbar-dropdown-item.ts
10070
10794
  import { LitElement as LitElement33, html as html33, css as css30 } from "lit";
10071
- import { customElement as customElement33, property as property27 } from "lit/decorators.js";
10795
+ import { customElement as customElement33, property as property28 } from "lit/decorators.js";
10072
10796
  var RelTopbarDropdownItem = class extends LitElement33 {
10073
10797
  constructor() {
10074
10798
  super(...arguments);
@@ -10127,13 +10851,13 @@ RelTopbarDropdownItem.styles = css30`
10127
10851
 
10128
10852
  `;
10129
10853
  __decorateClass([
10130
- property27({ type: String })
10854
+ property28({ type: String })
10131
10855
  ], RelTopbarDropdownItem.prototype, "label", 2);
10132
10856
  __decorateClass([
10133
- property27({ type: String })
10857
+ property28({ type: String })
10134
10858
  ], RelTopbarDropdownItem.prototype, "href", 2);
10135
10859
  __decorateClass([
10136
- property27({ type: Boolean, reflect: true })
10860
+ property28({ type: Boolean, reflect: true })
10137
10861
  ], RelTopbarDropdownItem.prototype, "active", 2);
10138
10862
  RelTopbarDropdownItem = __decorateClass([
10139
10863
  customElement33("rel-topbar-dropdown-item")
@@ -10461,7 +11185,6 @@ RelTopbar.styles = css31`
10461
11185
  color: var(--rel-topbar-item-color);
10462
11186
 
10463
11187
 
10464
-
10465
11188
  text-decoration: none;
10466
11189
  font-family: var(--rel-body-md-medium-font-family);
10467
11190
  font-weight: var(--rel-body-md-medium-font-weight);
@@ -10516,22 +11239,22 @@ RelTopbar.styles = css31`
10516
11239
  }
10517
11240
  `;
10518
11241
  __decorateClass([
10519
- property28({ type: String, reflect: true })
11242
+ property29({ type: String, reflect: true })
10520
11243
  ], RelTopbar.prototype, "variant", 2);
10521
11244
  __decorateClass([
10522
- property28({ type: Boolean, reflect: true })
11245
+ property29({ type: Boolean, reflect: true })
10523
11246
  ], RelTopbar.prototype, "mobileOpen", 2);
10524
11247
  __decorateClass([
10525
- property28({ type: Boolean, reflect: true })
11248
+ property29({ type: Boolean, reflect: true })
10526
11249
  ], RelTopbar.prototype, "showMenuToggle", 2);
10527
11250
  __decorateClass([
10528
- property28({ type: Boolean, reflect: true })
11251
+ property29({ type: Boolean, reflect: true })
10529
11252
  ], RelTopbar.prototype, "compact", 2);
10530
11253
  __decorateClass([
10531
- property28({ type: Boolean, reflect: true })
11254
+ property29({ type: Boolean, reflect: true })
10532
11255
  ], RelTopbar.prototype, "sticky", 2);
10533
11256
  __decorateClass([
10534
- property28({ type: String })
11257
+ property29({ type: String })
10535
11258
  ], RelTopbar.prototype, "forceLayout", 2);
10536
11259
  __decorateClass([
10537
11260
  state11()
@@ -10545,7 +11268,7 @@ RelTopbar = __decorateClass([
10545
11268
 
10546
11269
  // src/components/rel-topbar/rel-topbar-item.ts
10547
11270
  import { LitElement as LitElement35, html as html35, css as css32 } from "lit";
10548
- import { customElement as customElement35, property as property29, state as state12 } from "lit/decorators.js";
11271
+ import { customElement as customElement35, property as property30, state as state12 } from "lit/decorators.js";
10549
11272
  import "@reliability-design/icons/rel-icon";
10550
11273
  var RelTopbarItem = class extends LitElement35 {
10551
11274
  constructor() {
@@ -10711,8 +11434,6 @@ RelTopbarItem.styles = css32`
10711
11434
  color: var(--_item-color);
10712
11435
 
10713
11436
 
10714
-
10715
-
10716
11437
  text-decoration: none;
10717
11438
  white-space: nowrap;
10718
11439
  position: relative;
@@ -10813,25 +11534,25 @@ RelTopbarItem.styles = css32`
10813
11534
  }
10814
11535
  `;
10815
11536
  __decorateClass([
10816
- property29({ type: String })
11537
+ property30({ type: String })
10817
11538
  ], RelTopbarItem.prototype, "label", 2);
10818
11539
  __decorateClass([
10819
- property29({ type: String })
11540
+ property30({ type: String })
10820
11541
  ], RelTopbarItem.prototype, "href", 2);
10821
11542
  __decorateClass([
10822
- property29({ type: Boolean, reflect: true })
11543
+ property30({ type: Boolean, reflect: true })
10823
11544
  ], RelTopbarItem.prototype, "active", 2);
10824
11545
  __decorateClass([
10825
- property29({ type: Boolean, reflect: true })
11546
+ property30({ type: Boolean, reflect: true })
10826
11547
  ], RelTopbarItem.prototype, "disabled", 2);
10827
11548
  __decorateClass([
10828
- property29({ type: Boolean, reflect: true })
11549
+ property30({ type: Boolean, reflect: true })
10829
11550
  ], RelTopbarItem.prototype, "expandable", 2);
10830
11551
  __decorateClass([
10831
- property29({ type: Boolean, reflect: true })
11552
+ property30({ type: Boolean, reflect: true })
10832
11553
  ], RelTopbarItem.prototype, "open", 2);
10833
11554
  __decorateClass([
10834
- property29({ type: String })
11555
+ property30({ type: String })
10835
11556
  ], RelTopbarItem.prototype, "value", 2);
10836
11557
  __decorateClass([
10837
11558
  state12()
@@ -10842,7 +11563,7 @@ RelTopbarItem = __decorateClass([
10842
11563
 
10843
11564
  // src/components/rel-topbar/rel-topbar-profile.ts
10844
11565
  import { LitElement as LitElement36, html as html36, css as css33 } from "lit";
10845
- import { customElement as customElement36, property as property30 } from "lit/decorators.js";
11566
+ import { customElement as customElement36, property as property31 } from "lit/decorators.js";
10846
11567
  var RelTopbarProfile = class extends LitElement36 {
10847
11568
  constructor() {
10848
11569
  super(...arguments);
@@ -10944,9 +11665,7 @@ RelTopbarProfile.styles = css33`
10944
11665
 
10945
11666
  .name {
10946
11667
 
10947
-
10948
11668
  color: var(--rel-text-default);
10949
-
10950
11669
  white-space: nowrap;
10951
11670
  overflow: hidden;
10952
11671
  text-overflow: ellipsis;
@@ -10965,9 +11684,7 @@ RelTopbarProfile.styles = css33`
10965
11684
 
10966
11685
  .subtitle {
10967
11686
 
10968
-
10969
11687
  color: var(--rel-text-placeholder);
10970
-
10971
11688
  white-space: nowrap;
10972
11689
  overflow: hidden;
10973
11690
  text-overflow: ellipsis;
@@ -10992,9 +11709,7 @@ RelTopbarProfile.styles = css33`
10992
11709
  padding: 2px var(--rel-spacing-2xs, 4px);
10993
11710
  border-radius: var(--rel-border-radius-xs, 2px);
10994
11711
 
10995
-
10996
11712
  text-transform: uppercase;
10997
-
10998
11713
  flex-shrink: 0;
10999
11714
  font-family: var(--rel-body-xs-semibold-font-family);
11000
11715
  font-weight: var(--rel-body-xs-semibold-font-weight);
@@ -11060,22 +11775,22 @@ RelTopbarProfile.styles = css33`
11060
11775
  }
11061
11776
  `;
11062
11777
  __decorateClass([
11063
- property30({ type: String, reflect: true })
11778
+ property31({ type: String, reflect: true })
11064
11779
  ], RelTopbarProfile.prototype, "type", 2);
11065
11780
  __decorateClass([
11066
- property30({ type: String })
11781
+ property31({ type: String })
11067
11782
  ], RelTopbarProfile.prototype, "initials", 2);
11068
11783
  __decorateClass([
11069
- property30({ type: String })
11784
+ property31({ type: String })
11070
11785
  ], RelTopbarProfile.prototype, "name", 2);
11071
11786
  __decorateClass([
11072
- property30({ type: String })
11787
+ property31({ type: String })
11073
11788
  ], RelTopbarProfile.prototype, "subtitle", 2);
11074
11789
  __decorateClass([
11075
- property30({ type: String, reflect: true })
11790
+ property31({ type: String, reflect: true })
11076
11791
  ], RelTopbarProfile.prototype, "reward", 2);
11077
11792
  __decorateClass([
11078
- property30({ type: Boolean, reflect: true })
11793
+ property31({ type: Boolean, reflect: true })
11079
11794
  ], RelTopbarProfile.prototype, "compact", 2);
11080
11795
  RelTopbarProfile = __decorateClass([
11081
11796
  customElement36("rel-topbar-profile")
@@ -11083,7 +11798,7 @@ RelTopbarProfile = __decorateClass([
11083
11798
 
11084
11799
  // src/components/rel-otp/rel-otp.ts
11085
11800
  import { LitElement as LitElement37, html as html37, css as css34 } from "lit";
11086
- import { customElement as customElement37, property as property31, state as state13, query as query6 } from "lit/decorators.js";
11801
+ import { customElement as customElement37, property as property32, state as state13, query as query6 } from "lit/decorators.js";
11087
11802
  var RelOtp = class extends LitElement37 {
11088
11803
  constructor() {
11089
11804
  super(...arguments);
@@ -11341,7 +12056,7 @@ var RelOtp = class extends LitElement37 {
11341
12056
  data-index="${index}"
11342
12057
  type="${this.mask ? "password" : "text"}"
11343
12058
  inputmode="${this.getInputMode()}"
11344
- autocomplete="new-password"
12059
+ autocomplete="one-time-code"
11345
12060
  pattern="${this.pattern || ""}"
11346
12061
  placeholder="${this.placeholder}"
11347
12062
  maxlength="1"
@@ -11404,7 +12119,6 @@ RelOtp.styles = css34`
11404
12119
  align-items: center;
11405
12120
  justify-content: center;
11406
12121
  color: var(--rel-border-default);
11407
-
11408
12122
  user-select: none;
11409
12123
  padding: 0 var(--rel-spacing-3xs);
11410
12124
  font-family: var(--rel-action-xl-font-family);
@@ -11425,7 +12139,6 @@ RelOtp.styles = css34`
11425
12139
  border-radius: var(--rel-border-radius-sm);
11426
12140
  background: var(--rel-bg-neutral);
11427
12141
 
11428
-
11429
12142
  text-align: center;
11430
12143
  color: var(--rel-text-default);
11431
12144
  outline: none;
@@ -11515,55 +12228,55 @@ RelOtp.styles = css34`
11515
12228
 
11516
12229
  `;
11517
12230
  __decorateClass([
11518
- property31({ type: String, reflect: true })
12231
+ property32({ type: String, reflect: true })
11519
12232
  ], RelOtp.prototype, "value", 2);
11520
12233
  __decorateClass([
11521
- property31({ type: Number })
12234
+ property32({ type: Number })
11522
12235
  ], RelOtp.prototype, "length", 2);
11523
12236
  __decorateClass([
11524
- property31({ type: Number, attribute: "group-size" })
12237
+ property32({ type: Number, attribute: "group-size" })
11525
12238
  ], RelOtp.prototype, "groupSize", 2);
11526
12239
  __decorateClass([
11527
- property31({ type: String })
12240
+ property32({ type: String })
11528
12241
  ], RelOtp.prototype, "placeholder", 2);
11529
12242
  __decorateClass([
11530
- property31({ type: String })
12243
+ property32({ type: String })
11531
12244
  ], RelOtp.prototype, "type", 2);
11532
12245
  __decorateClass([
11533
- property31({ type: Boolean })
12246
+ property32({ type: Boolean })
11534
12247
  ], RelOtp.prototype, "mask", 2);
11535
12248
  __decorateClass([
11536
- property31({ type: Boolean, reflect: true })
12249
+ property32({ type: Boolean, reflect: true })
11537
12250
  ], RelOtp.prototype, "disabled", 2);
11538
12251
  __decorateClass([
11539
- property31({ type: Boolean, reflect: true })
12252
+ property32({ type: Boolean, reflect: true })
11540
12253
  ], RelOtp.prototype, "readonly", 2);
11541
12254
  __decorateClass([
11542
- property31({ type: Boolean })
12255
+ property32({ type: Boolean })
11543
12256
  ], RelOtp.prototype, "required", 2);
11544
12257
  __decorateClass([
11545
- property31({ type: String })
12258
+ property32({ type: String })
11546
12259
  ], RelOtp.prototype, "name", 2);
11547
12260
  __decorateClass([
11548
- property31({ type: String })
12261
+ property32({ type: String })
11549
12262
  ], RelOtp.prototype, "autocomplete", 2);
11550
12263
  __decorateClass([
11551
- property31({ type: String })
12264
+ property32({ type: String })
11552
12265
  ], RelOtp.prototype, "inputmode", 2);
11553
12266
  __decorateClass([
11554
- property31({ type: String })
12267
+ property32({ type: String })
11555
12268
  ], RelOtp.prototype, "pattern", 2);
11556
12269
  __decorateClass([
11557
- property31({ type: String, attribute: "aria-label" })
12270
+ property32({ type: String, attribute: "aria-label" })
11558
12271
  ], RelOtp.prototype, "ariaLabel", 2);
11559
12272
  __decorateClass([
11560
- property31({ type: Boolean, reflect: true })
12273
+ property32({ type: Boolean, reflect: true })
11561
12274
  ], RelOtp.prototype, "invalid", 2);
11562
12275
  __decorateClass([
11563
- property31({ type: Boolean, attribute: "show-separator" })
12276
+ property32({ type: Boolean, attribute: "show-separator" })
11564
12277
  ], RelOtp.prototype, "showSeparator", 2);
11565
12278
  __decorateClass([
11566
- property31({ type: String, reflect: true })
12279
+ property32({ type: String, reflect: true })
11567
12280
  ], RelOtp.prototype, "size", 2);
11568
12281
  __decorateClass([
11569
12282
  state13()
@@ -11576,8 +12289,8 @@ RelOtp = __decorateClass([
11576
12289
  ], RelOtp);
11577
12290
 
11578
12291
  // src/components/rel-pagination/rel-pagination.ts
11579
- import { LitElement as LitElement38, html as html38, css as css35, nothing as nothing9 } from "lit";
11580
- import { customElement as customElement38, property as property32, state as state14 } from "lit/decorators.js";
12292
+ import { LitElement as LitElement38, html as html38, css as css35, nothing as nothing12 } from "lit";
12293
+ import { customElement as customElement38, property as property33, state as state14 } from "lit/decorators.js";
11581
12294
  var RelPagination = class extends LitElement38 {
11582
12295
  constructor() {
11583
12296
  super(...arguments);
@@ -11709,7 +12422,7 @@ var RelPagination = class extends LitElement38 {
11709
12422
  type="button"
11710
12423
  class="pag-page-btn ${isNear ? "near" : ""} ${p === 1 || p === total ? "edge" : ""}"
11711
12424
  aria-label="Page ${p}"
11712
- title="${label === String(p) ? nothing9 : `Page ${p}`}"
12425
+ title="${label === String(p) ? nothing12 : `Page ${p}`}"
11713
12426
  aria-current="${p === current ? "page" : "false"}"
11714
12427
  @click="${() => this.handlePageChange(p)}"
11715
12428
  >${label}</button>`;
@@ -12050,34 +12763,34 @@ RelPagination.styles = css35`
12050
12763
  }
12051
12764
  `;
12052
12765
  __decorateClass([
12053
- property32({ type: String, reflect: true })
12766
+ property33({ type: String, reflect: true })
12054
12767
  ], RelPagination.prototype, "type", 2);
12055
12768
  __decorateClass([
12056
- property32({ type: Number })
12769
+ property33({ type: Number })
12057
12770
  ], RelPagination.prototype, "page", 2);
12058
12771
  __decorateClass([
12059
- property32({ type: Number })
12772
+ property33({ type: Number })
12060
12773
  ], RelPagination.prototype, "defaultPage", 2);
12061
12774
  __decorateClass([
12062
- property32({ type: Number })
12775
+ property33({ type: Number })
12063
12776
  ], RelPagination.prototype, "totalPages", 2);
12064
12777
  __decorateClass([
12065
- property32({ type: Number })
12778
+ property33({ type: Number })
12066
12779
  ], RelPagination.prototype, "totalItems", 2);
12067
12780
  __decorateClass([
12068
- property32({ type: Number })
12781
+ property33({ type: Number })
12069
12782
  ], RelPagination.prototype, "perPage", 2);
12070
12783
  __decorateClass([
12071
- property32({ type: Boolean })
12784
+ property33({ type: Boolean })
12072
12785
  ], RelPagination.prototype, "showLabel", 2);
12073
12786
  __decorateClass([
12074
- property32({ type: Boolean, reflect: true })
12787
+ property33({ type: Boolean, reflect: true })
12075
12788
  ], RelPagination.prototype, "disabled", 2);
12076
12789
  __decorateClass([
12077
- property32({ type: String })
12790
+ property33({ type: String })
12078
12791
  ], RelPagination.prototype, "hrefTemplate", 2);
12079
12792
  __decorateClass([
12080
- property32({ type: String })
12793
+ property33({ type: String })
12081
12794
  ], RelPagination.prototype, "ariaLabel", 2);
12082
12795
  __decorateClass([
12083
12796
  state14()
@@ -12088,7 +12801,7 @@ RelPagination = __decorateClass([
12088
12801
 
12089
12802
  // src/components/rel-popover/rel-popover.ts
12090
12803
  import { LitElement as LitElement39, html as html39, css as css36 } from "lit";
12091
- import { customElement as customElement39, property as property33, state as state15, query as query7 } from "lit/decorators.js";
12804
+ import { customElement as customElement39, property as property34, state as state15, query as query7 } from "lit/decorators.js";
12092
12805
  var RelPopover = class extends LitElement39 {
12093
12806
  constructor() {
12094
12807
  super(...arguments);
@@ -12117,6 +12830,14 @@ var RelPopover = class extends LitElement39 {
12117
12830
  e.stopPropagation();
12118
12831
  this.setOpen(!this.activeOpen);
12119
12832
  };
12833
+ this.onHostKeyDown = (e) => {
12834
+ if (this.disabled) return;
12835
+ if (e.key !== "Enter" && e.key !== " ") return;
12836
+ if (!this.triggerEl || !e.composedPath().includes(this.triggerEl)) return;
12837
+ e.preventDefault();
12838
+ e.stopPropagation();
12839
+ this.setOpen(!this.activeOpen);
12840
+ };
12120
12841
  this.onOutsidePointerDown = (e) => {
12121
12842
  if (!this.activeOpen) return;
12122
12843
  const path = e.composedPath();
@@ -12190,10 +12911,12 @@ var RelPopover = class extends LitElement39 {
12190
12911
  super.connectedCallback();
12191
12912
  this.internalOpen = this.isControlled() ? !!this.open : this.defaultOpen;
12192
12913
  this.addEventListener("pointerdown", this.onHostPointerDown, true);
12914
+ this.addEventListener("keydown", this.onHostKeyDown, true);
12193
12915
  }
12194
12916
  disconnectedCallback() {
12195
12917
  super.disconnectedCallback();
12196
12918
  this.removeEventListener("pointerdown", this.onHostPointerDown, true);
12919
+ this.removeEventListener("keydown", this.onHostKeyDown, true);
12197
12920
  this.removeGlobalListeners();
12198
12921
  this.hideNativePopover();
12199
12922
  }
@@ -12234,7 +12957,7 @@ var RelPopover = class extends LitElement39 {
12234
12957
  * OPEN / CLOSE
12235
12958
  * ======================= */
12236
12959
  onOpen() {
12237
- this.returnFocusEl = document.activeElement ?? this.triggerEl;
12960
+ this.returnFocusEl = getDeepActiveElement() ?? this.triggerEl;
12238
12961
  this.addGlobalListeners();
12239
12962
  this.showNativePopover();
12240
12963
  requestAnimationFrame(() => {
@@ -12342,6 +13065,12 @@ var RelPopover = class extends LitElement39 {
12342
13065
  this.triggerEl.setAttribute("aria-haspopup", "dialog");
12343
13066
  this.triggerEl.setAttribute("aria-expanded", String(this.activeOpen));
12344
13067
  this.triggerEl.setAttribute("aria-controls", this.uniqueId);
13068
+ if (this.triggerEl.tabIndex < 0 && !this.triggerEl.hasAttribute("tabindex") && getFocusableElements(this.triggerEl).length === 0) {
13069
+ this.triggerEl.setAttribute("tabindex", "0");
13070
+ if (!this.triggerEl.hasAttribute("role")) {
13071
+ this.triggerEl.setAttribute("role", "button");
13072
+ }
13073
+ }
12345
13074
  }
12346
13075
  /* =======================
12347
13076
  * RENDER
@@ -12402,34 +13131,34 @@ RelPopover.styles = css36`
12402
13131
  }
12403
13132
  `;
12404
13133
  __decorateClass([
12405
- property33({ type: Boolean, reflect: true })
13134
+ property34({ type: Boolean, reflect: true })
12406
13135
  ], RelPopover.prototype, "open", 2);
12407
13136
  __decorateClass([
12408
- property33({ type: Boolean, attribute: "defaultopen" })
13137
+ property34({ type: Boolean, attribute: "defaultopen" })
12409
13138
  ], RelPopover.prototype, "defaultOpen", 2);
12410
13139
  __decorateClass([
12411
- property33({ type: Boolean, reflect: true })
13140
+ property34({ type: Boolean, reflect: true })
12412
13141
  ], RelPopover.prototype, "disabled", 2);
12413
13142
  __decorateClass([
12414
- property33({ type: String, reflect: true })
13143
+ property34({ type: String, reflect: true })
12415
13144
  ], RelPopover.prototype, "side", 2);
12416
13145
  __decorateClass([
12417
- property33({ type: String, reflect: true })
13146
+ property34({ type: String, reflect: true })
12418
13147
  ], RelPopover.prototype, "align", 2);
12419
13148
  __decorateClass([
12420
- property33({ type: Number, attribute: "sideoffset" })
13149
+ property34({ type: Number, attribute: "sideoffset" })
12421
13150
  ], RelPopover.prototype, "sideOffset", 2);
12422
13151
  __decorateClass([
12423
- property33({ type: Number, attribute: "alignoffset" })
13152
+ property34({ type: Number, attribute: "alignoffset" })
12424
13153
  ], RelPopover.prototype, "alignOffset", 2);
12425
13154
  __decorateClass([
12426
- property33({ type: Boolean, attribute: "trapfocus" })
13155
+ property34({ type: Boolean, attribute: "trapfocus" })
12427
13156
  ], RelPopover.prototype, "trapFocus", 2);
12428
13157
  __decorateClass([
12429
- property33({ type: Boolean, attribute: "closeonescape" })
13158
+ property34({ type: Boolean, attribute: "closeonescape" })
12430
13159
  ], RelPopover.prototype, "closeOnEscape", 2);
12431
13160
  __decorateClass([
12432
- property33({ type: Boolean, attribute: "closeonoutsideclick" })
13161
+ property34({ type: Boolean, attribute: "closeonoutsideclick" })
12433
13162
  ], RelPopover.prototype, "closeOnOutsideClick", 2);
12434
13163
  __decorateClass([
12435
13164
  state15()
@@ -12446,7 +13175,7 @@ RelPopover = __decorateClass([
12446
13175
 
12447
13176
  // src/components/rel-popover/rel-popover-content.ts
12448
13177
  import { LitElement as LitElement40, html as html40, css as css37 } from "lit";
12449
- import { customElement as customElement40, property as property34 } from "lit/decorators.js";
13178
+ import { customElement as customElement40, property as property35 } from "lit/decorators.js";
12450
13179
  var RelPopoverContent = class extends LitElement40 {
12451
13180
  constructor() {
12452
13181
  super(...arguments);
@@ -12524,10 +13253,10 @@ RelPopoverContent.styles = css37`
12524
13253
  }
12525
13254
  `;
12526
13255
  __decorateClass([
12527
- property34({ type: String, attribute: "aria-label" })
13256
+ property35({ type: String, attribute: "aria-label" })
12528
13257
  ], RelPopoverContent.prototype, "ariaLabel", 2);
12529
13258
  __decorateClass([
12530
- property34({ type: String, reflect: true })
13259
+ property35({ type: String, reflect: true })
12531
13260
  ], RelPopoverContent.prototype, "size", 2);
12532
13261
  RelPopoverContent = __decorateClass([
12533
13262
  customElement40("rel-popover-content")
@@ -12535,7 +13264,7 @@ RelPopoverContent = __decorateClass([
12535
13264
 
12536
13265
  // src/components/rel-progress/rel-progress.ts
12537
13266
  import { LitElement as LitElement41, html as html41, css as css38 } from "lit";
12538
- import { customElement as customElement41, property as property35 } from "lit/decorators.js";
13267
+ import { customElement as customElement41, property as property36 } from "lit/decorators.js";
12539
13268
  var RelProgress = class extends LitElement41 {
12540
13269
  constructor() {
12541
13270
  super(...arguments);
@@ -12742,10 +13471,10 @@ RelProgress.styles = css38`
12742
13471
  }
12743
13472
  `;
12744
13473
  __decorateClass([
12745
- property35({ type: String, reflect: true })
13474
+ property36({ type: String, reflect: true })
12746
13475
  ], RelProgress.prototype, "mode", 2);
12747
13476
  __decorateClass([
12748
- property35({ type: Number })
13477
+ property36({ type: Number })
12749
13478
  ], RelProgress.prototype, "value", 2);
12750
13479
  RelProgress = __decorateClass([
12751
13480
  customElement41("rel-progress")
@@ -12753,7 +13482,7 @@ RelProgress = __decorateClass([
12753
13482
 
12754
13483
  // src/components/rel-resizable/rel-resizable-group.ts
12755
13484
  import { LitElement as LitElement42, html as html42, css as css39 } from "lit";
12756
- import { customElement as customElement42, property as property36 } from "lit/decorators.js";
13485
+ import { customElement as customElement42, property as property37 } from "lit/decorators.js";
12757
13486
  var RelResizableGroup = class extends LitElement42 {
12758
13487
  constructor() {
12759
13488
  super(...arguments);
@@ -12821,6 +13550,14 @@ var RelResizableGroup = class extends LitElement42 {
12821
13550
  const delta = e.key === "ArrowUp" ? -step : step;
12822
13551
  this.applyKeyboardResize(handleIndex, delta);
12823
13552
  applied = true;
13553
+ } else if (e.key === "Home" || e.key === "End") {
13554
+ const leftPanel = this.panels[handleIndex];
13555
+ if (leftPanel && handleIndex + 1 < this.panels.length) {
13556
+ e.preventDefault();
13557
+ const target2 = e.key === "Home" ? leftPanel.minSize : leftPanel.maxSize;
13558
+ this.applyKeyboardResize(handleIndex, target2 - leftPanel.currentSize);
13559
+ applied = true;
13560
+ }
12824
13561
  }
12825
13562
  if (applied) {
12826
13563
  this.dispatchResizeEvent("rel-resize-end");
@@ -12860,6 +13597,13 @@ var RelResizableGroup = class extends LitElement42 {
12860
13597
  });
12861
13598
  const sizes = this.calculateInitialSizes();
12862
13599
  this.applySizes(sizes);
13600
+ this.handles.forEach((handle, idx) => {
13601
+ const left = sizes[idx];
13602
+ const right = sizes[idx + 1];
13603
+ if (left !== void 0 && right !== void 0 && left + right > 0) {
13604
+ handle.updateAriaValue(left / (left + right) * 100);
13605
+ }
13606
+ });
12863
13607
  }
12864
13608
  calculateInitialSizes() {
12865
13609
  const sizes = [];
@@ -13030,7 +13774,7 @@ RelResizableGroup.styles = css39`
13030
13774
  }
13031
13775
  `;
13032
13776
  __decorateClass([
13033
- property36({ type: String, reflect: true })
13777
+ property37({ type: String, reflect: true })
13034
13778
  ], RelResizableGroup.prototype, "direction", 2);
13035
13779
  RelResizableGroup = __decorateClass([
13036
13780
  customElement42("rel-resizable-group")
@@ -13038,7 +13782,7 @@ RelResizableGroup = __decorateClass([
13038
13782
 
13039
13783
  // src/components/rel-resizable/rel-resizable-panel.ts
13040
13784
  import { LitElement as LitElement43, html as html43, css as css40 } from "lit";
13041
- import { customElement as customElement43, property as property37 } from "lit/decorators.js";
13785
+ import { customElement as customElement43, property as property38 } from "lit/decorators.js";
13042
13786
  var RelResizablePanel = class extends LitElement43 {
13043
13787
  constructor() {
13044
13788
  super(...arguments);
@@ -13080,13 +13824,13 @@ RelResizablePanel.styles = css40`
13080
13824
  }
13081
13825
  `;
13082
13826
  __decorateClass([
13083
- property37({ type: Number, attribute: "defaultsize" })
13827
+ property38({ type: Number, attribute: "defaultsize" })
13084
13828
  ], RelResizablePanel.prototype, "defaultSize", 2);
13085
13829
  __decorateClass([
13086
- property37({ type: Number, attribute: "minsize" })
13830
+ property38({ type: Number, attribute: "minsize" })
13087
13831
  ], RelResizablePanel.prototype, "minSize", 2);
13088
13832
  __decorateClass([
13089
- property37({ type: Number, attribute: "maxsize" })
13833
+ property38({ type: Number, attribute: "maxsize" })
13090
13834
  ], RelResizablePanel.prototype, "maxSize", 2);
13091
13835
  RelResizablePanel = __decorateClass([
13092
13836
  customElement43("rel-resizable-panel")
@@ -13094,7 +13838,7 @@ RelResizablePanel = __decorateClass([
13094
13838
 
13095
13839
  // src/components/rel-resizable/rel-resizable-handle.ts
13096
13840
  import { LitElement as LitElement44, html as html44, css as css41 } from "lit";
13097
- import { customElement as customElement44, property as property38 } from "lit/decorators.js";
13841
+ import { customElement as customElement44, property as property39 } from "lit/decorators.js";
13098
13842
  var RelResizableHandle = class extends LitElement44 {
13099
13843
  constructor() {
13100
13844
  super(...arguments);
@@ -13222,7 +13966,7 @@ RelResizableHandle.styles = css41`
13222
13966
  }
13223
13967
  `;
13224
13968
  __decorateClass([
13225
- property38({ type: String, reflect: true })
13969
+ property39({ type: String, reflect: true })
13226
13970
  ], RelResizableHandle.prototype, "orientation", 2);
13227
13971
  RelResizableHandle = __decorateClass([
13228
13972
  customElement44("rel-resizable-handle")
@@ -13230,7 +13974,7 @@ RelResizableHandle = __decorateClass([
13230
13974
 
13231
13975
  // src/components/rel-segmented-button/rel-segmented-button.ts
13232
13976
  import { LitElement as LitElement45, html as html45, css as css42 } from "lit";
13233
- import { customElement as customElement45, property as property39 } from "lit/decorators.js";
13977
+ import { customElement as customElement45, property as property40 } from "lit/decorators.js";
13234
13978
  var RelSegmentedButton = class extends LitElement45 {
13235
13979
  constructor() {
13236
13980
  super(...arguments);
@@ -13238,6 +13982,26 @@ var RelSegmentedButton = class extends LitElement45 {
13238
13982
  this.active = "";
13239
13983
  this.size = "medium";
13240
13984
  this.align = "left";
13985
+ /** APG radio-group navigation: arrows move focus AND select, the group is
13986
+ * one Tab stop (roving tabindex on the selected segment). */
13987
+ this.onKeyDown = (e) => {
13988
+ const prevKey = e.key === "ArrowLeft" || e.key === "ArrowUp";
13989
+ const nextKey = e.key === "ArrowRight" || e.key === "ArrowDown";
13990
+ if (!prevKey && !nextKey && e.key !== "Home" && e.key !== "End") return;
13991
+ const enabled = this.options.filter((o) => !o.disabled);
13992
+ if (enabled.length === 0) return;
13993
+ e.preventDefault();
13994
+ const currentIdx = enabled.findIndex((o) => o.value === this.active);
13995
+ let target;
13996
+ if (e.key === "Home") target = 0;
13997
+ else if (e.key === "End") target = enabled.length - 1;
13998
+ else if (prevKey) target = currentIdx <= 0 ? enabled.length - 1 : currentIdx - 1;
13999
+ else target = (currentIdx + 1) % enabled.length;
14000
+ this.setActive(enabled[target]);
14001
+ this.updateComplete.then(() => {
14002
+ this.shadowRoot?.querySelector('button[tabindex="0"]')?.focus();
14003
+ });
14004
+ };
13241
14005
  }
13242
14006
  setActive(option) {
13243
14007
  if (!option.disabled) {
@@ -13251,7 +14015,7 @@ var RelSegmentedButton = class extends LitElement45 {
13251
14015
  );
13252
14016
  }
13253
14017
  }
13254
- renderSegment(option) {
14018
+ renderSegment(option, rovingValue) {
13255
14019
  const isActive = this.active === option.value;
13256
14020
  const classes = [
13257
14021
  "segment",
@@ -13261,6 +14025,9 @@ var RelSegmentedButton = class extends LitElement45 {
13261
14025
  return html45`
13262
14026
  <button
13263
14027
  part="option" class="${classes}"
14028
+ role="radio"
14029
+ aria-checked="${isActive}"
14030
+ tabindex="${!option.disabled && option.value === rovingValue ? 0 : -1}"
13264
14031
  ?disabled="${option.disabled}"
13265
14032
  @click="${() => this.setActive(option)}">
13266
14033
  ${option.label}
@@ -13273,9 +14040,15 @@ var RelSegmentedButton = class extends LitElement45 {
13273
14040
  this.size,
13274
14041
  `align-${this.align}`
13275
14042
  ].join(" ");
14043
+ const enabled = this.options.filter((o) => !o.disabled);
14044
+ const rovingValue = enabled.some((o) => o.value === this.active) ? this.active : enabled[0]?.value ?? null;
13276
14045
  return html45`
13277
- <div part="base" class="${containerClasses}">
13278
- ${this.options.map((option) => this.renderSegment(option))}
14046
+ <div
14047
+ part="base" class="${containerClasses}"
14048
+ role="radiogroup"
14049
+ @keydown="${this.onKeyDown}"
14050
+ >
14051
+ ${this.options.map((option) => this.renderSegment(option, rovingValue))}
13279
14052
  </div>
13280
14053
  `;
13281
14054
  }
@@ -13386,24 +14159,24 @@ RelSegmentedButton.styles = css42`
13386
14159
  }
13387
14160
  `;
13388
14161
  __decorateClass([
13389
- property39({ type: Array })
14162
+ property40({ type: Array })
13390
14163
  ], RelSegmentedButton.prototype, "options", 2);
13391
14164
  __decorateClass([
13392
- property39({ type: String })
14165
+ property40({ type: String })
13393
14166
  ], RelSegmentedButton.prototype, "active", 2);
13394
14167
  __decorateClass([
13395
- property39({ type: String })
14168
+ property40({ type: String })
13396
14169
  ], RelSegmentedButton.prototype, "size", 2);
13397
14170
  __decorateClass([
13398
- property39({ type: String })
14171
+ property40({ type: String })
13399
14172
  ], RelSegmentedButton.prototype, "align", 2);
13400
14173
  RelSegmentedButton = __decorateClass([
13401
14174
  customElement45("rel-segmented-button")
13402
14175
  ], RelSegmentedButton);
13403
14176
 
13404
14177
  // src/components/rel-select/rel-select.ts
13405
- import { LitElement as LitElement46, html as html46, css as css43, nothing as nothing10 } from "lit";
13406
- import { customElement as customElement46, property as property40, state as state16, query as query8 } from "lit/decorators.js";
14178
+ import { LitElement as LitElement46, html as html46, css as css43, nothing as nothing13 } from "lit";
14179
+ import { customElement as customElement46, property as property41, state as state16, query as query8 } from "lit/decorators.js";
13407
14180
  import { repeat as repeat2 } from "lit/directives/repeat.js";
13408
14181
  import "@reliability-design/icons/rel-icon";
13409
14182
  function normalizeOption(o) {
@@ -13437,6 +14210,8 @@ var RelSelect = class extends LitElement46 {
13437
14210
  this.noSearch = false;
13438
14211
  this.open = false;
13439
14212
  this.highlightedIndex = -1;
14213
+ this.selectAllHighlighted = false;
14214
+ this.typeaheadBuffer = "";
13440
14215
  this.panelStyle = "";
13441
14216
  this.searchValue = "";
13442
14217
  this.internalState = "default";
@@ -13485,6 +14260,7 @@ var RelSelect = class extends LitElement46 {
13485
14260
  this.onSearchInput = (e) => {
13486
14261
  this.searchValue = e.target.value;
13487
14262
  this.highlightedIndex = this.filteredOptions.length > 0 ? 0 : -1;
14263
+ this.selectAllHighlighted = false;
13488
14264
  requestAnimationFrame(() => this.updatePosition());
13489
14265
  };
13490
14266
  }
@@ -13612,6 +14388,7 @@ var RelSelect = class extends LitElement46 {
13612
14388
  this.open = true;
13613
14389
  this.searchValue = "";
13614
14390
  this.highlightedIndex = -1;
14391
+ this.selectAllHighlighted = false;
13615
14392
  this.addGlobalListeners();
13616
14393
  requestAnimationFrame(() => {
13617
14394
  this.showNativePopover();
@@ -13687,6 +14464,11 @@ var RelSelect = class extends LitElement46 {
13687
14464
  }
13688
14465
  onTriggerKeyDown(e) {
13689
14466
  if (this.state === "disabled") return;
14467
+ if (this.multiple && (e.key === "Backspace" || e.key === "Delete") && this.selectedValues.length > 0) {
14468
+ e.preventDefault();
14469
+ this.removeChip(this.selectedValues[this.selectedValues.length - 1]);
14470
+ return;
14471
+ }
13690
14472
  if (!this.open) {
13691
14473
  if (["ArrowDown", "ArrowUp", "Enter", " "].includes(e.key)) {
13692
14474
  e.preventDefault();
@@ -13697,26 +14479,60 @@ var RelSelect = class extends LitElement46 {
13697
14479
  if (this.noSearch) this.handleListNavigation(e);
13698
14480
  }
13699
14481
  onSearchKeyDown(e) {
14482
+ if (this.multiple && e.key === "Backspace" && this.searchValue === "" && this.selectedValues.length > 0) {
14483
+ this.removeChip(this.selectedValues[this.selectedValues.length - 1]);
14484
+ return;
14485
+ }
13700
14486
  this.handleListNavigation(e);
13701
14487
  }
13702
14488
  handleListNavigation(e) {
13703
14489
  const filtered = this.filteredOptions;
14490
+ const hasSelectAll = this.multiple && filtered.length > 0;
13704
14491
  switch (e.key) {
13705
14492
  case "ArrowDown":
13706
14493
  e.preventDefault();
13707
- this.highlightedIndex = Math.min(filtered.length - 1, this.highlightedIndex + 1);
14494
+ if (this.selectAllHighlighted) {
14495
+ this.selectAllHighlighted = false;
14496
+ this.highlightedIndex = filtered.length > 0 ? 0 : -1;
14497
+ } else if (this.highlightedIndex === -1 && hasSelectAll) {
14498
+ this.selectAllHighlighted = true;
14499
+ } else {
14500
+ this.highlightedIndex = Math.min(filtered.length - 1, this.highlightedIndex + 1);
14501
+ }
14502
+ this.scrollHighlightedIntoView();
13708
14503
  break;
13709
14504
  case "ArrowUp":
13710
14505
  e.preventDefault();
13711
- this.highlightedIndex = Math.max(0, this.highlightedIndex - 1);
14506
+ if (!this.selectAllHighlighted && this.highlightedIndex <= 0 && hasSelectAll) {
14507
+ this.highlightedIndex = -1;
14508
+ this.selectAllHighlighted = true;
14509
+ } else {
14510
+ this.highlightedIndex = Math.max(0, this.highlightedIndex - 1);
14511
+ }
14512
+ this.scrollHighlightedIntoView();
14513
+ break;
14514
+ case "Home":
14515
+ if (filtered.length === 0) break;
14516
+ e.preventDefault();
14517
+ this.selectAllHighlighted = false;
14518
+ this.highlightedIndex = 0;
14519
+ this.scrollHighlightedIntoView();
14520
+ break;
14521
+ case "End":
14522
+ if (filtered.length === 0) break;
14523
+ e.preventDefault();
14524
+ this.selectAllHighlighted = false;
14525
+ this.highlightedIndex = filtered.length - 1;
14526
+ this.scrollHighlightedIntoView();
14527
+ break;
14528
+ case " ":
14529
+ if (!this.noSearch) return;
14530
+ e.preventDefault();
14531
+ this.activateHighlighted();
13712
14532
  break;
13713
14533
  case "Enter":
13714
14534
  e.preventDefault();
13715
- if (this.highlightedIndex >= 0 && filtered[this.highlightedIndex]) {
13716
- const opt = filtered[this.highlightedIndex];
13717
- if (this.multiple) this.toggleMultiOption(opt);
13718
- else this.selectSingleOption(opt);
13719
- }
14535
+ this.activateHighlighted();
13720
14536
  break;
13721
14537
  case "Escape":
13722
14538
  e.preventDefault();
@@ -13725,8 +14541,55 @@ var RelSelect = class extends LitElement46 {
13725
14541
  case "Tab":
13726
14542
  this.closeListbox();
13727
14543
  break;
14544
+ default:
14545
+ this.handleTypeahead(e);
14546
+ break;
14547
+ }
14548
+ }
14549
+ /** APG typeahead for the no-search mode (with a search field, typing
14550
+ * filters instead). Accumulates printable keys for 500 ms and jumps the
14551
+ * highlight to the next option whose label starts with the buffer. */
14552
+ handleTypeahead(e) {
14553
+ if (!this.noSearch) return;
14554
+ if (e.key.length !== 1 || e.ctrlKey || e.metaKey || e.altKey) return;
14555
+ e.preventDefault();
14556
+ const isNewQuery = this.typeaheadBuffer === "";
14557
+ this.typeaheadBuffer += e.key.toLowerCase();
14558
+ clearTimeout(this.typeaheadTimer);
14559
+ this.typeaheadTimer = window.setTimeout(() => {
14560
+ this.typeaheadBuffer = "";
14561
+ }, 500);
14562
+ const filtered = this.filteredOptions;
14563
+ if (filtered.length === 0) return;
14564
+ const start = Math.max(0, this.highlightedIndex) + (isNewQuery ? 1 : 0);
14565
+ for (let offset = 0; offset < filtered.length; offset++) {
14566
+ const idx = (start + offset) % filtered.length;
14567
+ if (filtered[idx].label.toLowerCase().startsWith(this.typeaheadBuffer)) {
14568
+ this.selectAllHighlighted = false;
14569
+ this.highlightedIndex = idx;
14570
+ this.scrollHighlightedIntoView();
14571
+ return;
14572
+ }
13728
14573
  }
13729
14574
  }
14575
+ activateHighlighted() {
14576
+ if (this.selectAllHighlighted) {
14577
+ this.toggleSelectAll();
14578
+ return;
14579
+ }
14580
+ const filtered = this.filteredOptions;
14581
+ if (this.highlightedIndex >= 0 && filtered[this.highlightedIndex]) {
14582
+ const opt = filtered[this.highlightedIndex];
14583
+ if (this.multiple) this.toggleMultiOption(opt);
14584
+ else this.selectSingleOption(opt);
14585
+ }
14586
+ }
14587
+ scrollHighlightedIntoView() {
14588
+ if (this.highlightedIndex < 0) return;
14589
+ requestAnimationFrame(() => {
14590
+ this.renderRoot.querySelector(`#${this.uniqueId}-option-${this.highlightedIndex}`)?.scrollIntoView({ block: "nearest" });
14591
+ });
14592
+ }
13730
14593
  renderChips() {
13731
14594
  const values = this.selectedValues;
13732
14595
  const visible = values.slice(0, Math.min(this.visibleChipCount, this.maxVisibleChips));
@@ -13755,7 +14618,7 @@ var RelSelect = class extends LitElement46 {
13755
14618
  `;
13756
14619
  }
13757
14620
  )}
13758
- ${overflow > 0 ? html46`<rel-chip label="+${overflow}" size="sm" variant="fill" border="default"></rel-chip>` : nothing10}
14621
+ ${overflow > 0 ? html46`<rel-chip label="+${overflow}" size="sm" variant="fill" border="default"></rel-chip>` : nothing13}
13759
14622
  </span>
13760
14623
  `;
13761
14624
  }
@@ -13804,7 +14667,7 @@ var RelSelect = class extends LitElement46 {
13804
14667
  this.open ? "open" : ""
13805
14668
  ].filter(Boolean).join(" ");
13806
14669
  const listboxId = `${this.uniqueId}-listbox`;
13807
- const activeOptionId = this.open && this.highlightedIndex >= 0 ? `${this.uniqueId}-option-${this.highlightedIndex}` : "";
14670
+ const activeOptionId = !this.open ? "" : this.selectAllHighlighted ? `${this.uniqueId}-select-all` : this.highlightedIndex >= 0 ? `${this.uniqueId}-option-${this.highlightedIndex}` : "";
13808
14671
  const selectedSingle = opts.find((o) => o.value === this.selected);
13809
14672
  return html46`
13810
14673
  <div class="${wrapperClasses}">
@@ -13825,8 +14688,8 @@ var RelSelect = class extends LitElement46 {
13825
14688
  aria-controls="${listboxId}"
13826
14689
  aria-activedescendant="${activeOptionId}"
13827
14690
  aria-invalid="${this.state === "error"}"
13828
- aria-label="${this.fieldAriaLabelledby ? nothing10 : accessibleName || this.placeholder}"
13829
- aria-labelledby="${this.fieldAriaLabelledby ?? nothing10}"
14691
+ aria-label="${this.fieldAriaLabelledby ? nothing13 : accessibleName || this.placeholder}"
14692
+ aria-labelledby="${this.fieldAriaLabelledby ?? nothing13}"
13830
14693
  ?disabled="${isDisabled}"
13831
14694
  @click="${this.onTriggerClick}"
13832
14695
  @keydown="${this.onTriggerKeyDown}"
@@ -13850,7 +14713,7 @@ var RelSelect = class extends LitElement46 {
13850
14713
  ></rel-icon>
13851
14714
  </button>
13852
14715
 
13853
- ${this.multiple && this.selectedValues.length > 0 ? this.renderChipsMeasure() : nothing10}
14716
+ ${this.multiple && this.selectedValues.length > 0 ? this.renderChipsMeasure() : nothing13}
13854
14717
  </div>
13855
14718
 
13856
14719
  ${this.supportingText ? html46`<span part="helper" class="select-support ${this.state === "error" ? "error" : ""}">
@@ -13882,7 +14745,17 @@ var RelSelect = class extends LitElement46 {
13882
14745
  />
13883
14746
  </div>
13884
14747
  </div>` : ""}
13885
- ${this.multiple && filtered.length > 0 ? html46`<div class="select-all-row">
14748
+ ${this.multiple && filtered.length > 0 ? html46`<div
14749
+ id="${this.uniqueId}-select-all"
14750
+ class="select-all-row ${this.selectAllHighlighted ? "highlighted" : ""}"
14751
+ role="option"
14752
+ aria-selected="${this.selectAllStatus === "checked"}"
14753
+ @pointerenter="${() => {
14754
+ this.selectAllHighlighted = true;
14755
+ this.highlightedIndex = -1;
14756
+ }}"
14757
+ @pointerleave="${() => this.selectAllHighlighted = false}"
14758
+ >
13886
14759
  <rel-checkbox
13887
14760
  label="${this.selectAllLabel}"
13888
14761
  status="${this.selectAllStatus}"
@@ -13907,7 +14780,10 @@ var RelSelect = class extends LitElement46 {
13907
14780
  class="checkbox-option ${index === this.highlightedIndex ? "highlighted" : ""}"
13908
14781
  role="option"
13909
14782
  aria-selected="${this.selectedValues.includes(option.value)}"
13910
- @pointerenter="${() => this.highlightedIndex = index}"
14783
+ @pointerenter="${() => {
14784
+ this.highlightedIndex = index;
14785
+ this.selectAllHighlighted = false;
14786
+ }}"
13911
14787
  >
13912
14788
  <rel-checkbox
13913
14789
  label="${option.label}"
@@ -13943,7 +14819,7 @@ var RelSelect = class extends LitElement46 {
13943
14819
  name="${option.icon}"
13944
14820
  size="sm"
13945
14821
  class="select-option-icon"
13946
- ></rel-icon>` : nothing10}
14822
+ ></rel-icon>` : nothing13}
13947
14823
  <span class="select-option-label">${option.label}</span>
13948
14824
  </span>
13949
14825
  ${option.value === this.selected ? html46`<rel-icon name="check" size="sm" class="select-option-check"></rel-icon>` : ""}
@@ -14406,6 +15282,10 @@ RelSelect.styles = css43`
14406
15282
  padding: 12px;
14407
15283
  }
14408
15284
 
15285
+ .select-all-row.highlighted {
15286
+ background: var(--rel-select-option-hover, var(--rel-bg-neutral-elevated-1));
15287
+ }
15288
+
14409
15289
  .select-empty {
14410
15290
  padding: var(--rel-spacing-xs) 12px;
14411
15291
  color: var(--rel-select-placeholder-color, var(--rel-text-body));
@@ -14418,61 +15298,61 @@ RelSelect.styles = css43`
14418
15298
 
14419
15299
  `;
14420
15300
  __decorateClass([
14421
- property40({ type: String })
15301
+ property41({ type: String })
14422
15302
  ], RelSelect.prototype, "label", 2);
14423
15303
  __decorateClass([
14424
- property40({ type: String, attribute: "label-style", reflect: true })
15304
+ property41({ type: String, attribute: "label-style", reflect: true })
14425
15305
  ], RelSelect.prototype, "labelStyle", 2);
14426
15306
  __decorateClass([
14427
- property40({ type: String, attribute: "field-aria-label" })
15307
+ property41({ type: String, attribute: "field-aria-label" })
14428
15308
  ], RelSelect.prototype, "fieldAriaLabel", 2);
14429
15309
  __decorateClass([
14430
- property40({ type: String, attribute: "field-aria-labelledby" })
15310
+ property41({ type: String, attribute: "field-aria-labelledby" })
14431
15311
  ], RelSelect.prototype, "fieldAriaLabelledby", 2);
14432
15312
  __decorateClass([
14433
- property40({ type: Array })
15313
+ property41({ type: Array })
14434
15314
  ], RelSelect.prototype, "options", 2);
14435
15315
  __decorateClass([
14436
- property40({ type: Boolean })
15316
+ property41({ type: Boolean })
14437
15317
  ], RelSelect.prototype, "multiple", 2);
14438
15318
  __decorateClass([
14439
- property40({ type: String })
15319
+ property41({ type: String })
14440
15320
  ], RelSelect.prototype, "selected", 2);
14441
15321
  __decorateClass([
14442
- property40({ type: Array, attribute: "selected-values" })
15322
+ property41({ type: Array, attribute: "selected-values" })
14443
15323
  ], RelSelect.prototype, "selectedValues", 2);
14444
15324
  __decorateClass([
14445
- property40({ type: String })
15325
+ property41({ type: String })
14446
15326
  ], RelSelect.prototype, "state", 2);
14447
15327
  __decorateClass([
14448
- property40({ type: String, attribute: "supporting-text" })
15328
+ property41({ type: String, attribute: "supporting-text" })
14449
15329
  ], RelSelect.prototype, "supportingText", 2);
14450
15330
  __decorateClass([
14451
- property40({ type: String, reflect: true })
15331
+ property41({ type: String, reflect: true })
14452
15332
  ], RelSelect.prototype, "size", 2);
14453
15333
  __decorateClass([
14454
- property40({ type: String })
15334
+ property41({ type: String })
14455
15335
  ], RelSelect.prototype, "border", 2);
14456
15336
  __decorateClass([
14457
- property40({ type: String, attribute: "left-icon" })
15337
+ property41({ type: String, attribute: "left-icon" })
14458
15338
  ], RelSelect.prototype, "leftIcon", 2);
14459
15339
  __decorateClass([
14460
- property40({ type: String, attribute: "right-icon" })
15340
+ property41({ type: String, attribute: "right-icon" })
14461
15341
  ], RelSelect.prototype, "rightIcon", 2);
14462
15342
  __decorateClass([
14463
- property40({ type: String })
15343
+ property41({ type: String })
14464
15344
  ], RelSelect.prototype, "placeholder", 2);
14465
15345
  __decorateClass([
14466
- property40({ type: String, attribute: "search-placeholder" })
15346
+ property41({ type: String, attribute: "search-placeholder" })
14467
15347
  ], RelSelect.prototype, "searchPlaceholder", 2);
14468
15348
  __decorateClass([
14469
- property40({ type: String, attribute: "select-all-label" })
15349
+ property41({ type: String, attribute: "select-all-label" })
14470
15350
  ], RelSelect.prototype, "selectAllLabel", 2);
14471
15351
  __decorateClass([
14472
- property40({ type: Number, attribute: "max-visible-chips" })
15352
+ property41({ type: Number, attribute: "max-visible-chips" })
14473
15353
  ], RelSelect.prototype, "maxVisibleChips", 2);
14474
15354
  __decorateClass([
14475
- property40({ type: Boolean, attribute: "no-search" })
15355
+ property41({ type: Boolean, attribute: "no-search" })
14476
15356
  ], RelSelect.prototype, "noSearch", 2);
14477
15357
  __decorateClass([
14478
15358
  state16()
@@ -14480,6 +15360,9 @@ __decorateClass([
14480
15360
  __decorateClass([
14481
15361
  state16()
14482
15362
  ], RelSelect.prototype, "highlightedIndex", 2);
15363
+ __decorateClass([
15364
+ state16()
15365
+ ], RelSelect.prototype, "selectAllHighlighted", 2);
14483
15366
  __decorateClass([
14484
15367
  state16()
14485
15368
  ], RelSelect.prototype, "panelStyle", 2);
@@ -14513,7 +15396,7 @@ RelSelect = __decorateClass([
14513
15396
 
14514
15397
  // src/components/rel-skeleton/rel-skeleton.ts
14515
15398
  import { LitElement as LitElement47, html as html47, css as css44 } from "lit";
14516
- import { customElement as customElement47, property as property41 } from "lit/decorators.js";
15399
+ import { customElement as customElement47, property as property42 } from "lit/decorators.js";
14517
15400
  var RelSkeleton = class extends LitElement47 {
14518
15401
  constructor() {
14519
15402
  super(...arguments);
@@ -14634,22 +15517,22 @@ RelSkeleton.styles = css44`
14634
15517
  }
14635
15518
  `;
14636
15519
  __decorateClass([
14637
- property41({ type: String, reflect: true })
15520
+ property42({ type: String, reflect: true })
14638
15521
  ], RelSkeleton.prototype, "shape", 2);
14639
15522
  __decorateClass([
14640
- property41({ type: Number })
15523
+ property42({ type: Number })
14641
15524
  ], RelSkeleton.prototype, "lines", 2);
14642
15525
  __decorateClass([
14643
- property41({ type: String })
15526
+ property42({ type: String })
14644
15527
  ], RelSkeleton.prototype, "width", 2);
14645
15528
  __decorateClass([
14646
- property41({ type: String })
15529
+ property42({ type: String })
14647
15530
  ], RelSkeleton.prototype, "height", 2);
14648
15531
  __decorateClass([
14649
- property41({ type: String, reflect: true })
15532
+ property42({ type: String, reflect: true })
14650
15533
  ], RelSkeleton.prototype, "animation", 2);
14651
15534
  __decorateClass([
14652
- property41({ type: Boolean, reflect: true })
15535
+ property42({ type: Boolean, reflect: true })
14653
15536
  ], RelSkeleton.prototype, "loaded", 2);
14654
15537
  RelSkeleton = __decorateClass([
14655
15538
  customElement47("rel-skeleton")
@@ -14657,7 +15540,7 @@ RelSkeleton = __decorateClass([
14657
15540
 
14658
15541
  // src/components/rel-sheet/rel-sheet.ts
14659
15542
  import { LitElement as LitElement48, html as html48, css as css45 } from "lit";
14660
- import { customElement as customElement48, property as property42, query as query9 } from "lit/decorators.js";
15543
+ import { customElement as customElement48, property as property43, query as query9 } from "lit/decorators.js";
14661
15544
  import "@reliability-design/icons/rel-icon";
14662
15545
  var RelModal = class extends LitElement48 {
14663
15546
  constructor() {
@@ -14677,6 +15560,10 @@ var RelModal = class extends LitElement48 {
14677
15560
  if (e.key === "Escape" && this.dismissible) {
14678
15561
  e.preventDefault();
14679
15562
  this.open = false;
15563
+ return;
15564
+ }
15565
+ if (e.key === "Tab" && this.modal && this.panelElement) {
15566
+ trapTabKey(e, this.panelElement);
14680
15567
  }
14681
15568
  };
14682
15569
  this.handleOverlayClick = (e) => {
@@ -14727,9 +15614,18 @@ var RelModal = class extends LitElement48 {
14727
15614
  }
14728
15615
  }
14729
15616
  handleOpen() {
14730
- this.previousFocus = document.activeElement;
15617
+ this.previousFocus = getDeepActiveElement();
14731
15618
  this.lockScroll();
14732
15619
  document.addEventListener("keydown", this.handleKeydown);
15620
+ if (this.modal) {
15621
+ this.updateComplete.then(() => {
15622
+ const panel = this.panelElement;
15623
+ if (!panel) return;
15624
+ const focusTarget = getFocusableElements(panel)[0];
15625
+ if (focusTarget) focusTarget.focus();
15626
+ else panel.focus();
15627
+ });
15628
+ }
14733
15629
  this.dispatchEvent(
14734
15630
  new CustomEvent("rel-open-change", {
14735
15631
  detail: true,
@@ -15066,36 +15962,39 @@ RelModal.styles = css45`
15066
15962
  }
15067
15963
  `;
15068
15964
  __decorateClass([
15069
- property42({ type: Boolean, reflect: true })
15965
+ property43({ type: Boolean, reflect: true })
15070
15966
  ], RelModal.prototype, "open", 2);
15071
15967
  __decorateClass([
15072
- property42({ type: String })
15968
+ property43({ type: String })
15073
15969
  ], RelModal.prototype, "side", 2);
15074
15970
  __decorateClass([
15075
- property42({ type: String })
15971
+ property43({ type: String })
15076
15972
  ], RelModal.prototype, "title", 2);
15077
15973
  __decorateClass([
15078
- property42({ type: String })
15974
+ property43({ type: String })
15079
15975
  ], RelModal.prototype, "description", 2);
15080
15976
  __decorateClass([
15081
- property42({ type: Boolean })
15977
+ property43({ type: Boolean })
15082
15978
  ], RelModal.prototype, "dismissible", 2);
15083
15979
  __decorateClass([
15084
- property42({ type: Boolean })
15980
+ property43({ type: Boolean })
15085
15981
  ], RelModal.prototype, "modal", 2);
15086
15982
  __decorateClass([
15087
- property42({ type: String, reflect: true })
15983
+ property43({ type: String, reflect: true })
15088
15984
  ], RelModal.prototype, "breakpoint", 2);
15089
15985
  __decorateClass([
15090
15986
  query9(".overlay")
15091
15987
  ], RelModal.prototype, "overlayElement", 2);
15988
+ __decorateClass([
15989
+ query9(".panel")
15990
+ ], RelModal.prototype, "panelElement", 2);
15092
15991
  RelModal = __decorateClass([
15093
15992
  customElement48("rel-modal")
15094
15993
  ], RelModal);
15095
15994
 
15096
15995
  // src/components/rel-slider/rel-slider.ts
15097
15996
  import { LitElement as LitElement49, html as html49, css as css46 } from "lit";
15098
- import { customElement as customElement49, property as property43, state as state17 } from "lit/decorators.js";
15997
+ import { customElement as customElement49, property as property44, state as state17 } from "lit/decorators.js";
15099
15998
  var RelSlider = class extends LitElement49 {
15100
15999
  constructor() {
15101
16000
  super(...arguments);
@@ -15704,37 +16603,37 @@ RelSlider.styles = css46`
15704
16603
 
15705
16604
  `;
15706
16605
  __decorateClass([
15707
- property43({ type: String, reflect: true })
16606
+ property44({ type: String, reflect: true })
15708
16607
  ], RelSlider.prototype, "type", 2);
15709
16608
  __decorateClass([
15710
- property43({ type: String, reflect: true })
16609
+ property44({ type: String, reflect: true })
15711
16610
  ], RelSlider.prototype, "size", 2);
15712
16611
  __decorateClass([
15713
- property43({ type: Number })
16612
+ property44({ type: Number })
15714
16613
  ], RelSlider.prototype, "min", 2);
15715
16614
  __decorateClass([
15716
- property43({ type: Number })
16615
+ property44({ type: Number })
15717
16616
  ], RelSlider.prototype, "max", 2);
15718
16617
  __decorateClass([
15719
- property43({ type: Number })
16618
+ property44({ type: Number })
15720
16619
  ], RelSlider.prototype, "step", 2);
15721
16620
  __decorateClass([
15722
- property43({ type: Boolean })
16621
+ property44({ type: Boolean })
15723
16622
  ], RelSlider.prototype, "disabled", 2);
15724
16623
  __decorateClass([
15725
- property43({ type: String })
16624
+ property44({ type: String })
15726
16625
  ], RelSlider.prototype, "track", 2);
15727
16626
  __decorateClass([
15728
- property43({ type: Boolean })
16627
+ property44({ type: Boolean })
15729
16628
  ], RelSlider.prototype, "showTickLabels", 2);
15730
16629
  __decorateClass([
15731
- property43({ type: Boolean })
16630
+ property44({ type: Boolean })
15732
16631
  ], RelSlider.prototype, "showBubble", 2);
15733
16632
  __decorateClass([
15734
- property43({ type: Number })
16633
+ property44({ type: Number })
15735
16634
  ], RelSlider.prototype, "value", 2);
15736
16635
  __decorateClass([
15737
- property43({ type: Number, attribute: "value-end" })
16636
+ property44({ type: Number, attribute: "value-end" })
15738
16637
  ], RelSlider.prototype, "valueEnd", 2);
15739
16638
  __decorateClass([
15740
16639
  state17()
@@ -15745,7 +16644,7 @@ RelSlider = __decorateClass([
15745
16644
 
15746
16645
  // src/components/rel-snackbar/rel-snackbar.ts
15747
16646
  import { LitElement as LitElement50, html as html50, css as css47 } from "lit";
15748
- import { customElement as customElement50, property as property44, state as state18 } from "lit/decorators.js";
16647
+ import { customElement as customElement50, property as property45, state as state18 } from "lit/decorators.js";
15749
16648
  import "@reliability-design/icons/rel-icon";
15750
16649
  var RelSnackbar = class extends LitElement50 {
15751
16650
  constructor() {
@@ -16046,28 +16945,28 @@ RelSnackbar.styles = css47`
16046
16945
  }
16047
16946
  `;
16048
16947
  __decorateClass([
16049
- property44({ type: String })
16948
+ property45({ type: String })
16050
16949
  ], RelSnackbar.prototype, "message", 2);
16051
16950
  __decorateClass([
16052
- property44({ type: String })
16951
+ property45({ type: String })
16053
16952
  ], RelSnackbar.prototype, "action", 2);
16054
16953
  __decorateClass([
16055
- property44({ type: Boolean })
16954
+ property45({ type: Boolean })
16056
16955
  ], RelSnackbar.prototype, "longerAction", 2);
16057
16956
  __decorateClass([
16058
- property44({ type: Boolean })
16957
+ property45({ type: Boolean })
16059
16958
  ], RelSnackbar.prototype, "iconClose", 2);
16060
16959
  __decorateClass([
16061
- property44({ type: String })
16960
+ property45({ type: String })
16062
16961
  ], RelSnackbar.prototype, "lines", 2);
16063
16962
  __decorateClass([
16064
- property44({ type: Number })
16963
+ property45({ type: Number })
16065
16964
  ], RelSnackbar.prototype, "duration", 2);
16066
16965
  __decorateClass([
16067
- property44({ type: String })
16966
+ property45({ type: String })
16068
16967
  ], RelSnackbar.prototype, "type", 2);
16069
16968
  __decorateClass([
16070
- property44({ type: Boolean, reflect: true })
16969
+ property45({ type: Boolean, reflect: true })
16071
16970
  ], RelSnackbar.prototype, "show", 2);
16072
16971
  __decorateClass([
16073
16972
  state18()
@@ -16077,8 +16976,8 @@ RelSnackbar = __decorateClass([
16077
16976
  ], RelSnackbar);
16078
16977
 
16079
16978
  // src/components/rel-stepper/rel-stepper.ts
16080
- import { LitElement as LitElement51, html as html51, css as css48 } from "lit";
16081
- import { customElement as customElement51, property as property45 } from "lit/decorators.js";
16979
+ import { LitElement as LitElement51, html as html51, css as css48, nothing as nothing14 } from "lit";
16980
+ import { customElement as customElement51, property as property46 } from "lit/decorators.js";
16082
16981
  var RelStepper = class extends LitElement51 {
16083
16982
  constructor() {
16084
16983
  super(...arguments);
@@ -16104,6 +17003,28 @@ var RelStepper = class extends LitElement51 {
16104
17003
  if (this.isDisabled(step)) classes.push("disabled");
16105
17004
  return classes.join(" ");
16106
17005
  }
17006
+ onStepKeyDown(e, step, index) {
17007
+ if (e.key === "Enter" || e.key === " ") {
17008
+ e.preventDefault();
17009
+ this.onStepClick(step, index);
17010
+ return;
17011
+ }
17012
+ const prevKey = e.key === "ArrowLeft" || e.key === "ArrowUp";
17013
+ const nextKey = e.key === "ArrowRight" || e.key === "ArrowDown";
17014
+ if (!prevKey && !nextKey && e.key !== "Home" && e.key !== "End") return;
17015
+ const steps = Array.from(
17016
+ this.renderRoot.querySelectorAll(".rel-step:not(.disabled)")
17017
+ );
17018
+ if (steps.length === 0) return;
17019
+ e.preventDefault();
17020
+ const current = steps.indexOf(e.currentTarget);
17021
+ let target;
17022
+ if (e.key === "Home") target = 0;
17023
+ else if (e.key === "End") target = steps.length - 1;
17024
+ else if (prevKey) target = (current - 1 + steps.length) % steps.length;
17025
+ else target = (current + 1) % steps.length;
17026
+ steps[target]?.focus();
17027
+ }
16107
17028
  onStepClick(step, index) {
16108
17029
  if (step.status === "disabled") return;
16109
17030
  this.dispatchEvent(
@@ -16156,7 +17077,12 @@ var RelStepper = class extends LitElement51 {
16156
17077
  (step, idx) => html51`
16157
17078
  <div
16158
17079
  class="${this.getStepClasses(step)}"
17080
+ role="button"
17081
+ tabindex="${this.isDisabled(step) ? -1 : 0}"
17082
+ aria-disabled="${this.isDisabled(step) ? "true" : nothing14}"
17083
+ aria-current="${this.isProgress(step) ? "step" : nothing14}"
16159
17084
  @click="${() => this.onStepClick(step, idx)}"
17085
+ @keydown="${(e) => this.onStepKeyDown(e, step, idx)}"
16160
17086
  >
16161
17087
  ${isVertical && isTextRight ? html51`
16162
17088
  <!-- Indicator with connector below -->
@@ -16243,6 +17169,17 @@ RelStepper.styles = css48`
16243
17169
  .rel-step {
16244
17170
  display: flex;
16245
17171
  position: relative;
17172
+ cursor: pointer;
17173
+ }
17174
+
17175
+ .rel-step.disabled {
17176
+ cursor: not-allowed;
17177
+ }
17178
+
17179
+ .rel-step:focus-visible {
17180
+ outline: 2px solid var(--rel-border-focus);
17181
+ outline-offset: 2px;
17182
+ border-radius: var(--rel-border-radius-xs);
16246
17183
  }
16247
17184
 
16248
17185
  .rel-stepper.horizontal.text-below .rel-step {
@@ -16546,22 +17483,22 @@ RelStepper.styles = css48`
16546
17483
  }
16547
17484
  `;
16548
17485
  __decorateClass([
16549
- property45({ type: Array })
17486
+ property46({ type: Array })
16550
17487
  ], RelStepper.prototype, "steps", 2);
16551
17488
  __decorateClass([
16552
- property45({ type: String })
17489
+ property46({ type: String })
16553
17490
  ], RelStepper.prototype, "textAlign", 2);
16554
17491
  __decorateClass([
16555
- property45({ type: String })
17492
+ property46({ type: String })
16556
17493
  ], RelStepper.prototype, "orientation", 2);
16557
17494
  __decorateClass([
16558
- property45({ type: String })
17495
+ property46({ type: String })
16559
17496
  ], RelStepper.prototype, "size", 2);
16560
17497
  __decorateClass([
16561
- property45({ type: String, reflect: true })
17498
+ property46({ type: String, reflect: true })
16562
17499
  ], RelStepper.prototype, "type", 2);
16563
17500
  __decorateClass([
16564
- property45({ type: String, reflect: true, attribute: "label-placement" })
17501
+ property46({ type: String, reflect: true, attribute: "label-placement" })
16565
17502
  ], RelStepper.prototype, "labelPlacement", 2);
16566
17503
  RelStepper = __decorateClass([
16567
17504
  customElement51("rel-stepper")
@@ -16569,7 +17506,7 @@ RelStepper = __decorateClass([
16569
17506
 
16570
17507
  // src/components/rel-switch/rel-switch.ts
16571
17508
  import { LitElement as LitElement52, html as html52, css as css49 } from "lit";
16572
- import { customElement as customElement52, property as property46, state as state19 } from "lit/decorators.js";
17509
+ import { customElement as customElement52, property as property47, state as state19 } from "lit/decorators.js";
16573
17510
  var RelSwitch = class extends LitElement52 {
16574
17511
  constructor() {
16575
17512
  super(...arguments);
@@ -16760,13 +17697,13 @@ RelSwitch.styles = css49`
16760
17697
  }
16761
17698
  `;
16762
17699
  __decorateClass([
16763
- property46({ type: Boolean })
17700
+ property47({ type: Boolean })
16764
17701
  ], RelSwitch.prototype, "checked", 2);
16765
17702
  __decorateClass([
16766
- property46({ type: Boolean })
17703
+ property47({ type: Boolean })
16767
17704
  ], RelSwitch.prototype, "disabled", 2);
16768
17705
  __decorateClass([
16769
- property46({ type: String })
17706
+ property47({ type: String })
16770
17707
  ], RelSwitch.prototype, "value", 2);
16771
17708
  __decorateClass([
16772
17709
  state19()
@@ -16780,7 +17717,7 @@ RelSwitch = __decorateClass([
16780
17717
 
16781
17718
  // src/components/rel-tab/rel-tab.ts
16782
17719
  import { LitElement as LitElement53, html as html53, css as css50 } from "lit";
16783
- import { customElement as customElement53, property as property47, state as state20 } from "lit/decorators.js";
17720
+ import { customElement as customElement53, property as property48, state as state20 } from "lit/decorators.js";
16784
17721
  var RelTabItem = class extends LitElement53 {
16785
17722
  constructor() {
16786
17723
  super(...arguments);
@@ -16795,19 +17732,19 @@ var RelTabItem = class extends LitElement53 {
16795
17732
  }
16796
17733
  };
16797
17734
  __decorateClass([
16798
- property47({ type: String })
17735
+ property48({ type: String })
16799
17736
  ], RelTabItem.prototype, "label", 2);
16800
17737
  __decorateClass([
16801
- property47({ type: String })
17738
+ property48({ type: String })
16802
17739
  ], RelTabItem.prototype, "value", 2);
16803
17740
  __decorateClass([
16804
- property47({ type: Number })
17741
+ property48({ type: Number })
16805
17742
  ], RelTabItem.prototype, "badge", 2);
16806
17743
  __decorateClass([
16807
- property47({ type: Boolean, attribute: "badge-dot" })
17744
+ property48({ type: Boolean, attribute: "badge-dot" })
16808
17745
  ], RelTabItem.prototype, "badgeDot", 2);
16809
17746
  __decorateClass([
16810
- property47({ type: Boolean })
17747
+ property48({ type: Boolean })
16811
17748
  ], RelTabItem.prototype, "disabled", 2);
16812
17749
  RelTabItem = __decorateClass([
16813
17750
  customElement53("rel-tab-item")
@@ -16819,6 +17756,8 @@ var RelTab = class extends LitElement53 {
16819
17756
  this.activeIndex = 0;
16820
17757
  this.size = "md";
16821
17758
  this._tabItems = [];
17759
+ /** Stable id prefix linking tabs to the shared tabpanel. */
17760
+ this.tabsId = `rel-tab-${Math.random().toString(36).slice(2)}`;
16822
17761
  }
16823
17762
  _onSlotChange(e) {
16824
17763
  const slot = e.target;
@@ -16862,13 +17801,25 @@ var RelTab = class extends LitElement53 {
16862
17801
  next = (next + dir + tabs.length) % tabs.length;
16863
17802
  if (!tabs[next]?.disabled) break;
16864
17803
  }
16865
- this.selectTab(next);
16866
- this.updateComplete.then(() => {
16867
- const tabEls = this.shadowRoot?.querySelectorAll("[role=tab]");
16868
- tabEls?.[next]?.focus();
16869
- });
17804
+ this.selectAndFocusTab(next);
17805
+ return;
17806
+ }
17807
+ if (event.key === "Home" || event.key === "End") {
17808
+ event.preventDefault();
17809
+ const tabs = this._effectiveTabs;
17810
+ const order = [...tabs.keys()];
17811
+ if (event.key === "End") order.reverse();
17812
+ const next = order.find((i) => !tabs[i]?.disabled);
17813
+ if (next !== void 0) this.selectAndFocusTab(next);
16870
17814
  }
16871
17815
  }
17816
+ selectAndFocusTab(index) {
17817
+ this.selectTab(index);
17818
+ this.updateComplete.then(() => {
17819
+ const tabEls = this.shadowRoot?.querySelectorAll("[role=tab]");
17820
+ tabEls?.[index]?.focus();
17821
+ });
17822
+ }
16872
17823
  render() {
16873
17824
  const tabs = this._effectiveTabs;
16874
17825
  return html53`
@@ -16878,9 +17829,11 @@ var RelTab = class extends LitElement53 {
16878
17829
  (tab, i) => html53`
16879
17830
  <div
16880
17831
  part="item" class="tab ${i === this.activeIndex ? "active" : ""} ${tab.disabled ? "disabled" : ""}"
17832
+ id="${this.tabsId}-tab-${i}"
16881
17833
  role="tab"
16882
17834
  aria-selected="${i === this.activeIndex}"
16883
17835
  aria-disabled="${tab.disabled ?? false}"
17836
+ aria-controls="${this.tabsId}-panel"
16884
17837
  tabindex="${tab.disabled ? -1 : i === this.activeIndex ? 0 : -1}"
16885
17838
  @click="${() => this.selectTab(i)}"
16886
17839
  @keydown="${(e) => this.onKeyDown(e, i)}"
@@ -16892,7 +17845,13 @@ var RelTab = class extends LitElement53 {
16892
17845
  `
16893
17846
  )}
16894
17847
  </div>
16895
- <div class="tab-content">
17848
+ <div
17849
+ class="tab-content"
17850
+ id="${this.tabsId}-panel"
17851
+ role="tabpanel"
17852
+ aria-labelledby="${this.tabsId}-tab-${this.activeIndex}"
17853
+ tabindex="0"
17854
+ >
16896
17855
  <slot></slot>
16897
17856
  </div>
16898
17857
  `;
@@ -16923,7 +17882,6 @@ RelTab.styles = css50`
16923
17882
  padding: var(--rel-spacing-sm) var(--rel-spacing-md);
16924
17883
  cursor: pointer;
16925
17884
  color: var(--rel-text-body);
16926
-
16927
17885
  transition: color 0.2s ease;
16928
17886
  display: flex;
16929
17887
  align-items: center;
@@ -17012,13 +17970,13 @@ RelTab.styles = css50`
17012
17970
  }
17013
17971
  `;
17014
17972
  __decorateClass([
17015
- property47({ type: Array })
17973
+ property48({ type: Array })
17016
17974
  ], RelTab.prototype, "tabs", 2);
17017
17975
  __decorateClass([
17018
- property47({ type: Number, reflect: true })
17976
+ property48({ type: Number, reflect: true })
17019
17977
  ], RelTab.prototype, "activeIndex", 2);
17020
17978
  __decorateClass([
17021
- property47({ type: String, reflect: true })
17979
+ property48({ type: String, reflect: true })
17022
17980
  ], RelTab.prototype, "size", 2);
17023
17981
  __decorateClass([
17024
17982
  state20()
@@ -17028,8 +17986,8 @@ RelTab = __decorateClass([
17028
17986
  ], RelTab);
17029
17987
 
17030
17988
  // src/components/rel-time-picker/rel-time-picker.ts
17031
- import { LitElement as LitElement54, html as html54, css as css51, nothing as nothing11 } from "lit";
17032
- import { customElement as customElement54, property as property48, state as state21, query as query10 } from "lit/decorators.js";
17989
+ import { LitElement as LitElement54, html as html54, css as css51, nothing as nothing15 } from "lit";
17990
+ import { customElement as customElement54, property as property49, state as state21, query as query10 } from "lit/decorators.js";
17033
17991
  import "@reliability-design/icons/rel-icon";
17034
17992
  var RelTimePicker = class extends LitElement54 {
17035
17993
  constructor() {
@@ -17041,7 +17999,8 @@ var RelTimePicker = class extends LitElement54 {
17041
17999
  this.required = false;
17042
18000
  this.readonly = false;
17043
18001
  this.format = "12h";
17044
- this.minuteStep = 1;
18002
+ this.seconds = false;
18003
+ this.minuteStep = 5;
17045
18004
  this.minTime = null;
17046
18005
  this.maxTime = null;
17047
18006
  this.open = false;
@@ -17053,6 +18012,8 @@ var RelTimePicker = class extends LitElement54 {
17053
18012
  this.fullWidth = false;
17054
18013
  this.draftHour = null;
17055
18014
  this.draftMinute = null;
18015
+ this.draftSecond = null;
18016
+ this.openUp = false;
17056
18017
  this.handleClickOutside = (e) => {
17057
18018
  if (!this.open) return;
17058
18019
  const path = e.composedPath();
@@ -17077,40 +18038,58 @@ var RelTimePicker = class extends LitElement54 {
17077
18038
  document.removeEventListener("keydown", this.handleEscapeKey);
17078
18039
  }
17079
18040
  updated(changedProperties) {
17080
- if (changedProperties.has("open") && this.open) {
18041
+ if (changedProperties.has("open")) {
18042
+ if (!this.open) {
18043
+ this.openUp = false;
18044
+ return;
18045
+ }
17081
18046
  this.resetDraftFromValue();
17082
18047
  setTimeout(() => {
18048
+ this.updatePanelPlacement();
17083
18049
  this.scrollColumnsToSelection();
17084
18050
  const target = this.columnsElement?.querySelector(
17085
18051
  ".option-button.selected:not(:disabled)"
17086
18052
  ) ?? this.columnsElement?.querySelector(
17087
18053
  ".option-button:not(:disabled)"
17088
18054
  );
17089
- target?.focus();
18055
+ target?.focus({ preventScroll: true });
17090
18056
  }, 0);
17091
18057
  }
17092
18058
  }
18059
+ /** Open upward when the panel doesn't fit below but does fit above. */
18060
+ updatePanelPlacement() {
18061
+ const panel = this.renderRoot.querySelector(".popover");
18062
+ if (!panel) return;
18063
+ const rect = this.getBoundingClientRect();
18064
+ const panelHeight = panel.offsetHeight;
18065
+ const spaceBelow = window.innerHeight - rect.bottom;
18066
+ this.openUp = spaceBelow < panelHeight + 8 && rect.top > panelHeight + 8;
18067
+ }
17093
18068
  // ── Parsing / formatting ──
17094
18069
  parseTime(time) {
17095
18070
  if (!time) return null;
17096
- const match = time.match(/^(\d{1,2}):(\d{2})$/);
18071
+ const match = time.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
17097
18072
  if (!match) return null;
17098
18073
  const hour = parseInt(match[1], 10);
17099
18074
  const minute = parseInt(match[2], 10);
17100
- if (hour > 23 || minute > 59) return null;
17101
- return { hour, minute };
18075
+ const second = match[3] ? parseInt(match[3], 10) : 0;
18076
+ if (hour > 23 || minute > 59 || second > 59) return null;
18077
+ return { hour, minute, second };
17102
18078
  }
17103
- formatValue(hour, minute) {
17104
- return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
18079
+ formatValue(hour, minute, second = 0) {
18080
+ const hh = String(hour).padStart(2, "0");
18081
+ const mm = String(minute).padStart(2, "0");
18082
+ return this.seconds ? `${hh}:${mm}:${String(second).padStart(2, "0")}` : `${hh}:${mm}`;
17105
18083
  }
17106
- formatDisplay(hour, minute) {
18084
+ formatDisplay(hour, minute, second = 0) {
17107
18085
  const mm = String(minute).padStart(2, "0");
18086
+ const ss = this.seconds ? `:${String(second).padStart(2, "0")}` : "";
17108
18087
  if (this.format === "24h") {
17109
- return `${String(hour).padStart(2, "0")}:${mm}`;
18088
+ return `${String(hour).padStart(2, "0")}:${mm}${ss}`;
17110
18089
  }
17111
18090
  const period = hour < 12 ? "AM" : "PM";
17112
18091
  const hour12 = hour % 12 === 0 ? 12 : hour % 12;
17113
- return `${hour12}:${mm} ${period}`;
18092
+ return `${hour12}:${mm}${ss} ${period}`;
17114
18093
  }
17115
18094
  toMinutes(hour, minute) {
17116
18095
  return hour * 60 + minute;
@@ -17160,10 +18139,17 @@ var RelTimePicker = class extends LitElement54 {
17160
18139
  }
17161
18140
  const period = this.draftPeriod ?? "AM";
17162
18141
  const base = period === "AM" ? 0 : 12;
17163
- return Array.from({ length: 12 }, (_, i) => ({
17164
- label: i === 0 ? "12" : String(i).padStart(2, "0"),
17165
- hour24: base + i
17166
- }));
18142
+ return Array.from({ length: 12 }, (_, i) => {
18143
+ const display = i + 1;
18144
+ return {
18145
+ label: String(display).padStart(2, "0"),
18146
+ hour24: base + display % 12
18147
+ };
18148
+ });
18149
+ }
18150
+ /** Seconds shown in the seconds column (always step 1). */
18151
+ getSecondOptions() {
18152
+ return Array.from({ length: 60 }, (_, s) => s);
17167
18153
  }
17168
18154
  get draftPeriod() {
17169
18155
  if (this.draftHour === null) return null;
@@ -17173,6 +18159,7 @@ var RelTimePicker = class extends LitElement54 {
17173
18159
  const parsed = this.parseTime(this.value);
17174
18160
  this.draftHour = parsed ? parsed.hour : null;
17175
18161
  this.draftMinute = parsed ? parsed.minute : null;
18162
+ this.draftSecond = parsed ? parsed.second : null;
17176
18163
  }
17177
18164
  /** Snap the draft minute to the nearest valid step minute for the hour. */
17178
18165
  clampDraftToRange() {
@@ -17215,7 +18202,11 @@ var RelTimePicker = class extends LitElement54 {
17215
18202
  }
17216
18203
  applySelection() {
17217
18204
  if (this.draftHour === null) return;
17218
- const newValue = this.formatValue(this.draftHour, this.draftMinute ?? 0);
18205
+ const newValue = this.formatValue(
18206
+ this.draftHour,
18207
+ this.draftMinute ?? 0,
18208
+ this.draftSecond ?? 0
18209
+ );
17219
18210
  this.value = newValue;
17220
18211
  this.dispatchEvent(
17221
18212
  new CustomEvent("rel-change", {
@@ -17231,6 +18222,7 @@ var RelTimePicker = class extends LitElement54 {
17231
18222
  const now = /* @__PURE__ */ new Date();
17232
18223
  const step = this.minuteStepSafe;
17233
18224
  this.draftHour = now.getHours();
18225
+ this.draftSecond = this.seconds ? now.getSeconds() : null;
17234
18226
  this.draftMinute = Math.round(now.getMinutes() / step) * step;
17235
18227
  if (this.draftMinute >= 60) {
17236
18228
  this.draftMinute = 0;
@@ -17253,6 +18245,7 @@ var RelTimePicker = class extends LitElement54 {
17253
18245
  this.value = null;
17254
18246
  this.draftHour = null;
17255
18247
  this.draftMinute = null;
18248
+ this.draftSecond = null;
17256
18249
  this.dispatchEvent(
17257
18250
  new CustomEvent("rel-change", {
17258
18251
  detail: { value: null },
@@ -17281,6 +18274,20 @@ var RelTimePicker = class extends LitElement54 {
17281
18274
  if (!this.isTimeInRange(this.draftHour, minute)) return;
17282
18275
  this.draftMinute = minute;
17283
18276
  }
18277
+ selectSecond(second) {
18278
+ if (this.draftHour === null) {
18279
+ for (let h = 0; h < 24; h++) {
18280
+ if (this.isHourEnabled(h)) {
18281
+ this.draftHour = h;
18282
+ break;
18283
+ }
18284
+ }
18285
+ if (this.draftHour === null) return;
18286
+ }
18287
+ if (this.draftMinute === null) this.draftMinute = 0;
18288
+ this.draftSecond = second;
18289
+ this.clampDraftToRange();
18290
+ }
17284
18291
  selectPeriod(period) {
17285
18292
  if (!this.isPeriodEnabled(period)) return;
17286
18293
  const base = period === "AM" ? 0 : 12;
@@ -17298,9 +18305,27 @@ var RelTimePicker = class extends LitElement54 {
17298
18305
  this.clampDraftToRange();
17299
18306
  this.scrollColumnsToSelection();
17300
18307
  }
18308
+ /**
18309
+ * Scrolls the column's own scroll container only. scrollIntoView is off
18310
+ * limits here: it walks ALL scrollable ancestors, so it yanked the page
18311
+ * up/down whenever a column recentred (user-reported jump bug).
18312
+ */
18313
+ scrollOptionInColumn(btn, block) {
18314
+ const list = btn.parentElement;
18315
+ if (!list) return;
18316
+ const top = btn.offsetTop;
18317
+ const height = btn.offsetHeight;
18318
+ if (block === "center") {
18319
+ list.scrollTop = top - (list.clientHeight - height) / 2;
18320
+ } else if (top < list.scrollTop) {
18321
+ list.scrollTop = top;
18322
+ } else if (top + height > list.scrollTop + list.clientHeight) {
18323
+ list.scrollTop = top + height - list.clientHeight;
18324
+ }
18325
+ }
17301
18326
  scrollColumnsToSelection() {
17302
18327
  this.updateComplete.then(() => {
17303
- this.columnsElement?.querySelectorAll(".option-button.selected").forEach((btn) => btn.scrollIntoView({ block: "center" }));
18328
+ this.columnsElement?.querySelectorAll(".option-button.selected").forEach((btn) => this.scrollOptionInColumn(btn, "center"));
17304
18329
  });
17305
18330
  }
17306
18331
  // ── Keyboard ──
@@ -17357,19 +18382,23 @@ var RelTimePicker = class extends LitElement54 {
17357
18382
  }
17358
18383
  if (target && target !== buttons[index]) {
17359
18384
  target.click();
17360
- target.focus();
17361
- target.scrollIntoView({ block: "nearest" });
18385
+ target.focus({ preventScroll: true });
18386
+ this.scrollOptionInColumn(target, "nearest");
17362
18387
  }
17363
18388
  }
17364
18389
  focusAdjacentColumn(from, direction) {
17365
- const order = this.format === "12h" ? ["hour", "minute", "period"] : ["hour", "minute"];
18390
+ const order = ["hour", "minute"];
18391
+ if (this.seconds) order.push("second");
18392
+ if (this.format === "12h") order.push("period");
17366
18393
  const nextIndex = order.indexOf(from) + direction;
17367
18394
  if (nextIndex < 0 || nextIndex >= order.length) return;
17368
18395
  const lists = this.columnsElement?.querySelectorAll(".column-list");
17369
18396
  const list = lists?.[nextIndex];
17370
18397
  const target = list?.querySelector(".option-button.selected:not(:disabled)") ?? list?.querySelector(".option-button:not(:disabled)");
17371
- target?.focus();
17372
- target?.scrollIntoView({ block: "nearest" });
18398
+ if (target) {
18399
+ target.focus({ preventScroll: true });
18400
+ this.scrollOptionInColumn(target, "nearest");
18401
+ }
17373
18402
  }
17374
18403
  // ── Render ──
17375
18404
  render() {
@@ -17377,10 +18406,10 @@ var RelTimePicker = class extends LitElement54 {
17377
18406
  const belowText = isError && this.errorMessage ? this.errorMessage : this.helperText;
17378
18407
  const describedById = belowText ? "time-picker-desc" : void 0;
17379
18408
  const parsedValue = this.parseTime(this.value);
17380
- const displayText = parsedValue ? this.formatDisplay(parsedValue.hour, parsedValue.minute) : "";
17381
- const draftDisplay = this.draftHour !== null ? this.formatDisplay(this.draftHour, this.draftMinute ?? 0) : "";
18409
+ const displayText = parsedValue ? this.formatDisplay(parsedValue.hour, parsedValue.minute, parsedValue.second) : "";
17382
18410
  const hourOptions = this.getHourOptions();
17383
18411
  const minuteOptions = this.getMinuteOptions();
18412
+ const secondOptions = this.seconds ? this.getSecondOptions() : [];
17384
18413
  const draftPeriod = this.draftPeriod;
17385
18414
  const wrapperClasses = [
17386
18415
  "time-picker-wrapper",
@@ -17391,10 +18420,10 @@ var RelTimePicker = class extends LitElement54 {
17391
18420
  return html54`
17392
18421
  <div part="base" class="${wrapperClasses}">
17393
18422
  ${this.label ? html54`<label part="label" class="label" id="time-picker-label"
17394
- >${this.label}${this.required ? html54`<span class="required-mark" aria-hidden="true">*</span>` : nothing11}</label
17395
- >` : nothing11}
18423
+ >${this.label}${this.required ? html54`<span class="required-mark" aria-hidden="true">*</span>` : nothing15}</label
18424
+ >` : nothing15}
17396
18425
 
17397
- ${this.name ? html54`<input type="hidden" name=${this.name} .value=${this.value ?? ""} />` : nothing11}
18426
+ ${this.name ? html54`<input type="hidden" name=${this.name} .value=${this.value ?? ""} />` : nothing15}
17398
18427
 
17399
18428
  <button
17400
18429
  part="trigger"
@@ -17415,8 +18444,8 @@ var RelTimePicker = class extends LitElement54 {
17415
18444
  aria-required=${this.required}
17416
18445
  aria-invalid=${isError}
17417
18446
  aria-readonly=${this.readonly}
17418
- aria-describedby=${describedById ?? nothing11}
17419
- aria-labelledby=${this.label ? "time-picker-label" : nothing11}
18447
+ aria-describedby=${describedById ?? nothing15}
18448
+ aria-labelledby=${this.label ? "time-picker-label" : nothing15}
17420
18449
  >
17421
18450
  <span part="value" class="trigger-content ${displayText ? "" : "placeholder"}">
17422
18451
  ${displayText || this.placeholder}
@@ -17438,111 +18467,113 @@ var RelTimePicker = class extends LitElement54 {
17438
18467
  />
17439
18468
  </svg>
17440
18469
  </button>
17441
- ` : nothing11}
18470
+ ` : nothing15}
17442
18471
  <rel-icon part="icon" name="time-filled" size="sm"></rel-icon>
17443
18472
  </span>
17444
18473
  </button>
17445
18474
 
17446
18475
  <div
17447
18476
  part="panel"
17448
- class="popover ${this.open ? "open" : ""}"
18477
+ class="popover ${this.open ? "open" : ""} ${this.openUp ? "open-up" : ""}"
17449
18478
  role="dialog"
17450
18479
  aria-label="Choose time"
17451
18480
  >
17452
- <div class="time-readout">
17453
- <span class="time-readout-label">Time</span>
17454
- <span class="time-readout-value ${draftDisplay ? "" : "empty"}">
17455
- ${draftDisplay || (this.format === "24h" ? "--:--" : "--:-- --")}
17456
- </span>
17457
- </div>
17458
-
17459
18481
  <div class="columns">
17460
- <div class="column">
17461
- <div class="column-header" aria-hidden="true">Hour</div>
17462
- <div class="column-list" role="listbox" aria-label="Hours">
17463
- ${hourOptions.map(
18482
+ <div class="column-list" role="listbox" aria-label="Hours">
18483
+ ${hourOptions.map(
17464
18484
  (opt, i) => html54`
17465
- <button
17466
- part="option"
17467
- class="option-button ${this.draftHour === opt.hour24 ? "selected" : ""}"
17468
- type="button"
17469
- role="option"
17470
- aria-selected=${this.draftHour === opt.hour24}
17471
- ?disabled=${!this.isHourEnabled(opt.hour24)}
17472
- @click=${() => this.selectHour(opt.hour24)}
17473
- @keydown=${(e) => this.handleOptionKeydown(e, "hour")}
17474
- tabindex=${this.draftHour === opt.hour24 || this.draftHour === null && i === 0 ? 0 : -1}
17475
- >
17476
- ${opt.label}
17477
- </button>
17478
- `
18485
+ <button
18486
+ part="option"
18487
+ class="option-button ${this.draftHour === opt.hour24 ? "selected" : ""}"
18488
+ type="button"
18489
+ role="option"
18490
+ aria-selected=${this.draftHour === opt.hour24}
18491
+ ?disabled=${!this.isHourEnabled(opt.hour24)}
18492
+ @click=${() => this.selectHour(opt.hour24)}
18493
+ @keydown=${(e) => this.handleOptionKeydown(e, "hour")}
18494
+ tabindex=${this.draftHour === opt.hour24 || this.draftHour === null && i === 0 ? 0 : -1}
18495
+ >
18496
+ ${opt.label}
18497
+ </button>
18498
+ `
17479
18499
  )}
17480
- </div>
17481
18500
  </div>
17482
18501
 
17483
- <div class="column">
17484
- <div class="column-header" aria-hidden="true">Min</div>
17485
- <div class="column-list" role="listbox" aria-label="Minutes">
17486
- ${minuteOptions.map(
18502
+ <div class="column-divider" aria-hidden="true"></div>
18503
+
18504
+ <div class="column-list" role="listbox" aria-label="Minutes">
18505
+ ${minuteOptions.map(
17487
18506
  (m, i) => html54`
17488
- <button
17489
- part="option"
17490
- class="option-button ${this.draftMinute === m ? "selected" : ""}"
17491
- type="button"
17492
- role="option"
17493
- aria-selected=${this.draftMinute === m}
17494
- ?disabled=${this.draftHour !== null && !this.isTimeInRange(this.draftHour, m)}
17495
- @click=${() => this.selectMinute(m)}
17496
- @keydown=${(e) => this.handleOptionKeydown(e, "minute")}
17497
- tabindex=${this.draftMinute === m || this.draftMinute === null && i === 0 ? 0 : -1}
17498
- >
17499
- ${String(m).padStart(2, "0")}
17500
- </button>
17501
- `
18507
+ <button
18508
+ part="option"
18509
+ class="option-button ${this.draftMinute === m ? "selected" : ""}"
18510
+ type="button"
18511
+ role="option"
18512
+ aria-selected=${this.draftMinute === m}
18513
+ ?disabled=${this.draftHour !== null && !this.isTimeInRange(this.draftHour, m)}
18514
+ @click=${() => this.selectMinute(m)}
18515
+ @keydown=${(e) => this.handleOptionKeydown(e, "minute")}
18516
+ tabindex=${this.draftMinute === m || this.draftMinute === null && i === 0 ? 0 : -1}
18517
+ >
18518
+ ${String(m).padStart(2, "0")}
18519
+ </button>
18520
+ `
17502
18521
  )}
17503
- </div>
17504
18522
  </div>
17505
18523
 
18524
+ ${this.seconds ? html54`
18525
+ <div class="column-divider" aria-hidden="true"></div>
18526
+ <div class="column-list" role="listbox" aria-label="Seconds">
18527
+ ${secondOptions.map(
18528
+ (s, i) => html54`
18529
+ <button
18530
+ part="option"
18531
+ class="option-button ${this.draftSecond === s ? "selected" : ""}"
18532
+ type="button"
18533
+ role="option"
18534
+ aria-selected=${this.draftSecond === s}
18535
+ @click=${() => this.selectSecond(s)}
18536
+ @keydown=${(e) => this.handleOptionKeydown(e, "second")}
18537
+ tabindex=${this.draftSecond === s || this.draftSecond === null && i === 0 ? 0 : -1}
18538
+ >
18539
+ ${String(s).padStart(2, "0")}
18540
+ </button>
18541
+ `
18542
+ )}
18543
+ </div>
18544
+ ` : nothing15}
17506
18545
  ${this.format === "12h" ? html54`
17507
- <div class="column">
17508
- <div class="column-header" aria-hidden="true">AM/PM</div>
17509
- <div class="column-list" role="listbox" aria-label="AM or PM">
17510
- ${["AM", "PM"].map(
18546
+ <div class="column-divider" aria-hidden="true"></div>
18547
+ <div class="column-list" role="listbox" aria-label="AM or PM">
18548
+ ${["AM", "PM"].map(
17511
18549
  (p) => html54`
17512
- <button
17513
- part="option"
17514
- class="option-button ${draftPeriod === p ? "selected" : ""}"
17515
- type="button"
17516
- role="option"
17517
- aria-selected=${draftPeriod === p}
17518
- ?disabled=${!this.isPeriodEnabled(p)}
17519
- @click=${() => this.selectPeriod(p)}
17520
- @keydown=${(e) => this.handleOptionKeydown(e, "period")}
17521
- tabindex=${draftPeriod === p || draftPeriod === null && p === "AM" ? 0 : -1}
17522
- >
17523
- ${p}
17524
- </button>
17525
- `
18550
+ <button
18551
+ part="option"
18552
+ class="option-button ${draftPeriod === p ? "selected" : ""}"
18553
+ type="button"
18554
+ role="option"
18555
+ aria-selected=${draftPeriod === p}
18556
+ ?disabled=${!this.isPeriodEnabled(p)}
18557
+ @click=${() => this.selectPeriod(p)}
18558
+ @keydown=${(e) => this.handleOptionKeydown(e, "period")}
18559
+ tabindex=${draftPeriod === p || draftPeriod === null && p === "AM" ? 0 : -1}
18560
+ >
18561
+ ${p}
18562
+ </button>
18563
+ `
17526
18564
  )}
17527
- </div>
17528
18565
  </div>
17529
- ` : nothing11}
18566
+ ` : nothing15}
17530
18567
  </div>
17531
18568
 
17532
18569
  <div part="footer" class="time-footer">
17533
- <rel-button
17534
- variant="secondary"
17535
- size="small"
17536
- border="corner-radius"
17537
- @click=${() => this.selectNow()}
17538
- >
18570
+ <rel-button variant="link" size="small" @click=${() => this.selectNow()}>
17539
18571
  Now
17540
18572
  </rel-button>
17541
18573
  <div class="footer-right">
17542
18574
  <rel-button
17543
- variant="secondary"
18575
+ variant="ghost"
17544
18576
  size="small"
17545
- border="corner-radius"
17546
18577
  @click=${() => this.cancelPopover()}
17547
18578
  >
17548
18579
  Cancel
@@ -17551,11 +18582,10 @@ var RelTimePicker = class extends LitElement54 {
17551
18582
  variant="primary"
17552
18583
  tone="default"
17553
18584
  size="small"
17554
- border="corner-radius"
17555
18585
  ?disabled=${this.draftHour === null}
17556
18586
  @click=${() => this.applySelection()}
17557
18587
  >
17558
- Apply
18588
+ OK
17559
18589
  </rel-button>
17560
18590
  </div>
17561
18591
  </div>
@@ -17567,7 +18597,7 @@ var RelTimePicker = class extends LitElement54 {
17567
18597
  id=${describedById}
17568
18598
  >
17569
18599
  ${belowText}
17570
- </div>` : nothing11}
18600
+ </div>` : nothing15}
17571
18601
  </div>
17572
18602
  `;
17573
18603
  }
@@ -17739,16 +18769,19 @@ RelTimePicker.styles = css51`
17739
18769
  height: 16px;
17740
18770
  }
17741
18771
 
18772
+ /* Panel (Figma "Time Picker"): fixed width per size, full-bleed content. */
17742
18773
  .popover {
17743
18774
  position: absolute;
17744
18775
  top: calc(100% + 4px);
17745
18776
  left: 0;
17746
18777
  z-index: 1000;
17747
18778
  background: var(--rel-bg-surface);
17748
- border: 1px solid var(--rel-border-default);
18779
+ border: 1px solid var(--rel-border-subtle);
17749
18780
  border-radius: var(--rel-border-radius-sm);
17750
18781
  box-shadow: var(--rel-shadows-shadow-300);
17751
- padding: var(--rel-spacing-md);
18782
+ overflow: hidden;
18783
+ min-width: 220px;
18784
+ width: 250px;
17752
18785
  display: none;
17753
18786
  }
17754
18787
 
@@ -17756,94 +18789,79 @@ RelTimePicker.styles = css51`
17756
18789
  display: block;
17757
18790
  }
17758
18791
 
17759
- /* Draft readout (mirrors the range-picker FROM/TO block) */
17760
- .time-readout {
17761
- display: flex;
17762
- align-items: baseline;
17763
- gap: var(--rel-spacing-sm);
17764
- padding-bottom: var(--rel-spacing-sm);
17765
- margin-bottom: var(--rel-spacing-sm);
17766
- border-bottom: 1px solid var(--rel-border-subtle);
17767
- }
17768
-
17769
- .time-readout-label {
17770
- color: var(--rel-text-placeholder);
17771
- text-transform: uppercase;
17772
- font-family: var(--rel-body-xs-semibold-font-family);
17773
- font-weight: var(--rel-body-xs-semibold-font-weight);
17774
- font-size: var(--rel-body-xs-semibold-font-size);
17775
- line-height: var(--rel-body-xs-semibold-line-height);
17776
- letter-spacing: var(--rel-body-xs-semibold-letter-spacing);
17777
- }
17778
-
17779
- .time-readout-value {
17780
- color: var(--rel-text-default);
17781
- font-family: var(--rel-body-md-semibold-font-family);
17782
- font-weight: var(--rel-body-md-semibold-font-weight);
17783
- font-size: var(--rel-body-md-semibold-font-size);
17784
- line-height: var(--rel-body-md-semibold-line-height);
17785
- letter-spacing: var(--rel-body-md-semibold-letter-spacing);
17786
- }
17787
-
17788
- .time-readout-value.empty {
17789
- color: var(--rel-text-placeholder);
18792
+ /* Flip above the field when the viewport has no room below. */
18793
+ .popover.open-up {
18794
+ top: auto;
18795
+ bottom: calc(100% + 4px);
17790
18796
  }
17791
18797
 
18798
+ /* Full-bleed column row with 1px dividers (Figma "Columns"). */
17792
18799
  .columns {
17793
18800
  display: flex;
17794
- gap: var(--rel-spacing-xs);
17795
- }
17796
-
17797
- /* Columns share the panel width equally, so the two-column 24h layout
17798
- fills the same footprint the footer dictates instead of bunching left. */
17799
- .column {
17800
- display: flex;
17801
- flex-direction: column;
17802
- flex: 1;
17803
- min-width: 64px;
18801
+ align-items: stretch;
18802
+ height: 260px;
17804
18803
  }
17805
18804
 
17806
- .column-header {
17807
- text-align: center;
17808
- color: var(--rel-text-placeholder);
17809
- padding: var(--rel-spacing-xs);
17810
- text-transform: uppercase;
17811
- font-family: var(--rel-body-xs-semibold-font-family);
17812
- font-weight: var(--rel-body-xs-semibold-font-weight);
17813
- font-size: var(--rel-body-xs-semibold-font-size);
17814
- line-height: var(--rel-body-xs-semibold-line-height);
17815
- letter-spacing: var(--rel-body-xs-semibold-letter-spacing);
18805
+ .column-divider {
18806
+ flex-shrink: 0;
18807
+ width: 1px;
18808
+ background: var(--rel-border-subtle);
17816
18809
  }
17817
18810
 
18811
+ /* Each column scrolls independently. The 4px rail is always reserved
18812
+ (scrollbar-gutter) so columns stay aligned whether or not they
18813
+ overflow; the thumb only appears on overflow. */
17818
18814
  .column-list {
18815
+ flex: 1;
18816
+ min-width: 0;
17819
18817
  display: flex;
17820
18818
  flex-direction: column;
17821
- gap: var(--rel-spacing-3xs);
17822
- max-height: 224px;
18819
+ /* Positioned so option offsetTop is list-relative — the in-column
18820
+ scroll math depends on it (we never scrollIntoView: it scrolls every
18821
+ ancestor, page included). */
18822
+ position: relative;
17823
18823
  overflow-y: auto;
17824
- padding: var(--rel-spacing-3xs);
18824
+ padding: var(--rel-spacing-2xs);
17825
18825
  scrollbar-width: thin;
18826
+ scrollbar-color: var(--rel-border-default) transparent;
18827
+ scrollbar-gutter: stable;
18828
+ }
18829
+
18830
+ .column-list::-webkit-scrollbar {
18831
+ width: 4px;
18832
+ }
18833
+
18834
+ .column-list::-webkit-scrollbar-track {
18835
+ background: transparent;
18836
+ }
18837
+
18838
+ .column-list::-webkit-scrollbar-thumb {
18839
+ background: var(--rel-border-default);
18840
+ border-radius: var(--rel-border-radius-full-rounded);
17826
18841
  }
17827
18842
 
18843
+ /* Option cell (Figma ".Time Option"): selected uses the neutral
18844
+ elevated-2 fill + medium weight, NOT the brand color. */
17828
18845
  .option-button {
17829
18846
  border: none;
17830
18847
  background: transparent;
17831
- border-radius: var(--rel-border-radius-sm);
18848
+ border-radius: var(--rel-border-radius-xs);
17832
18849
  color: var(--rel-text-default);
17833
18850
  cursor: pointer;
17834
- padding: var(--rel-spacing-xs) var(--rel-spacing-sm);
17835
- text-align: center;
17836
18851
  flex-shrink: 0;
17837
- transition: all 0.15s ease;
17838
- font-family: var(--rel-body-sm-medium-font-family);
17839
- font-weight: var(--rel-body-sm-medium-font-weight);
17840
- font-size: var(--rel-body-sm-medium-font-size);
17841
- line-height: var(--rel-body-sm-medium-line-height);
17842
- letter-spacing: var(--rel-body-sm-medium-letter-spacing);
18852
+ height: 36px;
18853
+ padding: 0 var(--rel-spacing-xs);
18854
+ text-align: center;
18855
+ transition: background 0.15s ease;
18856
+ font-family: var(--rel-body-md-regular-font-family);
18857
+ font-weight: var(--rel-body-md-regular-font-weight);
18858
+ font-size: var(--rel-body-md-regular-font-size);
18859
+ line-height: var(--rel-body-md-regular-line-height);
18860
+ letter-spacing: var(--rel-body-md-regular-letter-spacing);
17843
18861
  }
17844
18862
 
17845
18863
  .option-button:hover:not(:disabled):not(.selected) {
17846
- background: var(--rel-bg-surface-elevated);
18864
+ background: var(--rel-bg-neutral-elevated-1);
17847
18865
  }
17848
18866
 
17849
18867
  .option-button:focus-visible {
@@ -17853,9 +18871,9 @@ RelTimePicker.styles = css51`
17853
18871
  }
17854
18872
 
17855
18873
  .option-button.selected {
17856
- background: var(--rel-action-brand-fill);
17857
- color: var(--rel-action-brand-label-icons-primary);
17858
- font-weight: var(--rel-body-md-semibold-font-weight);
18874
+ background: var(--rel-bg-neutral-elevated-2);
18875
+ color: var(--rel-text-default);
18876
+ font-weight: var(--rel-body-md-medium-font-weight);
17859
18877
  }
17860
18878
 
17861
18879
  .option-button:disabled {
@@ -17868,14 +18886,15 @@ RelTimePicker.styles = css51`
17868
18886
  background: transparent;
17869
18887
  }
17870
18888
 
17871
- /* Footer (mirrors the range-picker calendar-footer) */
18889
+ /* Footer (Figma "Footer"): 8px padding + 8px extra left so the "Now"
18890
+ link aligns with the buttons' inner padding. Buttons are always S. */
17872
18891
  .time-footer {
17873
18892
  display: flex;
17874
18893
  align-items: center;
17875
18894
  justify-content: space-between;
17876
- gap: var(--rel-spacing-sm);
17877
- padding-top: var(--rel-spacing-sm);
17878
- margin-top: var(--rel-spacing-sm);
18895
+ gap: var(--rel-spacing-xs);
18896
+ padding: var(--rel-spacing-xs);
18897
+ padding-left: calc(var(--rel-spacing-xs) * 2);
17879
18898
  border-top: 1px solid var(--rel-border-subtle);
17880
18899
  }
17881
18900
 
@@ -17885,6 +18904,56 @@ RelTimePicker.styles = css51`
17885
18904
  gap: var(--rel-spacing-xs);
17886
18905
  }
17887
18906
 
18907
+ /* The design narrows OK below the DS small min-width (60 vs 80) so the
18908
+ compact footer fits the 220px panel. */
18909
+ .footer-right rel-button[variant="primary"] {
18910
+ --rel-button-min-width: 60px;
18911
+ }
18912
+
18913
+ /* Panel size variants (Figma S/M/L): width 220/250/280, option height
18914
+ 32/36/40, body-sm/md/lg type. Medium is the base above. */
18915
+ .time-picker-wrapper.small .popover {
18916
+ width: 220px;
18917
+ }
18918
+
18919
+ .time-picker-wrapper.small .columns {
18920
+ height: 232px;
18921
+ }
18922
+
18923
+ .time-picker-wrapper.small .option-button {
18924
+ height: 32px;
18925
+ font-family: var(--rel-body-sm-regular-font-family);
18926
+ font-weight: var(--rel-body-sm-regular-font-weight);
18927
+ font-size: var(--rel-body-sm-regular-font-size);
18928
+ line-height: var(--rel-body-sm-regular-line-height);
18929
+ letter-spacing: var(--rel-body-sm-regular-letter-spacing);
18930
+ }
18931
+
18932
+ .time-picker-wrapper.small .option-button.selected {
18933
+ font-weight: var(--rel-body-sm-medium-font-weight);
18934
+ }
18935
+
18936
+ .time-picker-wrapper.large .popover {
18937
+ width: 280px;
18938
+ }
18939
+
18940
+ .time-picker-wrapper.large .columns {
18941
+ height: 288px;
18942
+ }
18943
+
18944
+ .time-picker-wrapper.large .option-button {
18945
+ height: 40px;
18946
+ font-family: var(--rel-body-lg-regular-font-family);
18947
+ font-weight: var(--rel-body-lg-regular-font-weight);
18948
+ font-size: var(--rel-body-lg-regular-font-size);
18949
+ line-height: var(--rel-body-lg-regular-line-height);
18950
+ letter-spacing: var(--rel-body-lg-regular-letter-spacing);
18951
+ }
18952
+
18953
+ .time-picker-wrapper.large .option-button.selected {
18954
+ font-weight: var(--rel-body-lg-medium-font-weight);
18955
+ }
18956
+
17888
18957
  @media (prefers-reduced-motion: reduce) {
17889
18958
  .trigger-button,
17890
18959
  .icon-button,
@@ -17894,64 +18963,67 @@ RelTimePicker.styles = css51`
17894
18963
  }
17895
18964
  `;
17896
18965
  __decorateClass([
17897
- property48({ type: String, reflect: true })
18966
+ property49({ type: String, reflect: true })
17898
18967
  ], RelTimePicker.prototype, "value", 2);
17899
18968
  __decorateClass([
17900
- property48({ type: String })
18969
+ property49({ type: String })
17901
18970
  ], RelTimePicker.prototype, "placeholder", 2);
17902
18971
  __decorateClass([
17903
- property48({ type: String })
18972
+ property49({ type: String })
17904
18973
  ], RelTimePicker.prototype, "label", 2);
17905
18974
  __decorateClass([
17906
- property48({ type: Boolean, reflect: true })
18975
+ property49({ type: Boolean, reflect: true })
17907
18976
  ], RelTimePicker.prototype, "disabled", 2);
17908
18977
  __decorateClass([
17909
- property48({ type: Boolean })
18978
+ property49({ type: Boolean })
17910
18979
  ], RelTimePicker.prototype, "required", 2);
17911
18980
  __decorateClass([
17912
- property48({ type: Boolean, reflect: true })
18981
+ property49({ type: Boolean, reflect: true })
17913
18982
  ], RelTimePicker.prototype, "readonly", 2);
17914
18983
  __decorateClass([
17915
- property48({ type: String })
18984
+ property49({ type: String })
17916
18985
  ], RelTimePicker.prototype, "format", 2);
17917
18986
  __decorateClass([
17918
- property48({ type: Number, attribute: "minute-step" })
18987
+ property49({ type: Boolean, reflect: true })
18988
+ ], RelTimePicker.prototype, "seconds", 2);
18989
+ __decorateClass([
18990
+ property49({ type: Number, attribute: "minute-step" })
17919
18991
  ], RelTimePicker.prototype, "minuteStep", 2);
17920
18992
  __decorateClass([
17921
- property48({ type: String, attribute: "min-time" })
18993
+ property49({ type: String, attribute: "min-time" })
17922
18994
  ], RelTimePicker.prototype, "minTime", 2);
17923
18995
  __decorateClass([
17924
- property48({ type: String, attribute: "max-time" })
18996
+ property49({ type: String, attribute: "max-time" })
17925
18997
  ], RelTimePicker.prototype, "maxTime", 2);
17926
18998
  __decorateClass([
17927
- property48({ type: Boolean, reflect: true })
18999
+ property49({ type: Boolean, reflect: true })
17928
19000
  ], RelTimePicker.prototype, "open", 2);
17929
19001
  __decorateClass([
17930
- property48({ type: Boolean })
19002
+ property49({ type: Boolean })
17931
19003
  ], RelTimePicker.prototype, "clearable", 2);
17932
19004
  __decorateClass([
17933
- property48({ type: Boolean })
19005
+ property49({ type: Boolean })
17934
19006
  ], RelTimePicker.prototype, "error", 2);
17935
19007
  __decorateClass([
17936
- property48({ type: Boolean })
19008
+ property49({ type: Boolean })
17937
19009
  ], RelTimePicker.prototype, "invalid", 2);
17938
19010
  __decorateClass([
17939
- property48({ type: String, attribute: "error-message" })
19011
+ property49({ type: String, attribute: "error-message" })
17940
19012
  ], RelTimePicker.prototype, "errorMessage", 2);
17941
19013
  __decorateClass([
17942
- property48({ type: String, attribute: "helper-text" })
19014
+ property49({ type: String, attribute: "helper-text" })
17943
19015
  ], RelTimePicker.prototype, "helperText", 2);
17944
19016
  __decorateClass([
17945
- property48({ type: String })
19017
+ property49({ type: String })
17946
19018
  ], RelTimePicker.prototype, "name", 2);
17947
19019
  __decorateClass([
17948
- property48({ type: String })
19020
+ property49({ type: String })
17949
19021
  ], RelTimePicker.prototype, "size", 2);
17950
19022
  __decorateClass([
17951
- property48({ type: String, reflect: true })
19023
+ property49({ type: String, reflect: true })
17952
19024
  ], RelTimePicker.prototype, "variant", 2);
17953
19025
  __decorateClass([
17954
- property48({ type: Boolean, reflect: true })
19026
+ property49({ type: Boolean, reflect: true })
17955
19027
  ], RelTimePicker.prototype, "fullWidth", 2);
17956
19028
  __decorateClass([
17957
19029
  state21()
@@ -17959,6 +19031,12 @@ __decorateClass([
17959
19031
  __decorateClass([
17960
19032
  state21()
17961
19033
  ], RelTimePicker.prototype, "draftMinute", 2);
19034
+ __decorateClass([
19035
+ state21()
19036
+ ], RelTimePicker.prototype, "draftSecond", 2);
19037
+ __decorateClass([
19038
+ state21()
19039
+ ], RelTimePicker.prototype, "openUp", 2);
17962
19040
  __decorateClass([
17963
19041
  query10(".trigger-button")
17964
19042
  ], RelTimePicker.prototype, "triggerButton", 2);
@@ -17971,7 +19049,7 @@ RelTimePicker = __decorateClass([
17971
19049
 
17972
19050
  // src/components/rel-toast/rel-toast.ts
17973
19051
  import { LitElement as LitElement55, html as html55, css as css52 } from "lit";
17974
- import { customElement as customElement55, property as property49, state as state22 } from "lit/decorators.js";
19052
+ import { customElement as customElement55, property as property50, state as state22 } from "lit/decorators.js";
17975
19053
  var RelToast = class extends LitElement55 {
17976
19054
  constructor() {
17977
19055
  super(...arguments);
@@ -18164,19 +19242,19 @@ RelToast.styles = css52`
18164
19242
  }
18165
19243
  `;
18166
19244
  __decorateClass([
18167
- property49({ type: String })
19245
+ property50({ type: String })
18168
19246
  ], RelToast.prototype, "message", 2);
18169
19247
  __decorateClass([
18170
- property49({ type: String })
19248
+ property50({ type: String })
18171
19249
  ], RelToast.prototype, "type", 2);
18172
19250
  __decorateClass([
18173
- property49({ type: String })
19251
+ property50({ type: String })
18174
19252
  ], RelToast.prototype, "actionLabel", 2);
18175
19253
  __decorateClass([
18176
- property49({ type: Number })
19254
+ property50({ type: Number })
18177
19255
  ], RelToast.prototype, "duration", 2);
18178
19256
  __decorateClass([
18179
- property49({ type: Boolean, reflect: true })
19257
+ property50({ type: Boolean, reflect: true })
18180
19258
  ], RelToast.prototype, "show", 2);
18181
19259
  __decorateClass([
18182
19260
  state22()
@@ -18187,7 +19265,7 @@ RelToast = __decorateClass([
18187
19265
 
18188
19266
  // src/components/rel-tooltip/rel-tooltip.ts
18189
19267
  import { LitElement as LitElement56, html as html56, css as css53 } from "lit";
18190
- import { customElement as customElement56, property as property50 } from "lit/decorators.js";
19268
+ import { customElement as customElement56, property as property51 } from "lit/decorators.js";
18191
19269
  var RelTooltip = class extends LitElement56 {
18192
19270
  constructor() {
18193
19271
  super(...arguments);
@@ -18197,6 +19275,26 @@ var RelTooltip = class extends LitElement56 {
18197
19275
  this.type = "single-line";
18198
19276
  // Stable id so aria-describedby can reference the bubble across renders.
18199
19277
  this.uniqueId = Math.random().toString(36).slice(2);
19278
+ /** APG: Escape dismisses the tooltip. Not swallowed — an enclosing dialog
19279
+ * may legitimately close on the same keystroke. */
19280
+ this.onKeydown = (e) => {
19281
+ if (e.key === "Escape") this.toggleAttribute("data-dismissed", true);
19282
+ };
19283
+ this.clearDismissed = () => {
19284
+ this.removeAttribute("data-dismissed");
19285
+ };
19286
+ }
19287
+ connectedCallback() {
19288
+ super.connectedCallback();
19289
+ this.addEventListener("keydown", this.onKeydown);
19290
+ this.addEventListener("mouseleave", this.clearDismissed);
19291
+ this.addEventListener("focusout", this.clearDismissed);
19292
+ }
19293
+ disconnectedCallback() {
19294
+ super.disconnectedCallback();
19295
+ this.removeEventListener("keydown", this.onKeydown);
19296
+ this.removeEventListener("mouseleave", this.clearDismissed);
19297
+ this.removeEventListener("focusout", this.clearDismissed);
18200
19298
  }
18201
19299
  firstUpdated() {
18202
19300
  this.linkTrigger();
@@ -18263,6 +19361,12 @@ RelTooltip.styles = css53`
18263
19361
  opacity: 1;
18264
19362
  }
18265
19363
 
19364
+ /* Escape-dismissed (APG): stays hidden until hover/focus leaves and
19365
+ returns. Declared after the hover/focus rules so source order wins. */
19366
+ :host([data-dismissed]) .tooltip-bubble {
19367
+ opacity: 0;
19368
+ }
19369
+
18266
19370
  /* Positioning */
18267
19371
  .tooltip-bubble.above {
18268
19372
  bottom: calc(100% + 6px);
@@ -18337,24 +19441,24 @@ RelTooltip.styles = css53`
18337
19441
  }
18338
19442
  `;
18339
19443
  __decorateClass([
18340
- property50({ type: String })
19444
+ property51({ type: String })
18341
19445
  ], RelTooltip.prototype, "text", 2);
18342
19446
  __decorateClass([
18343
- property50({ type: String })
19447
+ property51({ type: String })
18344
19448
  ], RelTooltip.prototype, "position", 2);
18345
19449
  __decorateClass([
18346
- property50({ type: Boolean, attribute: "show-tail" })
19450
+ property51({ type: Boolean, attribute: "show-tail" })
18347
19451
  ], RelTooltip.prototype, "showTail", 2);
18348
19452
  __decorateClass([
18349
- property50({ type: String, reflect: true })
19453
+ property51({ type: String, reflect: true })
18350
19454
  ], RelTooltip.prototype, "type", 2);
18351
19455
  RelTooltip = __decorateClass([
18352
19456
  customElement56("rel-tooltip")
18353
19457
  ], RelTooltip);
18354
19458
 
18355
19459
  // src/components/rel-upload/rel-upload.ts
18356
- import { LitElement as LitElement57, html as html57, css as css54, nothing as nothing12 } from "lit";
18357
- import { customElement as customElement57, property as property51, state as state23, query as query11 } from "lit/decorators.js";
19460
+ import { LitElement as LitElement57, html as html57, css as css54, nothing as nothing16 } from "lit";
19461
+ import { customElement as customElement57, property as property52, state as state23, query as query11 } from "lit/decorators.js";
18358
19462
  import "@reliability-design/icons/rel-icon";
18359
19463
  var uid = 0;
18360
19464
  var RelUpload = class extends LitElement57 {
@@ -18751,7 +19855,7 @@ var RelUpload = class extends LitElement57 {
18751
19855
  ${f.status === "uploading" ? html57`<rel-progress
18752
19856
  mode="linear-determinate"
18753
19857
  .value=${f.progress ?? 0}
18754
- ></rel-progress>` : nothing12}
19858
+ ></rel-progress>` : nothing16}
18755
19859
  <span class="row-meta">${this.rowMeta(f)}</span>
18756
19860
  </div>
18757
19861
 
@@ -18762,14 +19866,14 @@ var RelUpload = class extends LitElement57 {
18762
19866
  size="md"
18763
19867
  role="img"
18764
19868
  aria-label="Uploaded"
18765
- ></rel-icon>` : nothing12}
19869
+ ></rel-icon>` : nothing16}
18766
19870
  ${f.status === "error" ? html57`<rel-icon
18767
19871
  class="status-error"
18768
19872
  name="error"
18769
19873
  size="md"
18770
19874
  role="img"
18771
19875
  aria-label="Failed"
18772
- ></rel-icon>` : nothing12}
19876
+ ></rel-icon>` : nothing16}
18773
19877
  <button
18774
19878
  class="remove"
18775
19879
  aria-label="Remove ${f.name}"
@@ -18791,7 +19895,7 @@ var RelUpload = class extends LitElement57 {
18791
19895
  appearance="subtle"
18792
19896
  message1=${alert.message1}
18793
19897
  message2=${alert.message2}
18794
- ></rel-alert>` : nothing12}
19898
+ ></rel-alert>` : nothing16}
18795
19899
 
18796
19900
  <div
18797
19901
  class="dropzone ${this.dragOver ? "dragover" : ""}"
@@ -18825,13 +19929,13 @@ var RelUpload = class extends LitElement57 {
18825
19929
  ${this.files.length ? html57`<div class="file-list">
18826
19930
  <p class="list-heading">${this.listHeading}</p>
18827
19931
  <div class="rows" role="list">${this.files.map((f) => this.renderRow(f))}</div>
18828
- </div>` : nothing12}
19932
+ </div>` : nothing16}
18829
19933
 
18830
19934
  <input
18831
19935
  class="file-input"
18832
19936
  type="file"
18833
19937
  ?multiple=${this.multiple}
18834
- accept=${this.accept || nothing12}
19938
+ accept=${this.accept || nothing16}
18835
19939
  @change=${this.onInputChange}
18836
19940
  />
18837
19941
  </div>
@@ -19087,37 +20191,37 @@ RelUpload.styles = css54`
19087
20191
  }
19088
20192
  `;
19089
20193
  __decorateClass([
19090
- property51({ type: String })
20194
+ property52({ type: String })
19091
20195
  ], RelUpload.prototype, "accept", 2);
19092
20196
  __decorateClass([
19093
- property51({ type: String, attribute: "max-size" })
20197
+ property52({ type: String, attribute: "max-size" })
19094
20198
  ], RelUpload.prototype, "maxSize", 2);
19095
20199
  __decorateClass([
19096
- property51({ type: Boolean })
20200
+ property52({ type: Boolean })
19097
20201
  ], RelUpload.prototype, "multiple", 2);
19098
20202
  __decorateClass([
19099
- property51({ type: Boolean, reflect: true })
20203
+ property52({ type: Boolean, reflect: true })
19100
20204
  ], RelUpload.prototype, "disabled", 2);
19101
20205
  __decorateClass([
19102
- property51({ type: String })
20206
+ property52({ type: String })
19103
20207
  ], RelUpload.prototype, "hint", 2);
19104
20208
  __decorateClass([
19105
- property51({ type: String, attribute: "dropzone-title" })
20209
+ property52({ type: String, attribute: "dropzone-title" })
19106
20210
  ], RelUpload.prototype, "dropzoneTitle", 2);
19107
20211
  __decorateClass([
19108
- property51({ type: String, attribute: "browse-label" })
20212
+ property52({ type: String, attribute: "browse-label" })
19109
20213
  ], RelUpload.prototype, "browseLabel", 2);
19110
20214
  __decorateClass([
19111
- property51({ attribute: false })
20215
+ property52({ attribute: false })
19112
20216
  ], RelUpload.prototype, "files", 2);
19113
20217
  __decorateClass([
19114
- property51({ attribute: false })
20218
+ property52({ attribute: false })
19115
20219
  ], RelUpload.prototype, "uploader", 2);
19116
20220
  __decorateClass([
19117
- property51({ type: Number })
20221
+ property52({ type: Number })
19118
20222
  ], RelUpload.prototype, "concurrency", 2);
19119
20223
  __decorateClass([
19120
- property51({ type: Number, attribute: "delay-threshold" })
20224
+ property52({ type: Number, attribute: "delay-threshold" })
19121
20225
  ], RelUpload.prototype, "delayThreshold", 2);
19122
20226
  __decorateClass([
19123
20227
  state23()
@@ -19133,8 +20237,8 @@ RelUpload = __decorateClass([
19133
20237
  ], RelUpload);
19134
20238
 
19135
20239
  // src/components/rel-upload/rel-upload-actions.ts
19136
- import { LitElement as LitElement58, html as html58, css as css55, nothing as nothing13 } from "lit";
19137
- import { customElement as customElement58, property as property52, state as state24 } from "lit/decorators.js";
20240
+ import { LitElement as LitElement58, html as html58, css as css55, nothing as nothing17 } from "lit";
20241
+ import { customElement as customElement58, property as property53, state as state24 } from "lit/decorators.js";
19138
20242
  import "@reliability-design/icons/rel-icon";
19139
20243
  var EMPTY_STATE = {
19140
20244
  phase: "empty",
@@ -19204,7 +20308,7 @@ var RelUploadActions = class extends LitElement58 {
19204
20308
  const busy = phase === "uploading" || phase === "delayed";
19205
20309
  return html58`
19206
20310
  <div class="actions" part="base">
19207
- ${this.noCancel ? nothing13 : html58`<rel-button part="cancel" variant="secondary" @click=${this.onCancel}>
20311
+ ${this.noCancel ? nothing17 : html58`<rel-button part="cancel" variant="secondary" @click=${this.onCancel}>
19208
20312
  ${this.cancelLabel}
19209
20313
  </rel-button>`}
19210
20314
 
@@ -19216,7 +20320,7 @@ var RelUploadActions = class extends LitElement58 {
19216
20320
  aria-label=${busy ? "Uploading" : primaryLabel}
19217
20321
  @click=${this.onPrimary}
19218
20322
  >
19219
- ${busy ? nothing13 : html58`${phase === "failed" ? html58`<rel-icon name="refresh" size="sm"></rel-icon>` : nothing13}${primaryLabel}`}
20323
+ ${busy ? nothing17 : html58`${phase === "failed" ? html58`<rel-icon name="refresh" size="sm"></rel-icon>` : nothing17}${primaryLabel}`}
19220
20324
  </rel-button>
19221
20325
  </div>
19222
20326
  `;
@@ -19240,13 +20344,13 @@ RelUploadActions.styles = css55`
19240
20344
  }
19241
20345
  `;
19242
20346
  __decorateClass([
19243
- property52({ type: String })
20347
+ property53({ type: String })
19244
20348
  ], RelUploadActions.prototype, "for", 2);
19245
20349
  __decorateClass([
19246
- property52({ type: String, attribute: "cancel-label" })
20350
+ property53({ type: String, attribute: "cancel-label" })
19247
20351
  ], RelUploadActions.prototype, "cancelLabel", 2);
19248
20352
  __decorateClass([
19249
- property52({ type: Boolean, attribute: "no-cancel" })
20353
+ property53({ type: Boolean, attribute: "no-cancel" })
19250
20354
  ], RelUploadActions.prototype, "noCancel", 2);
19251
20355
  __decorateClass([
19252
20356
  state24()
@@ -19258,6 +20362,7 @@ RelUploadActions = __decorateClass([
19258
20362
  // src/index.ts
19259
20363
  export * from "@reliability-design/icons";
19260
20364
  export {
20365
+ FocusTrap,
19261
20366
  RelAccordion,
19262
20367
  RelAlert,
19263
20368
  RelAutocomplete,
@@ -19318,6 +20423,15 @@ export {
19318
20423
  RelTopbarProfile,
19319
20424
  RelTopbarUtilities,
19320
20425
  RelUpload,
19321
- RelUploadActions
20426
+ RelUploadActions,
20427
+ bindShortcut,
20428
+ formatShortcutParts,
20429
+ getDeepActiveElement,
20430
+ getFocusableElements,
20431
+ isApplePlatform,
20432
+ isEditableTarget,
20433
+ matchesShortcut,
20434
+ parseShortcut,
20435
+ trapTabKey
19322
20436
  };
19323
20437
  //# sourceMappingURL=index.mjs.map