@reliability-design/web 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -14,6 +14,7 @@ import "./vars-I2PC74XD.css";
14
14
 
15
15
  // src/components/rel-accordion/rel-accordion.ts
16
16
  import "./vars-v2-VMGWTFJZ.css";
17
+ import "@reliability-design/icons/rel-icon";
17
18
  import { LitElement, html, css } from "lit";
18
19
  import { customElement, property } from "lit/decorators.js";
19
20
  var RelAccordion = class extends LitElement {
@@ -21,6 +22,8 @@ var RelAccordion = class extends LitElement {
21
22
  super(...arguments);
22
23
  this.title = "Accordion";
23
24
  this.open = false;
25
+ this.size = "md";
26
+ this.type = "default";
24
27
  }
25
28
  toggle() {
26
29
  this.open = !this.open;
@@ -32,13 +35,6 @@ var RelAccordion = class extends LitElement {
32
35
  })
33
36
  );
34
37
  }
35
- chevron() {
36
- return html`
37
- <svg viewBox="0 0 24 24">
38
- <polyline points="6 9 12 15 18 9"></polyline>
39
- </svg>
40
- `;
41
- }
42
38
  render() {
43
39
  return html`
44
40
  <div class="accordion">
@@ -55,12 +51,20 @@ var RelAccordion = class extends LitElement {
55
51
  }
56
52
  }}
57
53
  >
58
- <div class="title">${this.title}</div>
59
- <div class="icon ${this.open ? "rotated" : ""}">
60
- ${this.chevron()}
54
+ <div class="title-row">
55
+ ${this.type === "action" ? html`<span class="leading-icon">
56
+ <slot name="icon">
57
+ <span class="icon-rotate-on-open"><rel-icon name="chevron-right"></rel-icon></span>
58
+ </slot>
59
+ </span>` : ""}
60
+ <span class="title">${this.title}</span>
61
+ </div>
62
+ <div class="chevron">
63
+ <slot name="trailing-icon">
64
+ ${this.type === "default" ? html`<span class="chevron-rotate"><rel-icon name="chevron-down"></rel-icon></span>` : html`<rel-icon name="arrow-expansion"></rel-icon>`}
65
+ </slot>
61
66
  </div>
62
67
  </div>
63
- <!-- IMPORTANT: slot is ALWAYS rendered -->
64
68
  <div class="body ${this.open ? "open" : ""}">
65
69
  <slot></slot>
66
70
  </div>
@@ -74,77 +78,219 @@ RelAccordion.styles = css`
74
78
  width: 100%;
75
79
  font-family: var(--rel-fontFamilies-primary, sans-serif);
76
80
  }
81
+
77
82
  .accordion {
78
- background: var(--rel-color-bg-primary);
79
- border: none;
80
- border-bottom: 1px solid var(--rel-gray-text-placeholder);
81
- border-radius: 0;
83
+ background: var(--rel-color-bg-primary, #ffffff);
84
+ border-radius: 8px;
82
85
  overflow: hidden;
86
+ box-shadow: 0 2px 4px rgba(11, 11, 11, 0.1);
83
87
  }
84
- /* HEADER --------------------------------------------------- */
88
+
89
+ /* ── Header ───────────────────────────────────────────────── */
90
+
85
91
  .header {
86
92
  display: flex;
87
93
  justify-content: space-between;
88
94
  align-items: center;
89
- padding: var(--rel-spacing-space-md, 16px);
90
95
  cursor: pointer;
91
96
  user-select: none;
92
- border-radius: 0;
97
+ box-sizing: border-box;
98
+ /* matches .accordion's radius so the focus-visible outline isn't clipped square at the corners by the parent's overflow:hidden */
99
+ border-radius: 8px;
93
100
  }
94
- .header:hover {
95
- background: var(--rel-surface-surface, #f5f5f5);
101
+
102
+ :host([size="md"]) .header {
103
+ padding: 8px 8px 8px 16px;
104
+ min-height: 56px;
96
105
  }
97
- :host([open]) .header:hover {
98
- background: transparent;
106
+
107
+ :host([size="sm"]) .header {
108
+ padding: 8px 8px 8px 12px;
109
+ min-height: 48px;
99
110
  }
111
+
112
+ .header:hover {
113
+ background: var(--rel-color-bg-secondary, #f5f5f5);
114
+ }
115
+
100
116
  .header:focus-visible {
101
117
  outline: 2px solid var(--rel-color-border-focus);
102
118
  outline-offset: -2px;
103
119
  }
120
+
121
+ /* ── Title row ────────────────────────────────────────────── */
122
+
123
+ .title-row {
124
+ display: flex;
125
+ align-items: center;
126
+ gap: 8px;
127
+ flex: 1;
128
+ }
129
+
104
130
  .title {
131
+ font-weight: var(--rel-fontWeights-semibold, 600);
132
+ color: var(--rel-color-text-default, #0b0b0b);
133
+ letter-spacing: -0.3px;
134
+ }
135
+
136
+ :host([size="md"]) .title {
105
137
  font-size: var(--rel-fontSizes-lg, 20px);
106
- font-weight: var(--rel-fontWeights-medium, 500);
107
- color: var(--rel-text-heading, #2b2b2b);
138
+ line-height: 28px;
108
139
  }
109
- /* ICON ----------------------------------------------------- */
110
- .icon {
140
+
141
+ :host([size="sm"]) .title {
142
+ font-size: 16px;
143
+ line-height: 24px;
144
+ }
145
+
146
+ /* ── Leading icon (action type) ───────────────────────────── */
147
+
148
+ .leading-icon {
149
+ display: inline-flex;
150
+ align-items: center;
151
+ justify-content: center;
152
+ flex-shrink: 0;
153
+ color: var(--rel-color-text-default, #0b0b0b);
154
+ }
155
+
156
+ .leading-icon ::slotted(svg) {
157
+ width: 24px;
158
+ height: 24px;
159
+ }
160
+
161
+ .leading-icon rel-icon,
162
+ .leading-icon ::slotted(rel-icon) {
163
+ --rel-icon-size: 24px;
164
+ }
165
+
166
+ :host([size="sm"]) .leading-icon ::slotted(svg) {
111
167
  width: 20px;
112
168
  height: 20px;
169
+ }
170
+
171
+ :host([size="sm"]) .leading-icon rel-icon,
172
+ :host([size="sm"]) .leading-icon ::slotted(rel-icon) {
173
+ --rel-icon-size: 20px;
174
+ }
175
+
176
+ /* ── Chevron ──────────────────────────────────────────────── */
177
+
178
+ .chevron {
113
179
  display: flex;
114
180
  align-items: center;
115
181
  justify-content: center;
116
- transition: transform 0.25s ease;
182
+ flex-shrink: 0;
183
+ }
184
+
185
+ :host([size="md"]) .chevron {
186
+ width: 40px;
187
+ height: 40px;
188
+ }
189
+
190
+ :host([size="sm"]) .chevron {
191
+ width: 32px;
192
+ height: 32px;
193
+ }
194
+
195
+ .chevron ::slotted(svg) {
196
+ width: 24px;
197
+ height: 24px;
198
+ }
199
+
200
+ .chevron rel-icon,
201
+ .chevron ::slotted(rel-icon) {
202
+ --rel-icon-size: 24px;
203
+ color: var(--rel-color-text-default, #0b0b0b);
117
204
  }
118
- .icon svg {
205
+
206
+ :host([size="sm"]) .chevron ::slotted(svg) {
119
207
  width: 20px;
120
208
  height: 20px;
121
- stroke: var(--rel-text-primary, #333);
122
- stroke-width: 2;
123
- fill: none;
124
- stroke-linecap: round;
125
- stroke-linejoin: round;
126
209
  }
127
- .icon.rotated {
210
+
211
+ :host([size="sm"]) .chevron rel-icon,
212
+ :host([size="sm"]) .chevron ::slotted(rel-icon) {
213
+ --rel-icon-size: 20px;
214
+ }
215
+
216
+ /* ── Icon rotation ────────────────────────────────────────── */
217
+ /* Only the shadow-DOM fallback wrappers rotate on open.
218
+ Slotted (light-DOM) icons are never targeted, so they stay static. */
219
+
220
+ .icon-rotate-on-open,
221
+ .chevron-rotate {
222
+ display: inline-flex;
223
+ align-items: center;
224
+ transition: transform 0.25s ease;
225
+ }
226
+
227
+ /* Leading fallback chevron: 90° (points right when open) */
228
+ :host([open]) .icon-rotate-on-open {
229
+ transform: rotate(90deg);
230
+ }
231
+
232
+ /* Trailing fallback chevron (type="default" only): 180° flip */
233
+ :host([open]) .chevron-rotate {
128
234
  transform: rotate(180deg);
129
235
  }
130
- /* BODY ------------------------------------------------------ */
236
+
237
+ /* ── Body ─────────────────────────────────────────────────── */
238
+
131
239
  .body {
132
240
  overflow: hidden;
133
241
  max-height: 0;
134
- padding: 0 var(--rel-spacing-space-md, 16px);
242
+ padding: 0 16px;
135
243
  font-size: var(--rel-fontSizes-md, 14px);
136
- color: var(--rel-text-primary, #333);
244
+ line-height: 22px;
245
+ /* Figma spec value — --rel-color-text-secondary resolves to #9e9e9e (gray-disabled-text), not this */
246
+ color: var(--rel-accordion-body-color, #525252);
137
247
  transition:
138
248
  max-height 0.25s ease,
139
249
  padding 0.2s ease;
140
250
  }
251
+
252
+ :host([size="sm"]) .body {
253
+ font-size: var(--rel-fontSizes-sm, 12px);
254
+ line-height: 20px;
255
+ }
256
+
141
257
  .body.open {
142
258
  max-height: 1000px;
143
- padding: var(--rel-spacing-space-xl, 24px)
144
- var(--rel-spacing-space-md, 16px) var(--rel-spacing-space-lg, 20px);
259
+ padding: 4px 16px 16px;
145
260
  }
261
+
262
+ /* ── Dark mode ────────────────────────────────────────────── */
263
+
264
+ :host-context([data-theme="dark"]) .accordion,
265
+ [data-theme="dark"] .accordion {
266
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
267
+ }
268
+
269
+ :host-context([data-theme="dark"]) .title,
270
+ [data-theme="dark"] .title {
271
+ color: var(--rel-color-text-default-dark, #f5f5f5);
272
+ }
273
+
274
+ :host-context([data-theme="dark"]) .chevron rel-icon,
275
+ [data-theme="dark"] .chevron rel-icon,
276
+ :host-context([data-theme="dark"]) .chevron ::slotted(rel-icon),
277
+ [data-theme="dark"] .chevron ::slotted(rel-icon) {
278
+ color: var(--rel-color-text-default-dark, #f5f5f5);
279
+ }
280
+
281
+ :host-context([data-theme="dark"]) .leading-icon,
282
+ [data-theme="dark"] .leading-icon {
283
+ color: var(--rel-color-text-default-dark, #f5f5f5);
284
+ }
285
+
286
+ :host-context([data-theme="dark"]) .body,
287
+ [data-theme="dark"] .body {
288
+ color: var(--rel-accordion-body-color-dark, #a3a3a3);
289
+ }
290
+
146
291
  @media (prefers-reduced-motion: reduce) {
147
- .icon,
292
+ .icon-rotate-on-open,
293
+ .chevron-rotate,
148
294
  .body {
149
295
  transition: none;
150
296
  }
@@ -156,6 +302,12 @@ __decorateClass([
156
302
  __decorateClass([
157
303
  property({ type: Boolean, reflect: true })
158
304
  ], RelAccordion.prototype, "open", 2);
305
+ __decorateClass([
306
+ property({ type: String, reflect: true })
307
+ ], RelAccordion.prototype, "size", 2);
308
+ __decorateClass([
309
+ property({ type: String, reflect: true })
310
+ ], RelAccordion.prototype, "type", 2);
159
311
  RelAccordion = __decorateClass([
160
312
  customElement("rel-accordion")
161
313
  ], RelAccordion);
@@ -485,14 +637,16 @@ var RelAvatar = class extends LitElement3 {
485
637
  super(...arguments);
486
638
  this.size = "md";
487
639
  this.type = "image";
640
+ this.variant = "fill";
488
641
  this.src = "";
489
642
  this.text = "";
490
643
  this.alt = "Avatar";
491
644
  this.bg = "";
645
+ this.color = "";
492
646
  }
493
647
  render() {
494
648
  return html3`
495
- <div class="avatar avatar-${this.size}" style=${this.bg ? `background-color: ${this.bg}` : ""}>
649
+ <div class="avatar avatar-${this.size}" style=${[this.bg ? `background-color:${this.bg}` : "", this.color ? `color:${this.color}` : ""].filter(Boolean).join(";")}>
496
650
  ${this.type === "image" && this.src ? html3`<img src=${this.src} alt=${this.alt} />` : this.type === "text" ? html3`<span>${this.text}</span>` : html3`<span class="icon-slot"><slot></slot></span>`}
497
651
  </div>
498
652
  `;
@@ -510,59 +664,97 @@ RelAvatar.styles = css3`
510
664
  justify-content: center;
511
665
  border-radius: 50%;
512
666
  overflow: hidden;
513
-
514
- background-color: var(--rel-colors-gray-disabled-text);
515
- color: var(--rel-avatar-color, #ffffff);
516
- font-weight: var(--rel-fontWeights-bold);
517
-
667
+ box-sizing: border-box;
668
+ border: var(--rel-borders-width-stroke-100, 1px) solid transparent;
669
+ font-weight: var(--rel-fontWeights-semibold);
518
670
  user-select: none;
519
671
  text-transform: uppercase;
520
672
  }
521
673
 
522
- /* Sizes */
674
+ /* ── Variants ─────────────────────────────────────────────── */
675
+
676
+ :host([variant="fill"]) .avatar {
677
+ background-color: var(--rel-avatar-bg-fill, #0b0b0b);
678
+ color: var(--rel-avatar-color-fill, #ffffff);
679
+ }
680
+
681
+ :host([variant="subtle"]) .avatar {
682
+ background-color: var(--rel-avatar-bg-subtle, #f5f5f5);
683
+ color: var(--rel-avatar-color-subtle, #0b0b0b);
684
+ }
685
+
686
+ :host([variant="outline"]) .avatar {
687
+ background-color: transparent;
688
+ border-color: var(--rel-avatar-border-outline, var(--rel-color-border-default));
689
+ color: var(--rel-avatar-color-outline, #0b0b0b);
690
+ }
691
+
692
+ /* ── Sizes ────────────────────────────────────────────────── */
693
+
523
694
  .avatar-lg {
524
695
  width: 40px;
525
696
  height: 40px;
526
- font-size: var(--rel-fontSizes-xl);
697
+ font-size: var(--rel-fontSizes-lg); /* 20px */
527
698
  }
528
699
 
529
700
  .avatar-md {
530
701
  width: 32px;
531
702
  height: 32px;
532
- font-size: var(--rel-fontSizes-lg);
703
+ font-size: 16px;
533
704
  }
534
705
 
535
706
  .avatar-sm {
536
707
  width: 24px;
537
708
  height: 24px;
538
- font-size: var(--rel-fontSizes-md);
709
+ font-size: var(--rel-fontSizes-sm); /* 12px */
539
710
  }
540
711
 
541
712
  .avatar-xs {
542
- width: 18px;
543
- height: 18px;
544
- font-size: var(--rel-fontSizes-xs);
713
+ width: 20px;
714
+ height: 20px;
715
+ font-size: var(--rel-fontSizes-xs); /* 10px */
545
716
  }
546
717
 
718
+ /* ── Image ────────────────────────────────────────────────── */
719
+
547
720
  img {
548
721
  width: 100%;
549
722
  height: 100%;
550
723
  object-fit: cover;
551
724
  }
552
725
 
726
+ /* ── Icon slot ────────────────────────────────────────────── */
727
+
553
728
  .icon-slot {
554
729
  width: 100%;
555
730
  height: 100%;
556
731
  display: inline-flex;
557
732
  align-items: center;
558
733
  justify-content: center;
559
- color: #ffffff;
734
+ color: inherit;
560
735
  }
561
736
 
562
737
  .icon-slot ::slotted(svg) {
563
738
  width: 50%;
564
739
  height: 50%;
565
740
  }
741
+
742
+ /* ── Dark mode ────────────────────────────────────────────────
743
+ :host() can never be preceded by a combinator inside a shadow-tree
744
+ stylesheet, so ":host-context(dark) :host([variant=...]) .avatar"
745
+ (the previous approach) is invalid and silently matches nothing.
746
+ Instead, redefine the same custom properties the variant rules
747
+ above already read via var(--token, fallback) — a plain
748
+ :host-context() selector with no compounding, guaranteed valid. ── */
749
+
750
+ :host-context([data-theme="dark"]) {
751
+ --rel-avatar-bg-fill: #ffffff;
752
+ --rel-avatar-color-fill: #0b0b0b;
753
+ --rel-avatar-bg-subtle: #2b2b2b;
754
+ --rel-avatar-color-subtle: #f5f5f5;
755
+ --rel-avatar-border-outline: #525252;
756
+ --rel-avatar-color-outline: #f5f5f5;
757
+ }
566
758
  `;
567
759
  __decorateClass([
568
760
  property3({ type: String, reflect: true })
@@ -570,6 +762,9 @@ __decorateClass([
570
762
  __decorateClass([
571
763
  property3({ type: String, reflect: true })
572
764
  ], RelAvatar.prototype, "type", 2);
765
+ __decorateClass([
766
+ property3({ type: String, reflect: true })
767
+ ], RelAvatar.prototype, "variant", 2);
573
768
  __decorateClass([
574
769
  property3({ type: String })
575
770
  ], RelAvatar.prototype, "src", 2);
@@ -582,6 +777,9 @@ __decorateClass([
582
777
  __decorateClass([
583
778
  property3({ type: String })
584
779
  ], RelAvatar.prototype, "bg", 2);
780
+ __decorateClass([
781
+ property3({ type: String })
782
+ ], RelAvatar.prototype, "color", 2);
585
783
  RelAvatar = __decorateClass([
586
784
  customElement3("rel-avatar")
587
785
  ], RelAvatar);
@@ -598,10 +796,28 @@ var RelBadge = class extends LitElement4 {
598
796
  this.suffix = "notifications";
599
797
  this.size = "md";
600
798
  this.variant = "number";
799
+ this.color = "";
800
+ this.textColor = "";
601
801
  }
602
802
  get classes() {
603
803
  return ["badge", `badge-${this.size}`, `badge-${this.variant}`].join(" ");
604
804
  }
805
+ updated(changedProperties) {
806
+ if (changedProperties.has("color")) {
807
+ if (this.color) {
808
+ this.style.setProperty("--rel-badge-bg", this.color);
809
+ } else {
810
+ this.style.removeProperty("--rel-badge-bg");
811
+ }
812
+ }
813
+ if (changedProperties.has("textColor")) {
814
+ if (this.textColor) {
815
+ this.style.setProperty("--rel-badge-color", this.textColor);
816
+ } else {
817
+ this.style.removeProperty("--rel-badge-color");
818
+ }
819
+ }
820
+ }
605
821
  render() {
606
822
  return html4`
607
823
  <span class="${this.classes}" aria-label=${this.ariaLabel || `${this.number} ${this.suffix}`}>
@@ -621,8 +837,8 @@ RelBadge.styles = css4`
621
837
  justify-content: center;
622
838
  font-family: var(--rel-fontFamilies-primary, sans-serif);
623
839
  font-weight: var(--rel-fontWeights-semibold, 600);
624
- background-color: var(--rel-error-surface-default);
625
- color: #ffffff;
840
+ background-color: var(--rel-badge-bg, var(--rel-error-surface-default));
841
+ color: var(--rel-badge-color, #ffffff);
626
842
  border-radius: 50%;
627
843
  }
628
844
 
@@ -676,6 +892,12 @@ __decorateClass([
676
892
  __decorateClass([
677
893
  property4({ type: String, reflect: true })
678
894
  ], RelBadge.prototype, "variant", 2);
895
+ __decorateClass([
896
+ property4({ type: String, reflect: true })
897
+ ], RelBadge.prototype, "color", 2);
898
+ __decorateClass([
899
+ property4({ type: String, reflect: true, attribute: "text-color" })
900
+ ], RelBadge.prototype, "textColor", 2);
679
901
  RelBadge = __decorateClass([
680
902
  customElement4("rel-badge")
681
903
  ], RelBadge);
@@ -793,6 +1015,20 @@ var RelButton = class extends LitElement6 {
793
1015
  this.border = "corner-radius";
794
1016
  this.disabled = false;
795
1017
  this.ariaLabel = null;
1018
+ this.handleHostClick = (e) => {
1019
+ if (this.disabled) {
1020
+ e.preventDefault();
1021
+ e.stopImmediatePropagation();
1022
+ }
1023
+ };
1024
+ }
1025
+ connectedCallback() {
1026
+ super.connectedCallback();
1027
+ this.addEventListener("click", this.handleHostClick, { capture: true });
1028
+ }
1029
+ disconnectedCallback() {
1030
+ this.removeEventListener("click", this.handleHostClick, { capture: true });
1031
+ super.disconnectedCallback();
796
1032
  }
797
1033
  get classes() {
798
1034
  return [
@@ -808,12 +1044,6 @@ var RelButton = class extends LitElement6 {
808
1044
  e.stopImmediatePropagation();
809
1045
  return;
810
1046
  }
811
- this.dispatchEvent(
812
- new MouseEvent("click", {
813
- bubbles: true,
814
- composed: true
815
- })
816
- );
817
1047
  }
818
1048
  render() {
819
1049
  return html6`
@@ -882,6 +1112,10 @@ RelButton.styles = css6`
882
1112
  /* Disabled */
883
1113
  :host([disabled]) {
884
1114
  cursor: not-allowed;
1115
+ /* Without this, clicks on a disabled button hit-test fall through the
1116
+ inner button's pointer-events:none straight onto the host, which still
1117
+ dispatches a normal click to any externally-attached listener. */
1118
+ pointer-events: none;
885
1119
  }
886
1120
 
887
1121
  :host([disabled]) button {
@@ -3412,6 +3646,14 @@ var RelRangePicker = class extends LitElement13 {
3412
3646
  this.disabled = false;
3413
3647
  this.open = false;
3414
3648
  this.mode = "popover";
3649
+ this.width = "";
3650
+ this.minWidth = "";
3651
+ this.maxWidth = "";
3652
+ this.height = "";
3653
+ this.minHeight = "";
3654
+ this.maxHeight = "";
3655
+ this.placeholder = "Select date range";
3656
+ this.triggerVariant = "default";
3415
3657
  this.draftFrom = "";
3416
3658
  this.draftTo = "";
3417
3659
  this.draftActivePreset = null;
@@ -3462,6 +3704,14 @@ var RelRangePicker = class extends LitElement13 {
3462
3704
  document.removeEventListener("click", this.handleClickOutside);
3463
3705
  document.removeEventListener("keydown", this.handleGlobalKeydown);
3464
3706
  }
3707
+ updated() {
3708
+ this.style.width = this.width;
3709
+ this.style.minWidth = this.minWidth;
3710
+ this.style.maxWidth = this.maxWidth;
3711
+ this.style.height = this.height;
3712
+ this.style.minHeight = this.minHeight;
3713
+ this.style.maxHeight = this.maxHeight;
3714
+ }
3465
3715
  toggleOpen() {
3466
3716
  if (this.disabled) return;
3467
3717
  if (this.open) {
@@ -3518,7 +3768,7 @@ var RelRangePicker = class extends LitElement13 {
3518
3768
  this.to = this.draftTo;
3519
3769
  this.dispatchEvent(
3520
3770
  new CustomEvent("rel-change", {
3521
- detail: { from: this.from, to: this.to },
3771
+ detail: { from: this.from, to: this.to, label: this.displayLabel },
3522
3772
  bubbles: true,
3523
3773
  composed: true
3524
3774
  })
@@ -3551,6 +3801,10 @@ var RelRangePicker = class extends LitElement13 {
3551
3801
  if (from) return from;
3552
3802
  return "";
3553
3803
  }
3804
+ /** Formatted "MM/DD/YYYY → MM/DD/YYYY" (or single date / "") for the current committed `from`/`to`. */
3805
+ get displayLabel() {
3806
+ return this.getTriggerLabel();
3807
+ }
3554
3808
  // ── Date utilities ──
3555
3809
  parseISODate(iso) {
3556
3810
  const m = iso.match(/^(\d{4})-(\d{2})-(\d{2})$/);
@@ -3778,22 +4032,36 @@ var RelRangePicker = class extends LitElement13 {
3778
4032
  const isDraftEmpty = !this.draftFrom && !this.draftTo;
3779
4033
  const isPopup = this.mode === "popup";
3780
4034
  return html13`
3781
- <button
3782
- class="trigger-button"
3783
- type="button"
3784
- ?disabled=${this.disabled}
3785
- aria-haspopup="dialog"
3786
- aria-expanded=${this.open}
3787
- aria-label=${triggerLabel || "Select date range"}
3788
- @click=${this.toggleOpen}
3789
- >
3790
- <span class="trigger-content ${triggerLabel ? "" : "placeholder"}">
3791
- ${triggerLabel || "Select date range"}
3792
- </span>
3793
- <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
3794
- <path 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"/>
3795
- </svg>
3796
- </button>
4035
+ ${this.triggerVariant === "icon" ? html13`
4036
+ <rel-button
4037
+ variant="icon"
4038
+ tone="secondary"
4039
+ ?disabled=${this.disabled}
4040
+ aria-haspopup="dialog"
4041
+ aria-expanded=${this.open}
4042
+ aria-label=${triggerLabel || this.placeholder}
4043
+ @click=${() => this.toggleOpen()}
4044
+ >
4045
+ <rel-icon name="calendar-range"></rel-icon>
4046
+ </rel-button>
4047
+ ` : html13`
4048
+ <button
4049
+ class="trigger-button"
4050
+ type="button"
4051
+ ?disabled=${this.disabled}
4052
+ aria-haspopup="dialog"
4053
+ aria-expanded=${this.open}
4054
+ aria-label=${triggerLabel || this.placeholder}
4055
+ @click=${this.toggleOpen}
4056
+ >
4057
+ <span class="trigger-content ${triggerLabel ? "" : "placeholder"}">
4058
+ ${triggerLabel || this.placeholder}
4059
+ </span>
4060
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
4061
+ <path 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"/>
4062
+ </svg>
4063
+ </button>
4064
+ `}
3797
4065
 
3798
4066
  ${isPopup && this.open ? html13`<div class="backdrop" @click=${this.cancelPopover}></div>` : nothing4}
3799
4067
 
@@ -3911,30 +4179,34 @@ var RelRangePicker = class extends LitElement13 {
3911
4179
  </div>
3912
4180
 
3913
4181
  <div class="calendar-footer">
3914
- <button
3915
- class="btn-reset"
3916
- type="button"
4182
+ <rel-button
4183
+ variant="secondary"
4184
+ size="small"
4185
+ border="corner-radius"
3917
4186
  ?disabled=${isDraftEmpty}
3918
- @click=${this.resetDraft}
4187
+ @click=${() => this.resetDraft()}
3919
4188
  >
3920
4189
  Reset
3921
- </button>
4190
+ </rel-button>
3922
4191
  <div class="footer-right">
3923
- <button
3924
- class="btn-cancel"
3925
- type="button"
3926
- @click=${this.cancelPopover}
4192
+ <rel-button
4193
+ variant="secondary"
4194
+ size="small"
4195
+ border="corner-radius"
4196
+ @click=${() => this.cancelPopover()}
3927
4197
  >
3928
4198
  Cancel
3929
- </button>
3930
- <button
3931
- class="btn-apply"
3932
- type="button"
4199
+ </rel-button>
4200
+ <rel-button
4201
+ variant="primary"
4202
+ tone="default"
4203
+ size="small"
4204
+ border="corner-radius"
3933
4205
  ?disabled=${isDraftEmpty}
3934
- @click=${this.applySelection}
4206
+ @click=${() => this.applySelection()}
3935
4207
  >
3936
4208
  Apply
3937
- </button>
4209
+ </rel-button>
3938
4210
  </div>
3939
4211
  </div>
3940
4212
 
@@ -3954,6 +4226,10 @@ RelRangePicker.styles = css13`
3954
4226
  :host([disabled]) {
3955
4227
  opacity: 0.6;
3956
4228
  cursor: not-allowed;
4229
+ }
4230
+
4231
+ :host([disabled]) .trigger-button,
4232
+ :host([disabled]) rel-button {
3957
4233
  pointer-events: none;
3958
4234
  }
3959
4235
 
@@ -3971,7 +4247,6 @@ RelRangePicker.styles = css13`
3971
4247
  font-size: var(--rel-fontSizes-md, 14px);
3972
4248
  color: var(--rel-color-text-primary, #333);
3973
4249
  cursor: pointer;
3974
- min-width: 260px;
3975
4250
  width: 100%;
3976
4251
  text-align: left;
3977
4252
  transition: border-color 0.15s ease;
@@ -4000,7 +4275,7 @@ RelRangePicker.styles = css13`
4000
4275
  position: absolute;
4001
4276
  top: calc(100% + 4px);
4002
4277
  left: 0;
4003
- z-index: 1000;
4278
+ z-index: 2147483647;
4004
4279
  border: 1px solid var(--rel-color-border-default, #ddd);
4005
4280
  border-radius: var(--rel-borders-radius-border-radius-200, 8px);
4006
4281
  background: var(--rel-color-bg-primary, #fff);
@@ -4021,7 +4296,7 @@ RelRangePicker.styles = css13`
4021
4296
  .backdrop {
4022
4297
  position: fixed;
4023
4298
  inset: 0;
4024
- z-index: 999;
4299
+ z-index: 2147483646;
4025
4300
  background: rgba(0,0,0,0.4);
4026
4301
  }
4027
4302
 
@@ -4313,58 +4588,13 @@ RelRangePicker.styles = css13`
4313
4588
  gap: 8px;
4314
4589
  }
4315
4590
 
4316
- .btn-reset,
4317
- .btn-cancel,
4318
- .btn-apply {
4319
- font-family: var(--rel-fontFamilies-primary, Poppins, sans-serif);
4320
- font-size: var(--rel-fontSizes-md, 14px);
4321
- font-weight: var(--rel-fontWeights-medium, 500);
4322
- border-radius: var(--rel-borders-radius-border-radius-500, 1000px);
4323
- padding: 8px 20px;
4324
- cursor: pointer;
4325
- transition: background 0.15s ease, border-color 0.15s ease;
4326
- white-space: nowrap;
4327
- }
4328
-
4329
- .btn-reset,
4330
- .btn-cancel {
4331
- background: transparent;
4332
- border: 1px solid var(--rel-color-border-default, #ddd);
4333
- color: var(--rel-color-text-primary, #333);
4334
- }
4335
-
4336
- .btn-reset:hover:not(:disabled),
4337
- .btn-cancel:hover {
4338
- background: var(--rel-color-bg-hover, #f5f5f5);
4339
- }
4340
-
4341
- .btn-reset:disabled {
4342
- opacity: 0.4;
4343
- cursor: not-allowed;
4344
- }
4345
-
4346
- .btn-apply {
4347
- background: var(--rel-colors-green-primary, #00f49c);
4348
- border: none;
4349
- color: #000000;
4350
- }
4351
-
4352
- .btn-apply:hover:not(:disabled) {
4353
- background: var(--rel-colors-green-secondary, #06d98c);
4354
- }
4355
-
4356
- .btn-apply:disabled {
4357
- opacity: 0.4;
4358
- cursor: not-allowed;
4359
- }
4360
-
4361
4591
  .footer-right {
4362
4592
  display: flex;
4363
4593
  gap: 8px;
4364
4594
  }
4365
4595
 
4366
4596
  @media (prefers-reduced-motion: reduce) {
4367
- .preset-item, .nav-btn, .day-inner, .btn-reset, .btn-cancel, .btn-apply {
4597
+ .preset-item, .nav-btn, .day-inner {
4368
4598
  transition: none;
4369
4599
  }
4370
4600
  }
@@ -4396,6 +4626,30 @@ __decorateClass([
4396
4626
  __decorateClass([
4397
4627
  property12({ type: String })
4398
4628
  ], RelRangePicker.prototype, "mode", 2);
4629
+ __decorateClass([
4630
+ property12({ type: String })
4631
+ ], RelRangePicker.prototype, "width", 2);
4632
+ __decorateClass([
4633
+ property12({ type: String, attribute: "min-width" })
4634
+ ], RelRangePicker.prototype, "minWidth", 2);
4635
+ __decorateClass([
4636
+ property12({ type: String, attribute: "max-width" })
4637
+ ], RelRangePicker.prototype, "maxWidth", 2);
4638
+ __decorateClass([
4639
+ property12({ type: String })
4640
+ ], RelRangePicker.prototype, "height", 2);
4641
+ __decorateClass([
4642
+ property12({ type: String, attribute: "min-height" })
4643
+ ], RelRangePicker.prototype, "minHeight", 2);
4644
+ __decorateClass([
4645
+ property12({ type: String, attribute: "max-height" })
4646
+ ], RelRangePicker.prototype, "maxHeight", 2);
4647
+ __decorateClass([
4648
+ property12({ type: String })
4649
+ ], RelRangePicker.prototype, "placeholder", 2);
4650
+ __decorateClass([
4651
+ property12({ type: String, attribute: "trigger-variant" })
4652
+ ], RelRangePicker.prototype, "triggerVariant", 2);
4399
4653
  __decorateClass([
4400
4654
  state4()
4401
4655
  ], RelRangePicker.prototype, "draftFrom", 2);
@@ -4426,17 +4680,31 @@ RelRangePicker = __decorateClass([
4426
4680
 
4427
4681
  // src/components/rel-chip/rel-chip.ts
4428
4682
  import { LitElement as LitElement14, html as html14, css as css14 } from "lit";
4429
- import { customElement as customElement14, property as property13 } from "lit/decorators.js";
4683
+ import { customElement as customElement14, property as property13, state as state5 } from "lit/decorators.js";
4684
+ import "@reliability-design/icons/rel-icon";
4430
4685
  var RelChip = class extends LitElement14 {
4431
4686
  constructor() {
4432
4687
  super(...arguments);
4433
4688
  this.label = "Label";
4434
- this.tone = "default";
4689
+ this.tone = "neutral";
4690
+ this.variant = "fill";
4691
+ this.size = "md";
4692
+ this.border = "default";
4435
4693
  this.removable = false;
4436
4694
  this.removed = false;
4695
+ this.draggableChip = false;
4696
+ this.dragging = false;
4697
+ this.onDragStart = (e) => {
4698
+ if (!this.draggableChip) return;
4699
+ this.dragging = true;
4700
+ e.dataTransfer?.setData("text/plain", this.label);
4701
+ };
4702
+ this.onDragEnd = () => {
4703
+ this.dragging = false;
4704
+ };
4437
4705
  }
4438
4706
  get classes() {
4439
- return ["chip", `chip-${this.tone}`].join(" ");
4707
+ return "chip";
4440
4708
  }
4441
4709
  handleRemove(event) {
4442
4710
  event.stopPropagation();
@@ -4448,6 +4716,23 @@ var RelChip = class extends LitElement14 {
4448
4716
  })
4449
4717
  );
4450
4718
  }
4719
+ updated(changed) {
4720
+ if (changed.has("draggableChip")) {
4721
+ if (this.draggableChip) {
4722
+ this.setAttribute("draggable", "true");
4723
+ this.addEventListener("dragstart", this.onDragStart);
4724
+ this.addEventListener("dragend", this.onDragEnd);
4725
+ } else {
4726
+ this.removeAttribute("draggable");
4727
+ this.removeEventListener("dragstart", this.onDragStart);
4728
+ this.removeEventListener("dragend", this.onDragEnd);
4729
+ this.dragging = false;
4730
+ }
4731
+ }
4732
+ if (changed.has("dragging")) {
4733
+ this.toggleAttribute("dragging", this.dragging);
4734
+ }
4735
+ }
4451
4736
  render() {
4452
4737
  const showAvatar = !!this.avatar;
4453
4738
  const showLeadingIcon = !showAvatar && !!this.leadingIcon;
@@ -4464,30 +4749,30 @@ var RelChip = class extends LitElement14 {
4464
4749
  aria-label="${this.label}"
4465
4750
  >
4466
4751
  ${showAvatar ? html14`<rel-avatar type="text" text=${this.avatar} size="xs"></rel-avatar>` : null}
4467
- ${showLeadingIcon ? html14`<span class="chip-icon">
4468
- ${this.renderIcon(this.leadingIcon)}
4469
- </span>` : null}
4752
+ ${showLeadingIcon ? html14`<rel-icon class="chip-icon" name="${this.leadingIcon}"></rel-icon>` : null}
4470
4753
 
4471
4754
  <span class="chip-label">${this.label}</span>
4472
4755
 
4473
- ${this.trailingIcon ? html14`<span class="chip-icon">
4474
- ${this.renderIcon(this.trailingIcon)}
4475
- </span>` : null}
4756
+ ${this.trailingIcon ? html14`<rel-icon class="chip-icon" name="${this.trailingIcon}"></rel-icon>` : null}
4476
4757
  ${this.removable ? html14`<button
4477
4758
  class="chip-remove"
4478
4759
  aria-label="Remove ${this.label}"
4479
4760
  @click=${this.handleRemove}
4480
4761
  >
4481
- ✕
4762
+ <rel-icon name="close"></rel-icon>
4482
4763
  </button>` : null}
4483
4764
  </span>
4484
4765
  `;
4485
4766
  }
4486
- renderIcon(iconString) {
4487
- const template = document.createElement("template");
4488
- template.innerHTML = iconString.trim();
4489
- return template.content.cloneNode(true);
4490
- }
4767
+ };
4768
+ // The actually-focusable element is the inner <span tabindex="0">, not the
4769
+ // host. Without delegatesFocus, calling host.focus() (e.g. from a parent
4770
+ // component, or a "focus this" demo button) is a no-op since the host
4771
+ // itself carries no tabindex — only real Tab-key traversal would still
4772
+ // reach the inner span, because that walks the flattened DOM regardless.
4773
+ RelChip.shadowRootOptions = {
4774
+ ...LitElement14.shadowRootOptions,
4775
+ delegatesFocus: true
4491
4776
  };
4492
4777
  RelChip.styles = css14`
4493
4778
  :host {
@@ -4503,108 +4788,184 @@ RelChip.styles = css14`
4503
4788
  .chip {
4504
4789
  display: inline-flex;
4505
4790
  align-items: center;
4791
+ box-sizing: border-box;
4506
4792
  font-family: var(--rel-fontFamilies-primary);
4507
- font-size: var(--rel-fontSizes-md);
4508
- font-weight: var(--rel-fontWeights-medium);
4509
- border-radius: var(--rel-borders-radius-border-radius-100);
4510
- padding: var(--rel-spacing-space-2xs) var(--rel-spacing-space-xs);
4511
- gap: var(--rel-spacing-space-2xs);
4793
+ font-weight: 500;
4794
+ letter-spacing: -0.6px;
4795
+ gap: 8px;
4512
4796
  cursor: pointer;
4513
- border: var(--rel-borders-width-stroke-100) solid transparent;
4514
4797
  user-select: none;
4515
4798
  white-space: nowrap;
4799
+ outline: none;
4516
4800
  background: transparent;
4801
+ transition: background-color 0.15s ease;
4517
4802
  }
4518
4803
 
4519
- .chip:hover {
4520
- filter: brightness(0.88);
4521
- box-shadow: var(--rel-shadows-shadow-100);
4804
+ /* ── Size ── */
4805
+ :host([size="lg"]) .chip {
4806
+ height: 32px;
4807
+ padding: 4px 8px;
4808
+ font-size: 16px;
4809
+ line-height: 24px;
4522
4810
  }
4523
4811
 
4524
- .chip:focus-visible {
4525
- outline: 2px solid var(--rel-color-border-focus);
4526
- outline-offset: 2px;
4812
+ :host([size="md"]) .chip {
4813
+ height: 28px;
4814
+ padding: 4px 8px;
4815
+ font-size: 14px;
4816
+ line-height: 22px;
4527
4817
  }
4528
4818
 
4529
- .chip:active {
4530
- filter: brightness(0.80);
4531
- box-shadow: var(--rel-shadows-shadow-200);
4819
+ :host([size="sm"]) .chip {
4820
+ height: 24px;
4821
+ padding: 4px 8px;
4822
+ font-size: 12px;
4823
+ line-height: 20px;
4532
4824
  }
4533
4825
 
4534
- /* TONES — light (default) */
4535
- /* NOTE: #717171 has no exact vars-v2 token; nearest candidates are
4536
- --rel-colors-gray-toast-bg (#404040) and --rel-colors-gray-divider (#BDBDBD) */
4537
- .chip-default {
4538
- background: #717171;
4539
- color: var(--rel-colors-white);
4826
+ /* ── Border / shape — "Rounded" also widens horizontal padding to 12px,
4827
+ consistent across all three sizes per the Figma spec. ── */
4828
+ :host([border="default"]) .chip {
4829
+ border-radius: 4px;
4540
4830
  }
4541
4831
 
4542
- .chip-blue {
4543
- background: var(--rel-colors-blue-tertiary);
4544
- color: var(--rel-colors-white);
4832
+ :host([border="rounded"]) .chip {
4833
+ border-radius: 1000px;
4834
+ padding-left: 12px;
4835
+ padding-right: 12px;
4545
4836
  }
4546
4837
 
4547
- .chip-orange {
4548
- background: var(--rel-colors-yellow-pending);
4549
- color: var(--rel-colors-white);
4838
+ /* ── Tone x Variant — Default/Default state colors ── */
4839
+ :host([tone="neutral"][variant="fill"]) .chip {
4840
+ background: #0b0b0b;
4841
+ color: #ffffff;
4842
+ }
4843
+ :host([tone="neutral"][variant="subtle"]) .chip {
4844
+ background: #f5f5f5;
4845
+ color: #0b0b0b;
4846
+ }
4847
+ :host([tone="danger"][variant="fill"]) .chip {
4848
+ background: #f83b3b;
4849
+ color: #ffffff;
4850
+ }
4851
+ :host([tone="danger"][variant="subtle"]) .chip {
4852
+ background: #fff1f1;
4853
+ color: #ce3131;
4854
+ }
4855
+ :host([tone="warning"][variant="fill"]) .chip {
4856
+ background: #ffcb66;
4857
+ color: #0b0b0b;
4858
+ }
4859
+ :host([tone="warning"][variant="subtle"]) .chip {
4860
+ background: #ffefd1;
4861
+ color: #713f12;
4862
+ }
4863
+ :host([tone="success"][variant="fill"]) .chip {
4864
+ background: #00a86b;
4865
+ color: #ffffff;
4866
+ }
4867
+ :host([tone="success"][variant="subtle"]) .chip {
4868
+ background: #edf8f4;
4869
+ color: #008655;
4870
+ }
4871
+ :host([tone="info"][variant="fill"]) .chip {
4872
+ background: #0091ea;
4873
+ color: #ffffff;
4874
+ }
4875
+ :host([tone="info"][variant="subtle"]) .chip {
4876
+ background: #eff7ff;
4877
+ color: #00528d;
4550
4878
  }
4551
4879
 
4552
- .chip-red {
4553
- background: var(--rel-colors-red-primary);
4554
- color: var(--rel-colors-white);
4880
+ /* ── Hover / Dragged — Figma only specs explicit color shifts for the
4881
+ "neutral" tone; the other four tones have no hover/dragged sample to
4882
+ match, so a generic brightness dim covers them instead of leaving
4883
+ hover completely inert. Flagged in the handoff notes. ── */
4884
+ :host([tone="neutral"][variant="fill"]) .chip:hover {
4885
+ background: #363636;
4886
+ }
4887
+ :host([tone="neutral"][variant="fill"]) .chip:active,
4888
+ :host([tone="neutral"][variant="fill"][dragging]) .chip {
4889
+ background: #404040;
4890
+ }
4891
+ :host([tone="neutral"][variant="subtle"]) .chip:active,
4892
+ :host([tone="neutral"][variant="subtle"][dragging]) .chip {
4893
+ background: #e5e5e5;
4555
4894
  }
4556
4895
 
4557
- .chip-green {
4558
- background: var(--rel-colors-green-tertiary);
4559
- color: var(--rel-colors-white);
4896
+ :host(:not([tone="neutral"])) .chip:hover {
4897
+ filter: brightness(0.96);
4898
+ }
4899
+ :host(:not([tone="neutral"])) .chip:active,
4900
+ :host(:not([tone="neutral"])[dragging]) .chip {
4901
+ filter: brightness(0.92);
4560
4902
  }
4561
4903
 
4562
- /* AVATAR — light mode (all tones)
4563
- rel-avatar uses background-color: var(--rel-colors-gray-disabled-text).
4564
- Overriding that custom property here pins avatar bg to white across all tones.
4565
- NOTE: rel-avatar hardcodes color: #ffffff — text color (#000000) cannot be
4566
- overridden from outside the shadow DOM without ::part() or a custom property
4567
- in rel-avatar itself. */
4568
- .chip rel-avatar {
4569
- display: inline-flex;
4570
- width: 20px !important;
4571
- height: 20px !important;
4572
- flex-shrink: 0;
4573
- font-size: 10px;
4904
+ :host([dragging]) .chip {
4905
+ cursor: grabbing;
4574
4906
  }
4575
4907
 
4576
- .chip-default rel-avatar,
4577
- .chip-blue rel-avatar,
4578
- .chip-orange rel-avatar,
4579
- .chip-red rel-avatar,
4580
- .chip-green rel-avatar {
4581
- --rel-colors-gray-disabled-text: #ffffff;
4582
- --rel-avatar-color: #000000;
4908
+ /* ── Focused — 1.5px outline, drawn outside (matches Figma's
4909
+ strokeAlign:OUTSIDE) so it never affects layout. Same color
4910
+ regardless of tone, per spec. OUTSIDE alignment means the stroke
4911
+ sits flush against the shape's edge with zero gap, extending
4912
+ outward by strokeWeight — outline-offset must be 0, not a positive
4913
+ gap (a positive offset was the bug: it drew a visible gap that
4914
+ doesn't exist in Figma). ── */
4915
+ .chip:focus-visible {
4916
+ outline: 1.5px solid var(--rel-chip-focus-ring, #0b0b0b);
4917
+ outline-offset: 0;
4583
4918
  }
4584
4919
 
4920
+ /* ── Icons ── */
4921
+ /* rel-icon renders its SVG inside its own shadow root, so sizing has to
4922
+ go through --rel-icon-size (a custom property — pierces shadow
4923
+ boundaries) rather than a ".chip-icon svg" selector, which can never
4924
+ reach across shadow DOM. */
4585
4925
  .chip-icon {
4926
+ flex-shrink: 0;
4927
+ }
4928
+
4929
+ :host([size="lg"]) .chip-icon {
4930
+ --rel-icon-size: 16px;
4931
+ }
4932
+
4933
+ :host([size="md"]) .chip-icon {
4934
+ --rel-icon-size: 14px;
4935
+ }
4936
+
4937
+ :host([size="sm"]) .chip-icon {
4938
+ --rel-icon-size: 12px;
4939
+ }
4940
+
4941
+ /* ── Avatar — not shown in the Figma sample. rel-avatar sizes its inner
4942
+ .avatar div directly from its own "size" prop (fixed presets only —
4943
+ no --rel-avatar-size custom property escape hatch like rel-icon has),
4944
+ so a host-level width/height override here would only resize the
4945
+ empty outer wrapper, not the actual painted circle. "xs" (20px) is
4946
+ rel-avatar's smallest preset; used uniformly across all three chip
4947
+ sizes since there's nothing smaller to ask for. ── */
4948
+ .chip rel-avatar {
4586
4949
  display: inline-flex;
4587
- align-items: center;
4588
- justify-content: center;
4589
- width: 16px;
4590
- height: 16px;
4591
4950
  flex-shrink: 0;
4592
4951
  }
4593
4952
 
4594
- .chip-icon * {
4595
- width: 100%;
4596
- height: 100%;
4953
+ :host([variant="fill"]) .chip rel-avatar {
4954
+ --rel-avatar-bg-fill: rgba(255, 255, 255, 0.25);
4955
+ --rel-avatar-color-fill: #ffffff;
4597
4956
  }
4598
4957
 
4599
- .chip-icon ::slotted(svg),
4600
- .chip-icon svg {
4601
- width: 16px;
4602
- height: 16px;
4603
- fill: currentColor;
4958
+ :host([variant="subtle"]) .chip rel-avatar {
4959
+ --rel-avatar-bg-fill: rgba(11, 11, 11, 0.12);
4960
+ --rel-avatar-color-fill: currentColor;
4604
4961
  }
4605
4962
 
4963
+ /* ── Remove (close) button ── */
4606
4964
  .chip-remove {
4607
- margin-left: var(--rel-spacing-space-3xs);
4965
+ display: inline-flex;
4966
+ align-items: center;
4967
+ justify-content: center;
4968
+ flex-shrink: 0;
4608
4969
  cursor: pointer;
4609
4970
  opacity: 0.7;
4610
4971
  background: none;
@@ -4620,86 +4981,85 @@ RelChip.styles = css14`
4620
4981
  }
4621
4982
 
4622
4983
  .chip-remove:focus-visible {
4623
- outline: 2px solid var(--rel-colors-white);
4984
+ outline: 1.5px solid currentColor;
4624
4985
  outline-offset: 1px;
4625
4986
  border-radius: 2px;
4626
4987
  }
4627
4988
 
4628
- /* DARK THEME */
4629
- /* NOTE: #717171 (chip-default dark color) has no exact vars-v2 token */
4630
- /* NOTE: #FFFBF5 (chip-orange dark bg) has no exact vars-v2 token;
4631
- nearest is --rel-colors-gray-light (#FAFAFA) */
4632
-
4633
- /* Reinforce layout — external dark-mode stylesheets can override display/width on the host */
4634
- :host-context([data-theme="dark"]) .chip {
4635
- display: inline-flex;
4636
- width: auto;
4637
- }
4638
-
4639
- :host-context([data-theme="dark"]) .chip-default {
4640
- /* --rel-colors-gray-screen-bg flips to #262626 in dark — hardcoded to preserve #EEEEEE */
4641
- background: #EEEEEE;
4642
- color: #717171;
4989
+ :host([size="lg"]) .chip-remove {
4990
+ --rel-icon-size: 16px;
4643
4991
  }
4644
-
4645
- :host-context([data-theme="dark"]) .chip-blue {
4646
- /* --rel-colors-blue-bg flips to #0f1e2c in dark mode — hardcoded to preserve #E1F2FF */
4647
- background: #E1F2FF;
4648
- color: var(--rel-colors-blue-tertiary);
4992
+ :host([size="md"]) .chip-remove {
4993
+ --rel-icon-size: 14px;
4649
4994
  }
4650
-
4651
- :host-context([data-theme="dark"]) .chip-orange {
4652
- background: #FFFBF5;
4653
- color: var(--rel-colors-yellow-pending);
4995
+ :host([size="sm"]) .chip-remove {
4996
+ --rel-icon-size: 12px;
4654
4997
  }
4655
4998
 
4656
- :host-context([data-theme="dark"]) .chip-red {
4657
- background: var(--rel-colors-red-light);
4658
- color: var(--rel-colors-red-primary);
4999
+ /* ── Dark mode — Figma had no dark-mode sample for this new component
5000
+ set. Fill stays unchanged (the saturated tones already read fine on
5001
+ dark surfaces); Subtle gets a dark-tinted background, following the
5002
+ same invert pattern used elsewhere in this design system. Flagged in
5003
+ the handoff notes — adjust if exact values exist.
5004
+ No [data-theme="dark"] :host(...) fallback here — :host() can never
5005
+ be preceded by a combinator, so that form is invalid and silently
5006
+ matches nothing (the exact bug hit and fixed multiple times in
5007
+ rel-avatar/rel-select earlier this session). :host-context() alone
5008
+ has universal modern browser support, so no fallback is needed. ── */
5009
+ :host-context([data-theme="dark"])[tone="neutral"][variant="subtle"] .chip {
5010
+ background: #333333;
5011
+ color: #f5f5f5;
4659
5012
  }
4660
5013
 
4661
- :host-context([data-theme="dark"]) .chip-green {
4662
- background: var(--rel-colors-green-bg-light);
4663
- color: var(--rel-colors-green-tertiary);
5014
+ :host-context([data-theme="dark"])[tone="danger"][variant="subtle"] .chip {
5015
+ background: #3d1414;
5016
+ color: #ff8080;
4664
5017
  }
4665
5018
 
4666
- /* AVATAR — dark mode (per tone: bg = light fill color, text = white) */
4667
- :host-context([data-theme="dark"]) .chip-default rel-avatar {
4668
- --rel-colors-gray-disabled-text: #717171;
4669
- --rel-avatar-color: #ffffff;
5019
+ :host-context([data-theme="dark"])[tone="warning"][variant="subtle"] .chip {
5020
+ background: #3d2e0a;
5021
+ color: #ffd980;
4670
5022
  }
4671
5023
 
4672
- :host-context([data-theme="dark"]) .chip-blue rel-avatar {
4673
- --rel-colors-gray-disabled-text: #0059F4;
4674
- --rel-avatar-color: #ffffff;
5024
+ :host-context([data-theme="dark"])[tone="success"][variant="subtle"] .chip {
5025
+ background: #0d2e22;
5026
+ color: #4ddba3;
4675
5027
  }
4676
5028
 
4677
- :host-context([data-theme="dark"]) .chip-orange rel-avatar {
4678
- --rel-colors-gray-disabled-text: #FFBF43;
4679
- --rel-avatar-color: #ffffff;
5029
+ :host-context([data-theme="dark"])[tone="info"][variant="subtle"] .chip {
5030
+ background: #0a2e45;
5031
+ color: #66c2ff;
4680
5032
  }
4681
5033
 
4682
- :host-context([data-theme="dark"]) .chip-red rel-avatar {
4683
- --rel-colors-gray-disabled-text: #CC0000;
4684
- --rel-avatar-color: #ffffff;
5034
+ :host-context([data-theme="dark"])[tone="neutral"][variant="fill"] .chip {
5035
+ background: #f5f5f5;
5036
+ color: #0b0b0b;
4685
5037
  }
4686
5038
 
4687
- :host-context([data-theme="dark"]) .chip-green rel-avatar {
4688
- --rel-colors-gray-disabled-text: #00A86B;
4689
- --rel-avatar-color: #ffffff;
5039
+ :host-context([data-theme="dark"]) .chip-remove:focus-visible {
5040
+ outline-color: currentColor;
4690
5041
  }
4691
5042
  `;
4692
5043
  __decorateClass([
4693
5044
  property13({ type: String })
4694
5045
  ], RelChip.prototype, "label", 2);
4695
5046
  __decorateClass([
4696
- property13({ type: String })
5047
+ property13({ type: String, reflect: true })
4697
5048
  ], RelChip.prototype, "tone", 2);
4698
5049
  __decorateClass([
4699
- property13({ type: String })
5050
+ property13({ type: String, reflect: true })
5051
+ ], RelChip.prototype, "variant", 2);
5052
+ __decorateClass([
5053
+ property13({ type: String, reflect: true })
5054
+ ], RelChip.prototype, "size", 2);
5055
+ __decorateClass([
5056
+ property13({ type: String, reflect: true })
5057
+ ], RelChip.prototype, "border", 2);
5058
+ __decorateClass([
5059
+ property13({ type: String, attribute: "leading-icon" })
4700
5060
  ], RelChip.prototype, "leadingIcon", 2);
4701
5061
  __decorateClass([
4702
- property13({ type: String })
5062
+ property13({ type: String, attribute: "trailing-icon" })
4703
5063
  ], RelChip.prototype, "trailingIcon", 2);
4704
5064
  __decorateClass([
4705
5065
  property13({ type: String })
@@ -4710,6 +5070,12 @@ __decorateClass([
4710
5070
  __decorateClass([
4711
5071
  property13({ type: Boolean, reflect: true })
4712
5072
  ], RelChip.prototype, "removed", 2);
5073
+ __decorateClass([
5074
+ property13({ type: Boolean, attribute: "draggable-chip" })
5075
+ ], RelChip.prototype, "draggableChip", 2);
5076
+ __decorateClass([
5077
+ state5()
5078
+ ], RelChip.prototype, "dragging", 2);
4713
5079
  RelChip = __decorateClass([
4714
5080
  customElement14("rel-chip")
4715
5081
  ], RelChip);
@@ -4855,7 +5221,7 @@ RelDivider = __decorateClass([
4855
5221
 
4856
5222
  // src/components/rel-drawer/rel-drawer.ts
4857
5223
  import { LitElement as LitElement18, html as html18, css as css18 } from "lit";
4858
- import { customElement as customElement18, property as property16, state as state5, query as query4 } from "lit/decorators.js";
5224
+ import { customElement as customElement18, property as property16, state as state6, query as query4 } from "lit/decorators.js";
4859
5225
  import "@reliability-design/icons/rel-icon";
4860
5226
 
4861
5227
  // src/components/rel-drawer/rel-drawer-footer.ts
@@ -4920,7 +5286,7 @@ var RelDrawer = class extends LitElement18 {
4920
5286
  }
4921
5287
  const firstFocusable = focusable[0];
4922
5288
  const lastFocusable = focusable[focusable.length - 1];
4923
- const activeElement = this.shadowRoot?.activeElement || document.activeElement;
5289
+ const activeElement = document.activeElement;
4924
5290
  if (e.shiftKey) {
4925
5291
  if (activeElement === firstFocusable) {
4926
5292
  e.preventDefault();
@@ -4994,7 +5360,7 @@ var RelDrawer = class extends LitElement18 {
4994
5360
  this.lockScroll();
4995
5361
  if (this.modal) {
4996
5362
  this.updateComplete.then(() => {
4997
- const focusTarget = this.shadowRoot?.querySelector("[autofocus], .close-button, .panel");
5363
+ const focusTarget = this.querySelector("[autofocus]") ?? this.querySelector(".close-button") ?? this.querySelector(".panel");
4998
5364
  focusTarget?.focus();
4999
5365
  });
5000
5366
  }
@@ -5404,10 +5770,10 @@ __decorateClass([
5404
5770
  property16({ type: String })
5405
5771
  ], RelDrawer.prototype, "description", 2);
5406
5772
  __decorateClass([
5407
- state5()
5773
+ state6()
5408
5774
  ], RelDrawer.prototype, "isDragging", 2);
5409
5775
  __decorateClass([
5410
- state5()
5776
+ state6()
5411
5777
  ], RelDrawer.prototype, "dragOffset", 2);
5412
5778
  __decorateClass([
5413
5779
  query4(".panel")
@@ -5583,7 +5949,7 @@ RelLayout = __decorateClass([
5583
5949
 
5584
5950
  // src/components/rel-menu/rel-menu.ts
5585
5951
  import { LitElement as LitElement21, html as html21 } from "lit";
5586
- import { customElement as customElement21, property as property19, state as state6 } from "lit/decorators.js";
5952
+ import { customElement as customElement21, property as property19, state as state7 } from "lit/decorators.js";
5587
5953
  import "./vars-v2-VMGWTFJZ.css";
5588
5954
  var RelMenuItem = class extends LitElement21 {
5589
5955
  constructor() {
@@ -5922,10 +6288,10 @@ __decorateClass([
5922
6288
  property19({ type: Array })
5923
6289
  ], RelMenu.prototype, "items", 2);
5924
6290
  __decorateClass([
5925
- state6()
6291
+ state7()
5926
6292
  ], RelMenu.prototype, "focusedIndex", 2);
5927
6293
  __decorateClass([
5928
- state6()
6294
+ state7()
5929
6295
  ], RelMenu.prototype, "_items", 2);
5930
6296
  RelMenu = __decorateClass([
5931
6297
  customElement21("rel-menu")
@@ -5933,7 +6299,7 @@ RelMenu = __decorateClass([
5933
6299
 
5934
6300
  // src/components/rel-menubar/rel-menubar.ts
5935
6301
  import { LitElement as LitElement23, html as html23 } from "lit";
5936
- import { customElement as customElement23, state as state7 } from "lit/decorators.js";
6302
+ import { customElement as customElement23, state as state8 } from "lit/decorators.js";
5937
6303
  import "@reliability-design/icons/rel-icon";
5938
6304
 
5939
6305
  // src/components/rel-radio/rel-radio.ts
@@ -5977,10 +6343,13 @@ var RelRadio = class extends LitElement22 {
5977
6343
  writeValue(value) {
5978
6344
  this.checked = value === this.value;
5979
6345
  }
6346
+ get hasSelection() {
6347
+ return this.selectedValue !== null && this.selectedValue !== "";
6348
+ }
5980
6349
  renderOption(option) {
5981
6350
  const isChecked = this.selectedValue === option.value;
5982
6351
  const isDisabled = this.disabled || option.disabled;
5983
- const isErrorActive = this.error && !isChecked;
6352
+ const isErrorActive = this.error && !this.hasSelection;
5984
6353
  const classes = [
5985
6354
  "rel-radio-option",
5986
6355
  isDisabled ? "disabled" : "",
@@ -6010,7 +6379,7 @@ var RelRadio = class extends LitElement22 {
6010
6379
  <div class="rel-radio-group">
6011
6380
  ${this.options.map((o) => this.renderOption(o))}
6012
6381
  </div>
6013
- ${this.error && this.errorMessage ? html22`<div class="error-message">${this.errorMessage}</div>` : ""}
6382
+ ${this.error && this.errorMessage && !this.hasSelection ? html22`<div class="error-message">${this.errorMessage}</div>` : ""}
6014
6383
  `;
6015
6384
  }
6016
6385
  };
@@ -6023,16 +6392,15 @@ RelRadio.styles = css21`
6023
6392
  .rel-radio-group {
6024
6393
  display: flex;
6025
6394
  flex-direction: column;
6395
+ align-items: flex-start;
6026
6396
  gap: var(--rel-spacing-space-xs);
6027
6397
  }
6028
6398
 
6029
6399
  .rel-radio-option {
6030
- display: flex;
6400
+ display: inline-flex;
6031
6401
  flex-direction: column;
6032
6402
  gap: var(--rel-spacing-space-3xs);
6033
6403
  cursor: pointer;
6034
- padding: 4px 6px;
6035
- margin: -4px -6px;
6036
6404
  }
6037
6405
 
6038
6406
  .rel-radio-option.disabled {
@@ -6040,10 +6408,6 @@ RelRadio.styles = css21`
6040
6408
  cursor: not-allowed !important;
6041
6409
  }
6042
6410
 
6043
- .rel-radio-option:not(.disabled):hover {
6044
- background: var(--rel-color-bg-hover, #f5f5f5);
6045
- }
6046
-
6047
6411
  .rel-radio-option:not(.disabled):hover .radio-custom {
6048
6412
  border-color: #525252;
6049
6413
  }
@@ -6057,8 +6421,8 @@ RelRadio.styles = css21`
6057
6421
  }
6058
6422
 
6059
6423
  .rel-radio-option:focus-within:has(input:focus-visible) {
6060
- outline: 1px solid #000000;
6061
- outline-offset: 0;
6424
+ outline: 1.5px solid #000000;
6425
+ outline-offset: 1px;
6062
6426
  }
6063
6427
 
6064
6428
  .radio-main {
@@ -6091,15 +6455,15 @@ RelRadio.styles = css21`
6091
6455
  }
6092
6456
 
6093
6457
  .radio-label {
6094
- font-size: var(--rel-fontSizes-sm);
6458
+ font-size: var(--rel-fontSizes-md, 16px);
6095
6459
  font-weight: var(--rel-fontWeights-medium);
6096
6460
  color: var(--rel-color-text-primary);
6097
6461
  }
6098
6462
 
6099
6463
  .radio-supporting {
6100
- font-size: var(--rel-fontSizes-xs);
6464
+ font-size: var(--rel-fontSizes-sm, 12px);
6101
6465
  margin-left: 28px;
6102
- color: var(--rel-color-text-placeholder);
6466
+ color: #7D7D7D;
6103
6467
  }
6104
6468
 
6105
6469
  /* Error state — unchecked only */
@@ -6117,7 +6481,7 @@ RelRadio.styles = css21`
6117
6481
 
6118
6482
  /* Error message below group */
6119
6483
  .error-message {
6120
- font-size: var(--rel-fontSizes-xs, 10px);
6484
+ font-size: var(--rel-fontSizes-sm, 12px);
6121
6485
  color: #CE3131;
6122
6486
  margin-top: var(--rel-spacing-space-2xs, 4px);
6123
6487
  }
@@ -6140,7 +6504,8 @@ RelRadio.styles = css21`
6140
6504
 
6141
6505
  :host-context([data-theme="dark"]) .rel-radio-option:focus-within:has(input:focus-visible),
6142
6506
  :host-context(.dark) .rel-radio-option:focus-within:has(input:focus-visible) {
6143
- outline-color: var(--rel-color-text-primary, #F5F5F5);
6507
+ outline: 1.5px solid var(--rel-color-text-primary, #F5F5F5);
6508
+ outline-offset: 1px;
6144
6509
  }
6145
6510
  `;
6146
6511
  __decorateClass([
@@ -6567,6 +6932,7 @@ RelMenubar._css = `
6567
6932
  font-family: var(--rel-fontFamilies-primary);
6568
6933
  font-size: var(--rel-fontSizes-sm);
6569
6934
  height: 40px;
6935
+ width: fit-content;
6570
6936
  }
6571
6937
 
6572
6938
  .menubar-trigger {
@@ -6692,19 +7058,19 @@ RelMenubar._css = `
6692
7058
  }
6693
7059
  `;
6694
7060
  __decorateClass([
6695
- state7()
7061
+ state8()
6696
7062
  ], RelMenubar.prototype, "menus", 2);
6697
7063
  __decorateClass([
6698
- state7()
7064
+ state8()
6699
7065
  ], RelMenubar.prototype, "openMenuIndex", 2);
6700
7066
  __decorateClass([
6701
- state7()
7067
+ state8()
6702
7068
  ], RelMenubar.prototype, "focusedTriggerIndex", 2);
6703
7069
  __decorateClass([
6704
- state7()
7070
+ state8()
6705
7071
  ], RelMenubar.prototype, "focusedItemIndex", 2);
6706
7072
  __decorateClass([
6707
- state7()
7073
+ state8()
6708
7074
  ], RelMenubar.prototype, "openSubmenuElement", 2);
6709
7075
  RelMenubar = __decorateClass([
6710
7076
  customElement23("rel-menubar")
@@ -6837,7 +7203,7 @@ RelNavbar = __decorateClass([
6837
7203
 
6838
7204
  // src/components/rel-topbar/rel-topbar.ts
6839
7205
  import { LitElement as LitElement32, html as html32, css as css29 } from "lit";
6840
- import { customElement as customElement32, property as property25, state as state8 } from "lit/decorators.js";
7206
+ import { customElement as customElement32, property as property25, state as state9 } from "lit/decorators.js";
6841
7207
  import "./vars-v2-VMGWTFJZ.css";
6842
7208
  import "@reliability-design/icons/rel-icon";
6843
7209
 
@@ -7437,10 +7803,10 @@ __decorateClass([
7437
7803
  property25({ type: String })
7438
7804
  ], RelTopbar.prototype, "forceLayout", 2);
7439
7805
  __decorateClass([
7440
- state8()
7806
+ state9()
7441
7807
  ], RelTopbar.prototype, "_overflowCount", 2);
7442
7808
  __decorateClass([
7443
- state8()
7809
+ state9()
7444
7810
  ], RelTopbar.prototype, "_overflowItemsData", 2);
7445
7811
  RelTopbar = __decorateClass([
7446
7812
  customElement32("rel-topbar")
@@ -7448,7 +7814,7 @@ RelTopbar = __decorateClass([
7448
7814
 
7449
7815
  // src/components/rel-topbar/rel-topbar-item.ts
7450
7816
  import { LitElement as LitElement33, html as html33, css as css30 } from "lit";
7451
- import { customElement as customElement33, property as property26, state as state9 } from "lit/decorators.js";
7817
+ import { customElement as customElement33, property as property26, state as state10 } from "lit/decorators.js";
7452
7818
  import "./vars-v2-VMGWTFJZ.css";
7453
7819
  import "@reliability-design/icons/rel-icon";
7454
7820
  var RelTopbarItem = class extends LitElement33 {
@@ -7732,7 +8098,7 @@ __decorateClass([
7732
8098
  property26({ type: String })
7733
8099
  ], RelTopbarItem.prototype, "value", 2);
7734
8100
  __decorateClass([
7735
- state9()
8101
+ state10()
7736
8102
  ], RelTopbarItem.prototype, "_hasDropdown", 2);
7737
8103
  RelTopbarItem = __decorateClass([
7738
8104
  customElement33("rel-topbar-item")
@@ -7954,7 +8320,7 @@ RelTopbarProfile = __decorateClass([
7954
8320
 
7955
8321
  // src/components/rel-otp/rel-otp.ts
7956
8322
  import { LitElement as LitElement35, html as html35, css as css32 } from "lit";
7957
- import { customElement as customElement35, property as property28, state as state10, query as query5 } from "lit/decorators.js";
8323
+ import { customElement as customElement35, property as property28, state as state11, query as query5 } from "lit/decorators.js";
7958
8324
  var RelOtp = class extends LitElement35 {
7959
8325
  constructor() {
7960
8326
  super(...arguments);
@@ -8420,7 +8786,7 @@ __decorateClass([
8420
8786
  property28({ type: String })
8421
8787
  ], RelOtp.prototype, "size", 2);
8422
8788
  __decorateClass([
8423
- state10()
8789
+ state11()
8424
8790
  ], RelOtp.prototype, "cells", 2);
8425
8791
  __decorateClass([
8426
8792
  query5(".hidden-input")
@@ -8431,18 +8797,18 @@ RelOtp = __decorateClass([
8431
8797
 
8432
8798
  // src/components/rel-pagination/rel-pagination.ts
8433
8799
  import { LitElement as LitElement36, html as html36, css as css33 } from "lit";
8434
- import { customElement as customElement36, property as property29, state as state11 } from "lit/decorators.js";
8800
+ import { customElement as customElement36, property as property29, state as state12 } from "lit/decorators.js";
8435
8801
  import "./vars-v2-VMGWTFJZ.css";
8436
8802
  var RelPagination = class extends LitElement36 {
8437
8803
  constructor() {
8438
8804
  super(...arguments);
8805
+ this.type = "extended";
8439
8806
  this.defaultPage = 1;
8440
8807
  this.totalPages = 0;
8441
- this.siblingCount = 1;
8442
- this.boundaryCount = 1;
8808
+ this.totalItems = 0;
8809
+ this.perPage = 10;
8810
+ this.showLabel = false;
8443
8811
  this.disabled = false;
8444
- this.density = "comfortable";
8445
- this.variant = "default";
8446
8812
  this.hrefTemplate = "";
8447
8813
  this.ariaLabel = "Pagination";
8448
8814
  this.currentPage = 1;
@@ -8450,17 +8816,15 @@ var RelPagination = class extends LitElement36 {
8450
8816
  connectedCallback() {
8451
8817
  super.connectedCallback();
8452
8818
  const totalPagesAttr = this.getAttribute("total-pages");
8453
- if (totalPagesAttr) {
8454
- this.totalPages = Number(totalPagesAttr);
8455
- }
8819
+ if (totalPagesAttr) this.totalPages = Number(totalPagesAttr);
8456
8820
  const pageAttr = this.getAttribute("page");
8457
- if (pageAttr) {
8458
- this.page = Number(pageAttr);
8459
- }
8821
+ if (pageAttr) this.page = Number(pageAttr);
8460
8822
  const defaultPageAttr = this.getAttribute("default-page");
8461
- if (defaultPageAttr) {
8462
- this.defaultPage = Number(defaultPageAttr);
8463
- }
8823
+ if (defaultPageAttr) this.defaultPage = Number(defaultPageAttr);
8824
+ const totalItemsAttr = this.getAttribute("total-items");
8825
+ if (totalItemsAttr) this.totalItems = Number(totalItemsAttr);
8826
+ const perPageAttr = this.getAttribute("per-page");
8827
+ if (perPageAttr) this.perPage = Number(perPageAttr);
8464
8828
  this.currentPage = this.page ?? this.defaultPage;
8465
8829
  }
8466
8830
  updated(changedProperties) {
@@ -8471,47 +8835,43 @@ var RelPagination = class extends LitElement36 {
8471
8835
  get activePage() {
8472
8836
  return this.page ?? this.currentPage;
8473
8837
  }
8474
- generatePageItems() {
8475
- const items = [];
8838
+ get computedTotalPages() {
8839
+ if (this.totalPages > 0) return this.totalPages;
8840
+ if (this.totalItems > 0 && this.perPage > 0) {
8841
+ return Math.ceil(this.totalItems / this.perPage);
8842
+ }
8843
+ return 0;
8844
+ }
8845
+ generatePageNumbers() {
8846
+ const pages = [];
8476
8847
  const current = this.activePage;
8477
- const total = this.totalPages;
8478
- if (total <= 0) return items;
8479
- items.push({ type: "prev" });
8848
+ const total = this.computedTotalPages;
8849
+ if (total <= 0) return pages;
8480
8850
  if (total <= 7) {
8481
- for (let i = 1; i <= total; i++) {
8482
- items.push({ type: "page", value: i });
8483
- }
8851
+ for (let i = 1; i <= total; i++) pages.push(i);
8484
8852
  } else if (current <= 4) {
8485
- for (let i = 1; i <= 5; i++) {
8486
- items.push({ type: "page", value: i });
8487
- }
8488
- items.push({ type: "ellipsis" });
8489
- items.push({ type: "page", value: total });
8853
+ for (let i = 1; i <= 5; i++) pages.push(i);
8854
+ pages.push(-1);
8855
+ pages.push(total);
8490
8856
  } else if (current >= total - 3) {
8491
- items.push({ type: "page", value: 1 });
8492
- items.push({ type: "ellipsis" });
8493
- for (let i = total - 4; i <= total; i++) {
8494
- items.push({ type: "page", value: i });
8495
- }
8857
+ pages.push(1);
8858
+ pages.push(-1);
8859
+ for (let i = total - 4; i <= total; i++) pages.push(i);
8496
8860
  } else {
8497
- items.push({ type: "page", value: 1 });
8498
- items.push({ type: "ellipsis" });
8499
- items.push({ type: "page", value: current - 1 });
8500
- items.push({ type: "page", value: current });
8501
- items.push({ type: "page", value: current + 1 });
8502
- items.push({ type: "ellipsis" });
8503
- items.push({ type: "page", value: total });
8861
+ pages.push(1);
8862
+ pages.push(-1);
8863
+ pages.push(current - 1);
8864
+ pages.push(current);
8865
+ pages.push(current + 1);
8866
+ pages.push(-1);
8867
+ pages.push(total);
8504
8868
  }
8505
- items.push({ type: "next" });
8506
- return items;
8869
+ return pages;
8507
8870
  }
8508
8871
  handlePageChange(newPage) {
8509
- if (this.disabled || newPage < 1 || newPage > this.totalPages || newPage === this.activePage) {
8510
- return;
8511
- }
8512
- if (this.page === void 0) {
8513
- this.currentPage = newPage;
8514
- }
8872
+ const total = this.computedTotalPages;
8873
+ if (this.disabled || newPage < 1 || newPage > total || newPage === this.activePage) return;
8874
+ if (this.page === void 0) this.currentPage = newPage;
8515
8875
  this.dispatchEvent(
8516
8876
  new CustomEvent("rel-change", {
8517
8877
  detail: { page: newPage },
@@ -8520,292 +8880,335 @@ var RelPagination = class extends LitElement36 {
8520
8880
  })
8521
8881
  );
8522
8882
  }
8523
- getHref(page) {
8524
- if (!this.hrefTemplate) return "#";
8525
- return this.hrefTemplate.replace(/\{page\}/, String(page));
8883
+ renderChevronLeft() {
8884
+ return html36`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6"/></svg>`;
8526
8885
  }
8527
- handleKeyDown(event, callback) {
8528
- if (event.key === "Enter" || event.key === " ") {
8529
- event.preventDefault();
8530
- callback();
8531
- }
8886
+ renderChevronRight() {
8887
+ return html36`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18l6-6-6-6"/></svg>`;
8532
8888
  }
8533
- renderPrevIcon() {
8889
+ renderNavBtn(dir) {
8890
+ const current = this.activePage;
8891
+ const total = this.computedTotalPages;
8892
+ const isPrev = dir === "prev";
8893
+ const isDisabled = isPrev ? current <= 1 : current >= total;
8894
+ const targetPage = isPrev ? current - 1 : current + 1;
8534
8895
  return html36`
8535
- <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
8536
- <path d="M15 18l-6-6 6-6" />
8537
- </svg>
8896
+ <button
8897
+ type="button"
8898
+ class="pag-nav-btn"
8899
+ aria-label="${isPrev ? "Previous page" : "Next page"}"
8900
+ ?disabled="${isDisabled}"
8901
+ @click="${() => this.handlePageChange(targetPage)}"
8902
+ >
8903
+ ${isPrev ? this.renderChevronLeft() : this.renderChevronRight()}
8904
+ </button>
8538
8905
  `;
8539
8906
  }
8540
- renderNextIcon() {
8907
+ renderExtended() {
8908
+ const pages = this.generatePageNumbers();
8909
+ const current = this.activePage;
8910
+ const total = this.computedTotalPages;
8541
8911
  return html36`
8542
- <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
8543
- <path d="M9 18l6-6-6-6" />
8544
- </svg>
8912
+ <div class="pag-root" role="navigation" aria-label="${this.ariaLabel}">
8913
+ <div class="pag-stack">
8914
+ ${this.renderNavBtn("prev")}
8915
+ <div class="pag-numbers">
8916
+ ${pages.map(
8917
+ (p) => p === -1 ? html36`<span class="pag-ellipsis">...</span>` : html36`<button
8918
+ type="button"
8919
+ class="pag-page-btn"
8920
+ aria-label="Page ${p}"
8921
+ aria-current="${p === current ? "page" : "false"}"
8922
+ @click="${() => this.handlePageChange(p)}"
8923
+ >${p}</button>`
8924
+ )}
8925
+ </div>
8926
+ ${this.renderNavBtn("next")}
8927
+ </div>
8928
+ ${this.showLabel ? html36`<span class="pag-label">Viewing page ${current} of ${total}</span>` : null}
8929
+ </div>
8545
8930
  `;
8546
8931
  }
8547
- renderItem(item) {
8932
+ renderCompact() {
8548
8933
  const current = this.activePage;
8549
- const useLinks = !!this.hrefTemplate;
8550
- if (item.type === "spacer") {
8551
- return html36`<span class="pagination-spacer"></span>`;
8552
- }
8553
- if (item.type === "ellipsis") {
8554
- return html36`<span class="ellipsis">…</span>`;
8555
- }
8556
- if (item.type === "prev") {
8557
- const disabled = current === 1 || this.disabled;
8558
- const targetPage = current - 1;
8559
- if (useLinks) {
8560
- const href = disabled ? "#" : this.getHref(targetPage);
8561
- return html36`
8562
- <a
8563
- href="${href}"
8564
- class="prev-btn"
8565
- aria-label="Go to previous page"
8566
- aria-disabled="${disabled}"
8567
- @click="${(e) => {
8568
- if (disabled) {
8569
- e.preventDefault();
8570
- return;
8571
- }
8572
- e.preventDefault();
8573
- this.handlePageChange(targetPage);
8574
- }}"
8575
- >
8576
- ${this.variant === "icons" ? this.renderPrevIcon() : "Previous"}
8577
- </a>
8578
- `;
8579
- }
8580
- return html36`
8581
- <button
8582
- type="button"
8583
- class="prev-btn"
8584
- aria-label="Go to previous page"
8585
- ?disabled="${disabled}"
8586
- @click="${() => this.handlePageChange(targetPage)}"
8587
- >
8588
- ${this.variant === "icons" ? this.renderPrevIcon() : "Previous"}
8589
- </button>
8590
- `;
8591
- }
8592
- if (item.type === "next") {
8593
- const disabled = current === this.totalPages || this.disabled;
8594
- const targetPage = current + 1;
8595
- if (useLinks) {
8596
- const href = disabled ? "#" : this.getHref(targetPage);
8597
- return html36`
8598
- <a
8599
- href="${href}"
8600
- class="next-btn"
8601
- aria-label="Go to next page"
8602
- aria-disabled="${disabled}"
8603
- @click="${(e) => {
8604
- if (disabled) {
8605
- e.preventDefault();
8606
- return;
8607
- }
8608
- e.preventDefault();
8609
- this.handlePageChange(targetPage);
8610
- }}"
8611
- >
8612
- ${this.variant === "icons" ? this.renderNextIcon() : "Next"}
8613
- </a>
8614
- `;
8615
- }
8616
- return html36`
8617
- <button
8618
- type="button"
8619
- class="next-btn"
8620
- aria-label="Go to next page"
8621
- ?disabled="${disabled}"
8622
- @click="${() => this.handlePageChange(targetPage)}"
8623
- >
8624
- ${this.variant === "icons" ? this.renderNextIcon() : "Next"}
8625
- </button>
8626
- `;
8627
- }
8628
- const pageNum = item.value;
8629
- const isCurrent = pageNum === current;
8630
- if (useLinks) {
8631
- const href = this.getHref(pageNum);
8632
- return html36`
8633
- <a
8634
- href="${href}"
8635
- aria-label="Go to page ${pageNum}"
8636
- aria-current="${isCurrent ? "page" : "false"}"
8637
- @click="${(e) => {
8638
- e.preventDefault();
8639
- this.handlePageChange(pageNum);
8640
- }}"
8641
- >
8642
- ${pageNum}
8643
- </a>
8644
- `;
8645
- }
8934
+ const total = this.computedTotalPages;
8646
8935
  return html36`
8647
- <button
8648
- type="button"
8649
- aria-label="Go to page ${pageNum}"
8650
- aria-current="${isCurrent ? "page" : "false"}"
8651
- @click="${() => this.handlePageChange(pageNum)}"
8652
- >
8653
- ${pageNum}
8654
- </button>
8936
+ <div class="pag-stack" role="navigation" aria-label="${this.ariaLabel}">
8937
+ ${this.renderNavBtn("prev")}
8938
+ <span class="pag-page-text">Page ${current} of ${total}</span>
8939
+ ${this.renderNavBtn("next")}
8940
+ </div>
8655
8941
  `;
8656
8942
  }
8657
- render() {
8658
- const items = this.generatePageItems();
8943
+ renderCountText() {
8944
+ const current = this.activePage;
8945
+ const total = this.computedTotalPages;
8946
+ const effectiveTotalItems = this.totalItems > 0 ? this.totalItems : total * this.perPage;
8947
+ const start = (current - 1) * this.perPage + 1;
8948
+ const end = Math.min(current * this.perPage, effectiveTotalItems);
8659
8949
  return html36`
8660
- <nav
8661
- class="${this.density === "compact" ? "compact" : ""}"
8662
- aria-label="${this.ariaLabel}"
8663
- role="navigation"
8664
- >
8665
- ${items.map((item) => this.renderItem(item))}
8666
- </nav>
8950
+ <div class="pag-count" role="navigation" aria-label="${this.ariaLabel}">
8951
+ <span class="pag-count-text">${start}–${end} of ${effectiveTotalItems}</span>
8952
+ <div class="pag-count-nav">
8953
+ ${this.renderNavBtn("prev")}
8954
+ <span class="pag-current-num">${current}</span>
8955
+ ${this.renderNavBtn("next")}
8956
+ </div>
8957
+ </div>
8667
8958
  `;
8668
8959
  }
8960
+ render() {
8961
+ if (this.type === "compact") return this.renderCompact();
8962
+ if (this.type === "count-text") return this.renderCountText();
8963
+ return this.renderExtended();
8964
+ }
8669
8965
  };
8670
8966
  RelPagination.styles = css33`
8671
8967
  :host {
8672
8968
  display: inline-block;
8673
- font-family: var(--rel-fontFamilies-primary);
8969
+ font-family: var(--rel-fontFamilies-primary, 'Poppins', sans-serif);
8674
8970
  }
8675
8971
 
8676
- nav {
8972
+ :host([type="count-text"]) {
8973
+ display: block;
8974
+ width: 100%;
8975
+ }
8976
+
8977
+ :host([disabled]) {
8978
+ opacity: 0.5;
8979
+ cursor: not-allowed;
8980
+ }
8981
+
8982
+ :host([disabled]) button {
8983
+ pointer-events: none;
8984
+ }
8985
+
8986
+ /* ── Root / Stack containers ──────────────────────────────── */
8987
+
8988
+ .pag-root {
8677
8989
  display: flex;
8990
+ flex-direction: column;
8678
8991
  align-items: center;
8679
- gap: var(--rel-spacing-space-2xs);
8680
- min-width: max-content;
8992
+ gap: 16px;
8681
8993
  }
8682
8994
 
8683
- nav.compact {
8684
- gap: var(--rel-spacing-space-3xs);
8995
+ .pag-stack {
8996
+ display: inline-flex;
8997
+ align-items: center;
8998
+ gap: 12px;
8685
8999
  }
8686
9000
 
8687
- button,
8688
- a {
9001
+ .pag-count {
9002
+ display: flex;
9003
+ align-items: center;
9004
+ justify-content: space-between;
9005
+ gap: 16px;
9006
+ width: 100%;
9007
+ }
9008
+
9009
+ /* count-text right-side nav: no gap (40+24+40 = 104px, matches Figma) */
9010
+ .pag-count-nav {
9011
+ display: inline-flex;
9012
+ align-items: center;
9013
+ }
9014
+
9015
+ /* ── Page number list (tighter 4px gap) ──────────────────── */
9016
+
9017
+ .pag-numbers {
9018
+ display: inline-flex;
9019
+ align-items: center;
9020
+ gap: 4px;
9021
+ }
9022
+
9023
+ /* ── Prev / Next — circular buttons ──────────────────────── */
9024
+
9025
+ .pag-nav-btn {
8689
9026
  display: inline-flex;
8690
9027
  align-items: center;
8691
9028
  justify-content: center;
8692
9029
  width: 40px;
8693
9030
  height: 40px;
8694
9031
  padding: 0;
8695
- font-family: var(--rel-fontFamilies-primary);
8696
- font-size: var(--rel-fontSizes-sm);
8697
- font-weight: var(--rel-fontWeights-medium);
8698
- color: var(--rel-color-text-heading);
8699
- background: var(--rel-color-bg-primary);
8700
- border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);
8701
- border-radius: var(--rel-borders-radius-border-radius-200);
9032
+ border-radius: 1000px;
9033
+ border: 1px solid #e5e5e5;
9034
+ background: #ffffff;
8702
9035
  cursor: pointer;
8703
- transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
8704
- text-decoration: none;
8705
- outline: none;
8706
- user-select: none;
9036
+ color: #0b0b0b;
9037
+ box-sizing: border-box;
9038
+ transition: background 0.15s ease;
9039
+ flex-shrink: 0;
8707
9040
  }
8708
9041
 
8709
- button.prev-btn, button.next-btn,
8710
- a.prev-btn, a.next-btn {
8711
- width: auto;
8712
- padding: 0 var(--rel-spacing-space-sm);
9042
+ .pag-nav-btn:hover:not(:disabled) {
9043
+ background: #f5f5f5;
8713
9044
  }
8714
9045
 
8715
- nav.compact button,
8716
- nav.compact a {
8717
- width: 32px;
8718
- height: 32px;
8719
- padding: 0;
8720
- font-size: var(--rel-fontSizes-xs);
9046
+ .pag-nav-btn:focus-visible {
9047
+ outline: 2px solid var(--rel-color-border-focus, #0059f4);
9048
+ outline-offset: 2px;
8721
9049
  }
8722
9050
 
8723
- nav.compact button.prev-btn, nav.compact button.next-btn,
8724
- nav.compact a.prev-btn, nav.compact a.next-btn {
8725
- width: auto;
8726
- padding: 0 var(--rel-spacing-space-xs);
9051
+ .pag-nav-btn:disabled {
9052
+ opacity: 0.35;
9053
+ cursor: not-allowed;
8727
9054
  }
8728
9055
 
8729
- button:hover:not(:disabled),
8730
- a:hover:not([aria-disabled="true"]) {
8731
- background: var(--rel-color-bg-secondary);
8732
- border-color: var(--rel-color-text-primary);
9056
+ .pag-nav-btn svg {
9057
+ width: 20px;
9058
+ height: 20px;
8733
9059
  }
8734
9060
 
8735
- button:focus-visible,
8736
- a:focus-visible {
8737
- outline: 2px solid var(--rel-colors-blue-primary);
8738
- outline-offset: 2px;
9061
+ /* ── Page number buttons — square with 8px radius ─────────── */
9062
+
9063
+ .pag-page-btn {
9064
+ display: inline-flex;
9065
+ align-items: center;
9066
+ justify-content: center;
9067
+ width: 40px;
9068
+ height: 40px;
9069
+ padding: 8px;
9070
+ border-radius: 8px;
9071
+ border: 1px solid #e5e5e5;
9072
+ background: #ffffff;
9073
+ cursor: pointer;
9074
+ font-family: inherit;
9075
+ font-size: 14px;
9076
+ font-weight: 500;
9077
+ letter-spacing: -0.3px;
9078
+ color: #0b0b0b;
9079
+ line-height: 22px;
9080
+ box-sizing: border-box;
9081
+ transition: background 0.15s ease, border-color 0.15s ease;
8739
9082
  }
8740
9083
 
8741
- button:disabled,
8742
- a[aria-disabled="true"] {
8743
- opacity: 0.5;
8744
- cursor: not-allowed;
9084
+ .pag-page-btn:hover {
9085
+ background: #f5f5f5;
8745
9086
  }
8746
9087
 
8747
- button[aria-current="page"],
8748
- a[aria-current="page"] {
8749
- background: var(--rel-color-bg-selected);
8750
- color: var(--rel-color-text-primary);
8751
- border-color: var(--rel-color-text-heading);
8752
- font-weight: var(--rel-fontWeights-semibold);
9088
+ .pag-page-btn:focus-visible {
9089
+ outline: 2px solid var(--rel-color-border-focus, #0059f4);
9090
+ outline-offset: 2px;
8753
9091
  }
8754
9092
 
8755
- button[aria-current="page"]:hover,
8756
- a[aria-current="page"]:hover {
8757
- background: var(--rel-color-bg-selected);
8758
- border-color: var(--rel-color-text-heading);
9093
+ .pag-page-btn[aria-current="page"] {
9094
+ background: #e5e5e5;
9095
+ border-color: #0b0b0b;
8759
9096
  }
8760
9097
 
8761
- .ellipsis {
9098
+ /* ── Ellipsis ─────────────────────────────────────────────── */
9099
+
9100
+ .pag-ellipsis {
8762
9101
  display: inline-flex;
8763
9102
  align-items: center;
8764
9103
  justify-content: center;
8765
9104
  width: 40px;
8766
9105
  height: 40px;
8767
- color: var(--rel-color-text-placeholder);
8768
- font-size: var(--rel-fontSizes-sm);
9106
+ font-size: 14px;
9107
+ font-weight: 500;
9108
+ letter-spacing: -0.3px;
9109
+ color: #0b0b0b;
8769
9110
  user-select: none;
8770
9111
  }
8771
9112
 
8772
- nav.compact .ellipsis {
8773
- width: 32px;
8774
- height: 32px;
8775
- font-size: var(--rel-fontSizes-xs);
9113
+ /* ── Compact: "Page X of Y" ───────────────────────────────── */
9114
+
9115
+ .pag-page-text {
9116
+ font-size: 14px;
9117
+ font-weight: 500;
9118
+ letter-spacing: -0.3px;
9119
+ color: #0b0b0b;
9120
+ line-height: 22px;
9121
+ white-space: nowrap;
8776
9122
  }
8777
9123
 
8778
- .pagination-spacer {
9124
+ /* ── Count-text: "1-5 of 50" ─────────────────────────────── */
9125
+
9126
+ .pag-count-text {
9127
+ font-size: 14px;
9128
+ font-weight: 500;
9129
+ letter-spacing: -0.3px;
9130
+ color: #0b0b0b;
9131
+ line-height: 22px;
9132
+ white-space: nowrap;
9133
+ }
9134
+
9135
+ /* ── Count-text: inline current page number ───────────────── */
9136
+
9137
+ .pag-current-num {
8779
9138
  display: inline-flex;
8780
- width: 40px;
9139
+ align-items: center;
9140
+ justify-content: center;
9141
+ width: 24px;
8781
9142
  height: 40px;
9143
+ font-size: 14px;
9144
+ font-weight: 500;
9145
+ letter-spacing: -0.3px;
9146
+ color: #0b0b0b;
9147
+ line-height: 22px;
8782
9148
  }
8783
9149
 
8784
- nav.compact .pagination-spacer {
8785
- width: 32px;
8786
- height: 32px;
9150
+ /* ── Extended sub-label ───────────────────────────────────── */
9151
+
9152
+ .pag-label {
9153
+ font-size: 14px;
9154
+ font-weight: 400;
9155
+ letter-spacing: -0.3px;
9156
+ color: #7d7d7d;
9157
+ line-height: 22px;
9158
+ text-align: center;
8787
9159
  }
8788
9160
 
8789
- .icon {
8790
- width: 16px;
8791
- height: 16px;
8792
- display: inline-block;
9161
+ /* ── Dark mode ───────────────────────────────────────────── */
9162
+
9163
+ :host-context([data-theme="dark"]) .pag-nav-btn,
9164
+ [data-theme="dark"] .pag-nav-btn {
9165
+ background: #1a1a1a;
9166
+ border-color: #333333;
9167
+ color: #f5f5f5;
8793
9168
  }
8794
9169
 
8795
- nav.compact .icon {
8796
- width: 14px;
8797
- height: 14px;
9170
+ :host-context([data-theme="dark"]) .pag-nav-btn:hover:not(:disabled),
9171
+ [data-theme="dark"] .pag-nav-btn:hover:not(:disabled) {
9172
+ background: #2b2b2b;
8798
9173
  }
8799
9174
 
8800
- :host([disabled]) {
8801
- cursor: not-allowed;
9175
+ :host-context([data-theme="dark"]) .pag-page-btn,
9176
+ [data-theme="dark"] .pag-page-btn {
9177
+ background: #1a1a1a;
9178
+ border-color: #333333;
9179
+ color: #f5f5f5;
8802
9180
  }
8803
9181
 
8804
- :host([disabled]) nav {
8805
- opacity: 0.5;
8806
- pointer-events: none;
9182
+ :host-context([data-theme="dark"]) .pag-page-btn:hover,
9183
+ [data-theme="dark"] .pag-page-btn:hover {
9184
+ background: #2b2b2b;
9185
+ }
9186
+
9187
+ :host-context([data-theme="dark"]) .pag-page-btn[aria-current="page"],
9188
+ [data-theme="dark"] .pag-page-btn[aria-current="page"] {
9189
+ background: #333333;
9190
+ border-color: #f5f5f5;
9191
+ }
9192
+
9193
+ :host-context([data-theme="dark"]) .pag-ellipsis,
9194
+ :host-context([data-theme="dark"]) .pag-page-text,
9195
+ :host-context([data-theme="dark"]) .pag-count-text,
9196
+ :host-context([data-theme="dark"]) .pag-current-num,
9197
+ [data-theme="dark"] .pag-ellipsis,
9198
+ [data-theme="dark"] .pag-page-text,
9199
+ [data-theme="dark"] .pag-count-text,
9200
+ [data-theme="dark"] .pag-current-num {
9201
+ color: #f5f5f5;
9202
+ }
9203
+
9204
+ :host-context([data-theme="dark"]) .pag-label,
9205
+ [data-theme="dark"] .pag-label {
9206
+ color: #a3a3a3;
8807
9207
  }
8808
9208
  `;
9209
+ __decorateClass([
9210
+ property29({ type: String, reflect: true })
9211
+ ], RelPagination.prototype, "type", 2);
8809
9212
  __decorateClass([
8810
9213
  property29({ type: Number })
8811
9214
  ], RelPagination.prototype, "page", 2);
@@ -8817,19 +9220,16 @@ __decorateClass([
8817
9220
  ], RelPagination.prototype, "totalPages", 2);
8818
9221
  __decorateClass([
8819
9222
  property29({ type: Number })
8820
- ], RelPagination.prototype, "siblingCount", 2);
9223
+ ], RelPagination.prototype, "totalItems", 2);
8821
9224
  __decorateClass([
8822
9225
  property29({ type: Number })
8823
- ], RelPagination.prototype, "boundaryCount", 2);
9226
+ ], RelPagination.prototype, "perPage", 2);
9227
+ __decorateClass([
9228
+ property29({ type: Boolean })
9229
+ ], RelPagination.prototype, "showLabel", 2);
8824
9230
  __decorateClass([
8825
9231
  property29({ type: Boolean, reflect: true })
8826
9232
  ], RelPagination.prototype, "disabled", 2);
8827
- __decorateClass([
8828
- property29({ type: String })
8829
- ], RelPagination.prototype, "density", 2);
8830
- __decorateClass([
8831
- property29({ type: String })
8832
- ], RelPagination.prototype, "variant", 2);
8833
9233
  __decorateClass([
8834
9234
  property29({ type: String })
8835
9235
  ], RelPagination.prototype, "hrefTemplate", 2);
@@ -8837,7 +9237,7 @@ __decorateClass([
8837
9237
  property29({ type: String })
8838
9238
  ], RelPagination.prototype, "ariaLabel", 2);
8839
9239
  __decorateClass([
8840
- state11()
9240
+ state12()
8841
9241
  ], RelPagination.prototype, "currentPage", 2);
8842
9242
  RelPagination = __decorateClass([
8843
9243
  customElement36("rel-pagination")
@@ -8845,7 +9245,7 @@ RelPagination = __decorateClass([
8845
9245
 
8846
9246
  // src/components/rel-popover/rel-popover.ts
8847
9247
  import { LitElement as LitElement37, html as html37, css as css34 } from "lit";
8848
- import { customElement as customElement37, property as property30, state as state12, query as query6 } from "lit/decorators.js";
9248
+ import { customElement as customElement37, property as property30, state as state13, query as query6 } from "lit/decorators.js";
8849
9249
  import "./vars-v2-VMGWTFJZ.css";
8850
9250
  var RelPopover = class extends LitElement37 {
8851
9251
  constructor() {
@@ -9132,10 +9532,10 @@ __decorateClass([
9132
9532
  property30({ type: Boolean, attribute: "closeonoutsideclick" })
9133
9533
  ], RelPopover.prototype, "closeOnOutsideClick", 2);
9134
9534
  __decorateClass([
9135
- state12()
9535
+ state13()
9136
9536
  ], RelPopover.prototype, "internalOpen", 2);
9137
9537
  __decorateClass([
9138
- state12()
9538
+ state13()
9139
9539
  ], RelPopover.prototype, "contentStyle", 2);
9140
9540
  __decorateClass([
9141
9541
  query6(".content-wrapper")
@@ -10056,90 +10456,412 @@ RelSegmentedButton = __decorateClass([
10056
10456
  ], RelSegmentedButton);
10057
10457
 
10058
10458
  // src/components/rel-select/rel-select.ts
10059
- import { LitElement as LitElement44, html as html44, css as css41 } from "lit";
10060
- import { customElement as customElement44, property as property37 } from "lit/decorators.js";
10459
+ import { LitElement as LitElement44, html as html44, css as css41, nothing as nothing5 } from "lit";
10460
+ import { customElement as customElement44, property as property37, state as state14, query as query7 } from "lit/decorators.js";
10461
+ import { repeat } from "lit/directives/repeat.js";
10061
10462
  import "./vars-v2-VMGWTFJZ.css";
10062
10463
  import "@reliability-design/icons/rel-icon";
10464
+ function normalizeOption(o) {
10465
+ if (typeof o === "string") return { value: o, label: o, supportingText: "" };
10466
+ return { value: o.value, label: o.label ?? o.value, supportingText: o.supportingText ?? "" };
10467
+ }
10063
10468
  var RelSelect = class extends LitElement44 {
10064
10469
  constructor() {
10065
10470
  super(...arguments);
10066
10471
  this.label = "";
10472
+ this.labelStyle = "default";
10067
10473
  this.options = [];
10474
+ this.multiple = false;
10068
10475
  this.selected = "";
10476
+ this.selectedValues = [];
10069
10477
  this.state = "default";
10070
10478
  this.supportingText = "";
10071
10479
  this.size = "medium";
10072
10480
  this.border = "rounded";
10073
10481
  this.leftIcon = "";
10074
10482
  this.rightIcon = "";
10483
+ this.placeholder = "Select option";
10484
+ this.searchPlaceholder = "Search option";
10485
+ this.selectAllLabel = "Select all";
10486
+ this.maxVisibleChips = 3;
10487
+ this.noSearch = false;
10488
+ this.open = false;
10489
+ this.highlightedIndex = -1;
10490
+ this.panelStyle = "";
10491
+ this.searchValue = "";
10492
+ this.internalState = "default";
10493
+ this.uniqueId = `select-${Math.random().toString(36).slice(2)}`;
10494
+ this.onOutsidePointerDown = (e) => {
10495
+ if (!this.open) return;
10496
+ const path = e.composedPath();
10497
+ if (path.includes(this)) return;
10498
+ this.closeListbox();
10499
+ };
10500
+ // Continuously re-deriving a fixed-position panel's coordinates from
10501
+ // every page scroll event is fragile (it's what was causing the panel to
10502
+ // jump to the top of the viewport). Instead, close the panel on any
10503
+ // *outside* scroll, same as clicking outside — scrolling the option list
10504
+ // itself (target is the listbox) is the one case that should NOT close it.
10505
+ this.onPageScroll = (e) => {
10506
+ if (!this.open) return;
10507
+ if (e.composedPath()[0] === this.listboxEl) return;
10508
+ this.closeListbox();
10509
+ };
10510
+ this.updatePosition = () => {
10511
+ if (!this.triggerEl || !this.listboxEl) return;
10512
+ this.listboxEl.setAttribute("data-open", "");
10513
+ const t = this.triggerEl.getBoundingClientRect();
10514
+ const c = this.listboxEl.getBoundingClientRect();
10515
+ let top = t.bottom + 4;
10516
+ if (top + c.height > window.innerHeight - 8) {
10517
+ top = Math.max(8, t.top - c.height - 4);
10518
+ }
10519
+ let left = t.left;
10520
+ if (left + t.width > window.innerWidth - 8) {
10521
+ left = Math.max(8, window.innerWidth - t.width - 8);
10522
+ }
10523
+ this.panelStyle = `top:${top}px;left:${left}px;width:${t.width}px;`;
10524
+ };
10525
+ this.onSearchInput = (e) => {
10526
+ this.searchValue = e.target.value;
10527
+ this.highlightedIndex = this.filteredOptions.length > 0 ? 0 : -1;
10528
+ requestAnimationFrame(() => this.updatePosition());
10529
+ };
10075
10530
  }
10076
- connectedCallback() {
10077
- super.connectedCallback();
10078
- const leftIcon = this.getAttribute("left-icon");
10079
- if (leftIcon) this.leftIcon = leftIcon;
10080
- const rightIcon = this.getAttribute("right-icon");
10081
- if (rightIcon) this.rightIcon = rightIcon;
10531
+ disconnectedCallback() {
10532
+ super.disconnectedCallback();
10533
+ this.removeGlobalListeners();
10534
+ }
10535
+ willUpdate(changed) {
10536
+ if (changed.has("multiple") && this.multiple === false) {
10537
+ this.selectedValues = [];
10538
+ }
10082
10539
  }
10083
- onChange(event) {
10084
- const value = event.target.value;
10085
- this.selected = value;
10540
+ get normalizedOptions() {
10541
+ return this.options.map(normalizeOption);
10542
+ }
10543
+ /** Options matching the current search text (substring match, case-insensitive). */
10544
+ get filteredOptions() {
10545
+ const opts = this.normalizedOptions;
10546
+ if (!this.searchValue) return opts;
10547
+ const v = this.searchValue.toLowerCase();
10548
+ return opts.filter((o) => o.label.toLowerCase().includes(v));
10549
+ }
10550
+ get hasValue() {
10551
+ return this.multiple ? this.selectedValues.length > 0 : !!this.selected;
10552
+ }
10553
+ /** Icon size scales with the select's own size, matching the trigger. */
10554
+ get iconSize() {
10555
+ return this.size === "small" ? "xs" : this.size === "large" ? "md" : "sm";
10556
+ }
10557
+ /** The search field uses "small" sizing for both small and medium select — only "large" select bumps it to "medium". */
10558
+ get searchIconSize() {
10559
+ return this.size === "large" ? "md" : "sm";
10560
+ }
10561
+ get selectAllStatus() {
10562
+ const filtered = this.filteredOptions;
10563
+ if (filtered.length === 0) return "unchecked";
10564
+ const selectedCount = filtered.filter((o) => this.selectedValues.includes(o.value)).length;
10565
+ if (selectedCount === 0) return "unchecked";
10566
+ if (selectedCount === filtered.length) return "checked";
10567
+ return "indeterminate";
10568
+ }
10569
+ addGlobalListeners() {
10570
+ document.addEventListener("pointerdown", this.onOutsidePointerDown);
10571
+ window.addEventListener("resize", this.updatePosition);
10572
+ window.addEventListener("scroll", this.onPageScroll, true);
10573
+ }
10574
+ removeGlobalListeners() {
10575
+ document.removeEventListener("pointerdown", this.onOutsidePointerDown);
10576
+ window.removeEventListener("resize", this.updatePosition);
10577
+ window.removeEventListener("scroll", this.onPageScroll, true);
10578
+ }
10579
+ emitChange() {
10086
10580
  this.dispatchEvent(
10087
10581
  new CustomEvent("changed", {
10088
- detail: { value },
10582
+ detail: { value: this.multiple ? this.selectedValues : this.selected },
10089
10583
  bubbles: true,
10090
10584
  composed: true
10091
10585
  })
10092
10586
  );
10093
10587
  }
10588
+ openListbox() {
10589
+ if (this.state === "disabled" || this.open) return;
10590
+ this.open = true;
10591
+ this.searchValue = "";
10592
+ this.highlightedIndex = -1;
10593
+ this.addGlobalListeners();
10594
+ requestAnimationFrame(() => {
10595
+ this.updatePosition();
10596
+ if (!this.noSearch) {
10597
+ this.searchInputEl?.focus({ preventScroll: true });
10598
+ }
10599
+ });
10600
+ }
10601
+ closeListbox() {
10602
+ if (!this.open) return;
10603
+ this.open = false;
10604
+ this.removeGlobalListeners();
10605
+ this.triggerEl?.focus();
10606
+ }
10607
+ selectSingleOption(option) {
10608
+ this.selected = option.value;
10609
+ if (this.state === "error") this.state = "default";
10610
+ this.closeListbox();
10611
+ this.emitChange();
10612
+ }
10613
+ toggleMultiOption(option) {
10614
+ const idx = this.selectedValues.indexOf(option.value);
10615
+ this.selectedValues = idx >= 0 ? this.selectedValues.filter((v) => v !== option.value) : [...this.selectedValues, option.value];
10616
+ if (this.state === "error") this.state = "default";
10617
+ this.emitChange();
10618
+ }
10619
+ toggleSelectAll() {
10620
+ const filtered = this.filteredOptions;
10621
+ const status = this.selectAllStatus;
10622
+ if (status === "checked") {
10623
+ const filteredValues = new Set(filtered.map((o) => o.value));
10624
+ this.selectedValues = this.selectedValues.filter((v) => !filteredValues.has(v));
10625
+ } else {
10626
+ const toAdd = filtered.map((o) => o.value).filter((v) => !this.selectedValues.includes(v));
10627
+ this.selectedValues = [...this.selectedValues, ...toAdd];
10628
+ }
10629
+ if (this.state === "error") this.state = "default";
10630
+ this.emitChange();
10631
+ }
10632
+ removeChip(value) {
10633
+ if (this.state === "disabled") return;
10634
+ this.selectedValues = this.selectedValues.filter((v) => v !== value);
10635
+ this.emitChange();
10636
+ }
10637
+ onTriggerClick() {
10638
+ if (this.open) this.closeListbox();
10639
+ else this.openListbox();
10640
+ }
10641
+ onTriggerKeyDown(e) {
10642
+ if (this.state === "disabled") return;
10643
+ if (!this.open) {
10644
+ if (["ArrowDown", "ArrowUp", "Enter", " "].includes(e.key)) {
10645
+ e.preventDefault();
10646
+ this.openListbox();
10647
+ }
10648
+ return;
10649
+ }
10650
+ if (this.noSearch) this.handleListNavigation(e);
10651
+ }
10652
+ onSearchKeyDown(e) {
10653
+ this.handleListNavigation(e);
10654
+ }
10655
+ handleListNavigation(e) {
10656
+ const filtered = this.filteredOptions;
10657
+ switch (e.key) {
10658
+ case "ArrowDown":
10659
+ e.preventDefault();
10660
+ this.highlightedIndex = Math.min(filtered.length - 1, this.highlightedIndex + 1);
10661
+ break;
10662
+ case "ArrowUp":
10663
+ e.preventDefault();
10664
+ this.highlightedIndex = Math.max(0, this.highlightedIndex - 1);
10665
+ break;
10666
+ case "Enter":
10667
+ e.preventDefault();
10668
+ if (this.highlightedIndex >= 0 && filtered[this.highlightedIndex]) {
10669
+ const opt = filtered[this.highlightedIndex];
10670
+ if (this.multiple) this.toggleMultiOption(opt);
10671
+ else this.selectSingleOption(opt);
10672
+ }
10673
+ break;
10674
+ case "Escape":
10675
+ e.preventDefault();
10676
+ this.closeListbox();
10677
+ break;
10678
+ case "Tab":
10679
+ this.closeListbox();
10680
+ break;
10681
+ }
10682
+ }
10683
+ renderChips() {
10684
+ const values = this.selectedValues;
10685
+ const visible = values.slice(0, this.maxVisibleChips);
10686
+ const overflow = values.length - visible.length;
10687
+ const opts = this.normalizedOptions;
10688
+ return html44`
10689
+ <span class="select-chips">
10690
+ ${repeat(
10691
+ visible,
10692
+ (v) => v,
10693
+ (v) => {
10694
+ const opt = opts.find((o) => o.value === v);
10695
+ return html44`
10696
+ <rel-chip
10697
+ label="${opt?.label ?? v}"
10698
+ size="sm"
10699
+ variant="subtle"
10700
+ border="default"
10701
+ ?removable=${this.state !== "disabled"}
10702
+ @click=${(e) => e.stopPropagation()}
10703
+ @removed=${(e) => {
10704
+ e.stopPropagation();
10705
+ this.removeChip(v);
10706
+ }}
10707
+ ></rel-chip>
10708
+ `;
10709
+ }
10710
+ )}
10711
+ ${overflow > 0 ? html44`<rel-chip label="+${overflow}" size="sm" variant="fill" border="default"></rel-chip>` : nothing5}
10712
+ </span>
10713
+ `;
10714
+ }
10094
10715
  render() {
10095
- const containerClasses = [
10096
- "select-container",
10097
- this.leftIcon ? "with-left-icon" : "",
10098
- this.rightIcon ? "with-right-icon" : "",
10099
- `select-${this.size}`
10100
- ].filter(Boolean).join(" ");
10716
+ const opts = this.normalizedOptions;
10717
+ const filtered = this.filteredOptions;
10718
+ const isDisabled = this.state === "disabled";
10719
+ const showFloatingChrome = this.labelStyle === "floating" && !!this.label;
10101
10720
  const wrapperClasses = [
10102
10721
  "select-wrapper",
10103
- `select-${this.state}`,
10104
- `border-${this.border}`
10105
- ].join(" ");
10106
- const selectClasses = [this.state === "error" ? "error" : ""].filter(Boolean).join(" ");
10107
- const isDisabled = this.state === "disabled";
10722
+ this.size,
10723
+ this.state,
10724
+ `border-${this.border}`,
10725
+ showFloatingChrome ? "floating" : "",
10726
+ this.internalState === "focused" ? "focused" : "",
10727
+ this.hasValue ? "has-value" : "",
10728
+ this.open ? "open" : ""
10729
+ ].filter(Boolean).join(" ");
10730
+ const listboxId = `${this.uniqueId}-listbox`;
10731
+ const activeOptionId = this.open && this.highlightedIndex >= 0 ? `${this.uniqueId}-option-${this.highlightedIndex}` : "";
10732
+ const selectedSingle = opts.find((o) => o.value === this.selected);
10108
10733
  return html44`
10109
10734
  <div class="${wrapperClasses}">
10110
- ${this.label ? html44`<label class="select-label">${this.label}</label>` : ""}
10735
+ ${!showFloatingChrome && this.label ? html44`<label class="select-label" for="${this.uniqueId}">${this.label}</label>` : ""}
10111
10736
 
10112
- <div class="${containerClasses}">
10113
- ${this.leftIcon ? html44`<rel-icon name="${this.leftIcon}" size="sm" class="icon left"></rel-icon>` : ""}
10737
+ <div class="select-container">
10738
+ ${showFloatingChrome ? html44`<span class="floating-label${this.leftIcon ? " has-left-icon" : ""}"
10739
+ >${this.label}</span
10740
+ >` : ""}
10114
10741
 
10115
- <select
10116
- class="${selectClasses}"
10742
+ <button
10743
+ id="${this.uniqueId}"
10744
+ type="button"
10745
+ class="select-trigger"
10746
+ role="combobox"
10747
+ aria-haspopup="listbox"
10748
+ aria-expanded="${this.open}"
10749
+ aria-controls="${listboxId}"
10750
+ aria-activedescendant="${activeOptionId}"
10751
+ aria-invalid="${this.state === "error"}"
10752
+ aria-label="${this.label || this.placeholder}"
10117
10753
  ?disabled="${isDisabled}"
10118
- @change="${this.onChange}"
10119
- .value="${this.selected}">
10120
- <option value="" disabled ?selected="${!this.selected}" hidden>
10121
- Select Option
10122
- </option>
10123
- ${this.options.map(
10124
- (option) => html44`
10125
- <option value="${option}" ?selected="${option === this.selected}">
10126
- ${option}
10127
- </option>
10128
- `
10129
- )}
10130
- </select>
10754
+ @click="${this.onTriggerClick}"
10755
+ @keydown="${this.onTriggerKeyDown}"
10756
+ @focus="${() => this.internalState = "focused"}"
10757
+ @blur="${() => this.internalState = "default"}"
10758
+ >
10759
+ ${this.leftIcon ? html44`<rel-icon name="${this.leftIcon}" size="${this.iconSize}" class="icon left"></rel-icon>` : ""}
10131
10760
 
10132
- ${this.rightIcon ? html44`<span class="icon right">${this.rightIcon}</span>` : ""}
10761
+ ${this.multiple ? this.selectedValues.length > 0 ? html44`<span class="select-value">${this.renderChips()}</span>` : html44`<span class="select-value placeholder">
10762
+ <span class="select-value-text">${this.placeholder}</span>
10763
+ </span>` : html44`<span class="select-value ${selectedSingle ? "" : "placeholder"}">
10764
+ <span class="select-value-text"
10765
+ >${selectedSingle ? selectedSingle.label : this.placeholder}</span
10766
+ >
10767
+ </span>`}
10133
10768
 
10134
- <rel-icon name="chevron-down" size="sm" class="icon chevron"></rel-icon>
10769
+ <rel-icon
10770
+ name="${this.rightIcon || "chevron-down"}"
10771
+ size="${this.iconSize}"
10772
+ class="icon ${this.rightIcon ? "" : "chevron"}"
10773
+ ></rel-icon>
10774
+ </button>
10135
10775
  </div>
10136
10776
 
10137
- ${this.supportingText ? html44`
10138
- <span
10139
- class="supporting-text ${this.state === "error" ? "error-text" : ""}">
10140
- ${this.supportingText}
10141
- </span>
10142
- ` : ""}
10777
+ ${this.supportingText ? html44`<span class="select-support ${this.state === "error" ? "error" : ""}">
10778
+ ${this.supportingText}
10779
+ </span>` : ""}
10780
+ </div>
10781
+
10782
+ <div
10783
+ id="${listboxId}"
10784
+ class="select-listbox"
10785
+ role="listbox"
10786
+ aria-multiselectable="${this.multiple}"
10787
+ aria-label="${this.label || "Options"}"
10788
+ style="${this.panelStyle}"
10789
+ ?data-open="${this.open}"
10790
+ >
10791
+ ${!this.noSearch ? html44`<div class="select-search">
10792
+ <div class="search-input-wrap">
10793
+ <rel-icon name="search" size="${this.searchIconSize}" class="icon"></rel-icon>
10794
+ <input
10795
+ class="search-input"
10796
+ type="text"
10797
+ placeholder="${this.searchPlaceholder}"
10798
+ .value="${this.searchValue}"
10799
+ @input="${this.onSearchInput}"
10800
+ @keydown="${(e) => this.onSearchKeyDown(e)}"
10801
+ />
10802
+ </div>
10803
+ </div>` : ""}
10804
+
10805
+ ${filtered.length === 0 ? html44`<div class="select-empty">
10806
+ ${opts.length === 0 ? "No options available" : "No matches found"}
10807
+ </div>` : this.multiple ? html44`
10808
+ <div class="select-all-row">
10809
+ <rel-checkbox
10810
+ label="${this.selectAllLabel}"
10811
+ status="${this.selectAllStatus}"
10812
+ @rel-change=${(e) => {
10813
+ e.stopPropagation();
10814
+ this.toggleSelectAll();
10815
+ }}
10816
+ ></rel-checkbox>
10817
+ </div>
10818
+ <div class="select-options">
10819
+ ${repeat(
10820
+ filtered,
10821
+ (option) => option.value,
10822
+ (option, index) => html44`
10823
+ <div
10824
+ id="${this.uniqueId}-option-${index}"
10825
+ class="checkbox-option ${index === this.highlightedIndex ? "highlighted" : ""}"
10826
+ role="option"
10827
+ aria-selected="${this.selectedValues.includes(option.value)}"
10828
+ @pointerenter="${() => this.highlightedIndex = index}"
10829
+ >
10830
+ <rel-checkbox
10831
+ label="${option.label}"
10832
+ supportingtext="${option.supportingText}"
10833
+ status="${this.selectedValues.includes(option.value) ? "checked" : "unchecked"}"
10834
+ @rel-change=${(e) => {
10835
+ e.stopPropagation();
10836
+ this.toggleMultiOption(option);
10837
+ }}
10838
+ ></rel-checkbox>
10839
+ </div>
10840
+ `
10841
+ )}
10842
+ </div>
10843
+ ` : html44`
10844
+ <div class="select-options">
10845
+ ${repeat(
10846
+ filtered,
10847
+ (option) => option.value,
10848
+ (option, index) => html44`
10849
+ <div
10850
+ id="${this.uniqueId}-option-${index}"
10851
+ class="select-option ${index === this.highlightedIndex ? "highlighted" : ""}"
10852
+ role="option"
10853
+ aria-selected="${option.value === this.selected}"
10854
+ @mousedown="${(e) => e.preventDefault()}"
10855
+ @click="${() => this.selectSingleOption(option)}"
10856
+ @pointerenter="${() => this.highlightedIndex = index}"
10857
+ >
10858
+ <span class="select-option-label">${option.label}</span>
10859
+ ${option.value === this.selected ? html44`<rel-icon name="check" size="sm" class="select-option-check"></rel-icon>` : ""}
10860
+ </div>
10861
+ `
10862
+ )}
10863
+ </div>
10864
+ `}
10143
10865
  </div>
10144
10866
  `;
10145
10867
  }
@@ -10154,258 +10876,686 @@ RelSelect.styles = css41`
10154
10876
  .select-wrapper {
10155
10877
  display: flex;
10156
10878
  flex-direction: column;
10879
+ gap: var(--rel-spacing-space-2xs);
10157
10880
  width: 100%;
10158
10881
  }
10159
10882
 
10883
+ /* Dims everything inside uniformly (label, trigger, icons, value text,
10884
+ supporting text) — matches rel-button's :host([disabled]) opacity
10885
+ approach instead of relying on one barely-different background tint. */
10886
+ .select-wrapper.disabled {
10887
+ opacity: 0.5;
10888
+ }
10889
+
10160
10890
  .select-label {
10161
- font-size: var(--rel-fontSizes-sm);
10162
- margin-bottom: var(--rel-spacing-space-3xs);
10163
- font-weight: var(--rel-fontWeights-medium);
10164
- color: var(--rel-color-text-heading);
10891
+ font-size: var(--rel-fontSizes-sm, 14px);
10892
+ font-weight: var(--rel-fontWeights-regular, 400);
10893
+ color: var(--rel-select-label-color, #363636);
10165
10894
  }
10166
10895
 
10896
+ /* Error only colors the border/focus ring and the supporting text below
10897
+ the field — label, floating label, placeholder, and icons stay normal. */
10898
+
10899
+ /* Container */
10167
10900
  .select-container {
10168
10901
  position: relative;
10902
+ }
10903
+
10904
+ /* Trigger button — visually a text field, semantically a combobox button */
10905
+ .select-trigger {
10169
10906
  display: flex;
10170
10907
  align-items: center;
10908
+ width: 100%;
10909
+ box-sizing: border-box;
10910
+ gap: 8px;
10911
+ background: var(--rel-select-bg, #ffffff);
10912
+ border: 1px solid var(--rel-select-border-default, #e5e5e5);
10913
+ cursor: pointer;
10914
+ font-family: inherit;
10915
+ transition: border-color 0.15s ease;
10916
+ text-align: left;
10171
10917
  }
10172
10918
 
10173
- .icon {
10174
- position: absolute;
10919
+ .border-rounded .select-trigger {
10920
+ border-radius: var(--rel-select-radius, 4px);
10921
+ }
10922
+
10923
+ .border-sharp .select-trigger {
10924
+ border-radius: 0;
10925
+ }
10926
+
10927
+ .select-trigger:focus-visible,
10928
+ .select-wrapper.open .select-trigger {
10929
+ outline: none;
10930
+ border-color: var(--rel-select-border-focus, #0b0b0b);
10931
+ }
10932
+
10933
+ .select-wrapper.error .select-trigger {
10934
+ border-color: var(--rel-select-border-error, #ce3131);
10935
+ }
10936
+
10937
+ .select-wrapper.disabled .select-trigger {
10938
+ cursor: not-allowed;
10939
+ background: var(--rel-select-bg-disabled, #fafafa);
10940
+ border-color: var(--rel-select-border-default, #e5e5e5);
10941
+ }
10942
+
10943
+ /* Sizes */
10944
+ .select-wrapper.small .select-trigger {
10945
+ padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-sm);
10946
+ min-height: 40px;
10947
+ font-size: var(--rel-fontSizes-sm, 14px);
10948
+ }
10949
+
10950
+ .select-wrapper.medium .select-trigger {
10951
+ padding: 12px;
10952
+ min-height: 48px;
10953
+ font-size: var(--rel-fontSizes-md, 16px);
10954
+ }
10955
+
10956
+ .select-wrapper.large .select-trigger {
10957
+ padding: var(--rel-spacing-space-md);
10958
+ min-height: 56px;
10959
+ font-size: var(--rel-fontSizes-lg, 18px);
10960
+ }
10961
+
10962
+ /* Icons */
10963
+ .select-trigger .icon {
10175
10964
  display: flex;
10176
10965
  align-items: center;
10177
- justify-content: center;
10178
- pointer-events: none;
10179
- top: 50%;
10180
- transform: translateY(-50%);
10181
- font-size: 16px;
10182
- color: var(--rel-color-text-primary);
10966
+ flex-shrink: 0;
10967
+ color: var(--rel-select-icon-color, #0b0b0b);
10183
10968
  }
10184
10969
 
10185
- .icon.left {
10186
- left: 10px;
10187
- pointer-events: none;
10188
- position: absolute;
10189
- top: 50%;
10190
- transform: translateY(-50%);
10970
+ .select-trigger .icon.chevron {
10971
+ transition: transform 0.15s ease;
10191
10972
  }
10192
10973
 
10193
- .icon.right {
10194
- right: 36px;
10974
+ .select-wrapper.open .icon.chevron {
10975
+ transform: rotate(180deg);
10195
10976
  }
10196
10977
 
10197
- .icon.chevron {
10198
- right: 12px;
10978
+ .select-wrapper.disabled .icon {
10979
+ color: var(--rel-color-text-disabled, #a3a3a3);
10980
+ }
10981
+
10982
+ /* Value area */
10983
+ .select-value {
10984
+ flex: 1;
10985
+ min-width: 0;
10986
+ display: flex;
10987
+ align-items: center;
10988
+ gap: 6px;
10989
+ flex-wrap: wrap;
10990
+ color: var(--rel-select-value-color, #0b0b0b);
10991
+ overflow: hidden;
10992
+ }
10993
+
10994
+ .select-value.placeholder {
10995
+ color: var(--rel-select-placeholder-color, #757575);
10996
+ }
10997
+
10998
+ .select-wrapper.disabled .select-value.placeholder {
10999
+ color: var(--rel-select-placeholder-disabled-color, #7d7d7d);
11000
+ }
11001
+
11002
+ .select-value-text {
11003
+ overflow: hidden;
11004
+ text-overflow: ellipsis;
11005
+ white-space: nowrap;
11006
+ }
11007
+
11008
+ .select-chips {
11009
+ display: flex;
11010
+ align-items: center;
11011
+ gap: 6px;
11012
+ flex-wrap: wrap;
11013
+ }
11014
+
11015
+ /* rel-chip's outer element is a tabindex="0" span, not a native button —
11016
+ a disabled native <button> ancestor doesn't suppress clicks on that
11017
+ automatically the way it would for a nested native form control, so
11018
+ this has to be switched off explicitly. The cursor still correctly
11019
+ falls through to the disabled trigger underneath. */
11020
+ .select-wrapper.disabled .select-chips {
10199
11021
  pointer-events: none;
11022
+ }
11023
+
11024
+ /* Floating label — single element that animates between resting (inside,
11025
+ at the value position) and floated (small, on the border line), same
11026
+ mechanism as rel-textfield's [floatinglabel]. */
11027
+ .floating-label {
10200
11028
  position: absolute;
11029
+ left: 12px;
10201
11030
  top: 50%;
10202
11031
  transform: translateY(-50%);
10203
- color: var(--rel-color-text-primary);
11032
+ background: var(--rel-select-bg, #ffffff);
11033
+ padding: 0 4px;
11034
+ font-size: var(--rel-fontSizes-md, 16px);
11035
+ font-weight: 400;
11036
+ line-height: 1;
11037
+ color: var(--rel-select-placeholder-color, #757575);
11038
+ pointer-events: none;
11039
+ z-index: 1;
11040
+ white-space: nowrap;
11041
+ transition: top 0.15s ease, left 0.15s ease, font-size 0.15s ease, color 0.15s ease;
10204
11042
  }
10205
11043
 
10206
- .select-error .icon.chevron {
10207
- color: var(--rel-error-surface-default, #D50000);
11044
+ .floating-label.has-left-icon {
11045
+ left: 40px;
10208
11046
  }
10209
11047
 
10210
- .select-disabled .icon.chevron {
10211
- color: var(--rel-color-text-disabled);
11048
+ .select-wrapper.focused .floating-label,
11049
+ .select-wrapper.has-value .floating-label,
11050
+ .select-wrapper.open .floating-label {
11051
+ top: 0;
11052
+ left: 12px;
11053
+ font-size: 12px;
11054
+ color: var(--rel-select-label-color, #363636);
10212
11055
  }
10213
11056
 
10214
- select {
11057
+ /* The real placeholder hides while the float-label rests in its spot,
11058
+ and fades in once the label has moved up to the border. */
11059
+ .select-wrapper.floating .select-value.placeholder {
11060
+ opacity: 0;
11061
+ transition: opacity 0.1s ease;
11062
+ }
11063
+
11064
+ .select-wrapper.floating.focused .select-value.placeholder,
11065
+ .select-wrapper.floating.open .select-value.placeholder {
11066
+ opacity: 1;
11067
+ }
11068
+
11069
+ /* Supporting text */
11070
+ .select-support {
11071
+ font-size: 13px;
11072
+ color: var(--rel-select-supporting-color, #404040);
11073
+ }
11074
+
11075
+ .select-support.error {
11076
+ color: var(--rel-select-border-error, #ce3131);
11077
+ }
11078
+
11079
+ /* ── Dropdown listbox ── */
11080
+ .select-listbox {
11081
+ position: fixed;
11082
+ z-index: 1001;
11083
+ display: none;
11084
+ box-sizing: border-box;
11085
+ background: var(--rel-select-bg, #ffffff);
11086
+ border: 1px solid var(--rel-select-menu-border, #d4d4d4);
11087
+ border-radius: var(--rel-select-menu-radius, 8px);
11088
+ /* A border alone doesn't read clearly against a similarly-light page,
11089
+ and a shadow alone barely shows on a dark background — together
11090
+ they hold up in both themes. */
11091
+ box-shadow: var(--rel-select-menu-shadow, 0 8px 24px rgba(11, 11, 11, 0.18));
11092
+ max-height: 360px;
11093
+ overflow-y: auto;
11094
+ }
11095
+
11096
+ .select-listbox[data-open] {
11097
+ display: block;
11098
+ }
11099
+
11100
+ .select-search {
11101
+ position: sticky;
11102
+ top: 0;
11103
+ background: var(--rel-select-bg, #ffffff);
11104
+ padding: var(--rel-spacing-space-xs);
11105
+ border-bottom: 1px solid var(--rel-select-divider, #f5f5f5);
11106
+ }
11107
+
11108
+ /* Base = "small" textfield sizing, shared by both small AND medium
11109
+ select — only "large" select bumps the search field up to "medium". */
11110
+ .search-input-wrap {
11111
+ display: flex;
11112
+ align-items: center;
11113
+ gap: 8px;
11114
+ border: 1px solid var(--rel-select-search-border, #e5e5e5);
11115
+ border-radius: 4px;
11116
+ padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-sm);
11117
+ }
11118
+
11119
+ .search-input-wrap .icon {
11120
+ display: flex;
11121
+ align-items: center;
11122
+ flex-shrink: 0;
11123
+ color: var(--rel-select-icon-color, #0b0b0b);
11124
+ }
11125
+
11126
+ .search-input {
10215
11127
  flex: 1;
10216
- appearance: none;
10217
- border: 1px solid var(--rel-color-border-default);
10218
- background-color: var(--rel-color-bg-primary);
10219
- font-family: var(--rel-fontFamilies-primary);
10220
- cursor: pointer;
10221
- transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out, background-color 0.2s ease-in-out;
10222
- color: var(--rel-color-text-heading);
10223
- width: 100%;
11128
+ min-width: 0;
11129
+ border: none;
10224
11130
  outline: none;
11131
+ background: transparent;
11132
+ font-family: inherit;
11133
+ font-size: var(--rel-fontSizes-sm, 14px);
11134
+ color: var(--rel-select-value-color, #0b0b0b);
10225
11135
  }
10226
11136
 
10227
- select:hover:not(:disabled) {
10228
- border-color: var(--rel-color-text-primary);
11137
+ .search-input::placeholder {
11138
+ color: var(--rel-select-placeholder-color, #757575);
10229
11139
  }
10230
11140
 
10231
- select:focus-visible:not(:disabled) {
10232
- border-color: var(--rel-color-border-focus);
10233
- box-shadow: 0 0 0 2px var(--rel-color-border-focus);
11141
+ :host([size="large"]) .search-input-wrap {
11142
+ padding: 12px;
10234
11143
  }
10235
11144
 
10236
- /* States */
10237
- select.error {
10238
- border-color: var(--rel-error-surface-default, #D50000);
10239
- border-width: 2px;
11145
+ :host([size="large"]) .search-input {
11146
+ font-size: var(--rel-fontSizes-md, 16px);
10240
11147
  }
10241
11148
 
10242
- select.error:focus {
10243
- box-shadow: 0 0 0 3px var(--rel-error-surface-light);
11149
+ .select-options {
11150
+ padding: 4px 0;
10244
11151
  }
10245
11152
 
10246
- select:disabled {
10247
- background-color: var(--rel-color-bg-tertiary);
10248
- border-color: var(--rel-color-border-default);
10249
- color: var(--rel-color-text-disabled);
10250
- cursor: not-allowed;
10251
- opacity: 0.6;
11153
+ .select-option {
11154
+ display: flex;
11155
+ align-items: center;
11156
+ justify-content: space-between;
11157
+ gap: 12px;
11158
+ padding: var(--rel-spacing-space-xs) 12px;
11159
+ font-size: var(--rel-fontSizes-md, 16px);
11160
+ font-family: var(--rel-fontFamilies-primary);
11161
+ color: var(--rel-select-value-color, #0b0b0b);
11162
+ cursor: pointer;
10252
11163
  }
10253
11164
 
10254
- /* Sizes */
10255
- .select-small select {
10256
- font-size: var(--rel-fontSizes-xs);
10257
- padding: var(--rel-spacing-space-3xs) 36px
10258
- var(--rel-spacing-space-3xs) var(--rel-spacing-space-2xs);
11165
+ .select-option-label {
11166
+ overflow: hidden;
11167
+ text-overflow: ellipsis;
11168
+ white-space: nowrap;
10259
11169
  }
10260
11170
 
10261
- .select-medium select {
10262
- font-size: var(--rel-fontSizes-sm);
10263
- padding: var(--rel-spacing-space-2xs) 40px
10264
- var(--rel-spacing-space-2xs) var(--rel-spacing-space-xs);
11171
+ .select-option-check {
11172
+ flex-shrink: 0;
11173
+ color: var(--rel-select-value-color, #0b0b0b);
10265
11174
  }
10266
11175
 
10267
- .select-large select {
10268
- font-size: var(--rel-fontSizes-md);
10269
- padding: var(--rel-spacing-space-xs) 44px
10270
- var(--rel-spacing-space-xs) var(--rel-spacing-space-sm);
11176
+ .select-option:hover,
11177
+ .select-option.highlighted {
11178
+ background: var(--rel-select-option-hover, #ececec);
10271
11179
  }
10272
11180
 
10273
- /* With icons */
10274
- .with-left-icon.select-small select {
10275
- padding-left: var(--rel-spacing-space-xl);
11181
+ .select-option[aria-selected="true"] {
11182
+ font-weight: var(--rel-fontWeights-medium);
10276
11183
  }
10277
11184
 
10278
- .with-left-icon.select-medium select {
10279
- padding-left: var(--rel-spacing-space-2xl);
11185
+ .checkbox-option {
11186
+ padding: 12px;
10280
11187
  }
10281
11188
 
10282
- .with-left-icon.select-large select {
10283
- padding-left: var(--rel-spacing-space-3xl);
11189
+ .checkbox-option:hover,
11190
+ .checkbox-option.highlighted {
11191
+ background: var(--rel-select-option-hover, #ececec);
10284
11192
  }
10285
11193
 
10286
- .with-right-icon.select-small select {
10287
- padding-right: var(--rel-spacing-space-2xl);
11194
+ .select-all-row {
11195
+ border-bottom: 1px solid var(--rel-select-divider, #f5f5f5);
11196
+ padding: 12px;
11197
+ }
11198
+
11199
+ .select-empty {
11200
+ padding: var(--rel-spacing-space-xs) 12px;
11201
+ font-size: var(--rel-fontSizes-sm, 14px);
11202
+ color: var(--rel-select-placeholder-color, #757575);
11203
+ }
11204
+
11205
+ /* Dark mode */
11206
+ /* No :not(.error) needed here — error no longer recolors label/floating
11207
+ label, so there's nothing left for these to compete with. */
11208
+ :host-context([data-theme="dark"]) .select-label,
11209
+ [data-theme="dark"] .select-label {
11210
+ color: var(--rel-select-label-color-dark, #f5f5f5);
11211
+ }
11212
+
11213
+ /* :not(.error) — supporting text IS still red on error, and this rule's
11214
+ extra :host-context specificity would otherwise outrank the
11215
+ theme-agnostic .select-support.error rule. */
11216
+ :host-context([data-theme="dark"]) .select-wrapper:not(.error) .select-support,
11217
+ [data-theme="dark"] .select-wrapper:not(.error) .select-support {
11218
+ color: var(--rel-select-supporting-color-dark, #b3b3b3);
11219
+ }
11220
+
11221
+ :host-context([data-theme="dark"]) .select-wrapper.focused .floating-label,
11222
+ [data-theme="dark"] .select-wrapper.focused .floating-label,
11223
+ :host-context([data-theme="dark"]) .select-wrapper.has-value .floating-label,
11224
+ [data-theme="dark"] .select-wrapper.has-value .floating-label,
11225
+ :host-context([data-theme="dark"]) .select-wrapper.open .floating-label,
11226
+ [data-theme="dark"] .select-wrapper.open .floating-label {
11227
+ color: var(--rel-select-label-color-dark, #f5f5f5);
11228
+ }
11229
+
11230
+ /* Background only here — kept unconditional so error-state triggers
11231
+ still get the right dark background. border-color is split into its
11232
+ own :not(.error) rule below: this rule's specificity (with the extra
11233
+ :host-context) ties or beats the theme-agnostic error-border rule, and
11234
+ since it's declared later in the file, an unconditional border-color
11235
+ here would win the tie and show the default dark border instead of red
11236
+ — regardless of open/focus state, i.e. even at rest. */
11237
+ :host-context([data-theme="dark"]) .select-trigger,
11238
+ [data-theme="dark"] .select-trigger,
11239
+ :host-context([data-theme="dark"]) .floating-label,
11240
+ [data-theme="dark"] .floating-label {
11241
+ background: var(--rel-select-bg-dark, #1a1a1a);
11242
+ }
11243
+
11244
+ :host-context([data-theme="dark"]) .select-wrapper:not(.error) .select-trigger,
11245
+ [data-theme="dark"] .select-wrapper:not(.error) .select-trigger {
11246
+ border-color: var(--rel-select-border-default-dark, #333333);
11247
+ }
11248
+
11249
+ /* Own border token, a touch lighter than the trigger's — a shadow alone
11250
+ barely registers on a dark background, so the panel leans more on this
11251
+ border to separate itself from the page behind it. */
11252
+ :host-context([data-theme="dark"]) .select-listbox,
11253
+ [data-theme="dark"] .select-listbox {
11254
+ background: var(--rel-select-bg-dark, #1a1a1a);
11255
+ border-color: var(--rel-select-menu-border-dark, #454545);
11256
+ }
11257
+
11258
+ :host-context([data-theme="dark"]) .select-wrapper.disabled .select-trigger,
11259
+ [data-theme="dark"] .select-wrapper.disabled .select-trigger {
11260
+ background: var(--rel-select-bg-disabled-dark, #141414);
11261
+ }
11262
+
11263
+ /* :not(.error): same trap as the label rules — this rule's extra
11264
+ :host-context specificity would otherwise outrank the theme-agnostic
11265
+ .select-wrapper.error .select-trigger rule and show the focus-white
11266
+ border instead of error-red the moment an error field is opened. */
11267
+ :host-context([data-theme="dark"]) .select-wrapper:not(.error).open .select-trigger,
11268
+ [data-theme="dark"] .select-wrapper:not(.error).open .select-trigger,
11269
+ :host-context([data-theme="dark"]) .select-wrapper:not(.error) .select-trigger:focus-visible,
11270
+ [data-theme="dark"] .select-wrapper:not(.error) .select-trigger:focus-visible {
11271
+ border-color: var(--rel-select-border-focus-dark, #f5f5f5);
11272
+ }
11273
+
11274
+ :host-context([data-theme="dark"]) .select-value,
11275
+ [data-theme="dark"] .select-value,
11276
+ :host-context([data-theme="dark"]) .search-input,
11277
+ [data-theme="dark"] .search-input,
11278
+ :host-context([data-theme="dark"]) .select-option,
11279
+ [data-theme="dark"] .select-option,
11280
+ :host-context([data-theme="dark"]) .select-option-check,
11281
+ [data-theme="dark"] .select-option-check,
11282
+ :host-context([data-theme="dark"]) .icon,
11283
+ [data-theme="dark"] .icon {
11284
+ color: var(--rel-select-value-color-dark, #f5f5f5);
11285
+ }
11286
+
11287
+ :host-context([data-theme="dark"]) .select-option:hover,
11288
+ [data-theme="dark"] .select-option:hover,
11289
+ :host-context([data-theme="dark"]) .select-option.highlighted,
11290
+ [data-theme="dark"] .select-option.highlighted,
11291
+ :host-context([data-theme="dark"]) .checkbox-option:hover,
11292
+ [data-theme="dark"] .checkbox-option:hover,
11293
+ :host-context([data-theme="dark"]) .checkbox-option.highlighted,
11294
+ [data-theme="dark"] .checkbox-option.highlighted {
11295
+ background: var(--rel-select-option-hover-dark, #333333);
11296
+ }
11297
+
11298
+ :host-context([data-theme="dark"]) .select-search,
11299
+ [data-theme="dark"] .select-search {
11300
+ background: var(--rel-select-bg-dark, #1a1a1a);
11301
+ border-color: var(--rel-select-divider-dark, #333333);
11302
+ }
11303
+
11304
+ :host-context([data-theme="dark"]) .select-all-row,
11305
+ [data-theme="dark"] .select-all-row {
11306
+ border-color: var(--rel-select-divider-dark, #333333);
11307
+ }
11308
+
11309
+ :host-context([data-theme="dark"]) .select-value.placeholder,
11310
+ [data-theme="dark"] .select-value.placeholder,
11311
+ :host-context([data-theme="dark"]) .floating-label,
11312
+ [data-theme="dark"] .floating-label,
11313
+ :host-context([data-theme="dark"]) .search-input::placeholder,
11314
+ [data-theme="dark"] .search-input::placeholder,
11315
+ :host-context([data-theme="dark"]) .select-empty,
11316
+ [data-theme="dark"] .select-empty {
11317
+ color: var(--rel-select-placeholder-color-dark, #a3a3a3);
11318
+ }
11319
+
11320
+ :host-context([data-theme="dark"]) .search-input-wrap,
11321
+ [data-theme="dark"] .search-input-wrap {
11322
+ border-color: var(--rel-select-search-border-dark, #333333);
11323
+ }
11324
+ `;
11325
+ __decorateClass([
11326
+ property37({ type: String })
11327
+ ], RelSelect.prototype, "label", 2);
11328
+ __decorateClass([
11329
+ property37({ type: String, attribute: "label-style" })
11330
+ ], RelSelect.prototype, "labelStyle", 2);
11331
+ __decorateClass([
11332
+ property37({ type: Array })
11333
+ ], RelSelect.prototype, "options", 2);
11334
+ __decorateClass([
11335
+ property37({ type: Boolean })
11336
+ ], RelSelect.prototype, "multiple", 2);
11337
+ __decorateClass([
11338
+ property37({ type: String })
11339
+ ], RelSelect.prototype, "selected", 2);
11340
+ __decorateClass([
11341
+ property37({ type: Array, attribute: "selected-values" })
11342
+ ], RelSelect.prototype, "selectedValues", 2);
11343
+ __decorateClass([
11344
+ property37({ type: String })
11345
+ ], RelSelect.prototype, "state", 2);
11346
+ __decorateClass([
11347
+ property37({ type: String, attribute: "supporting-text" })
11348
+ ], RelSelect.prototype, "supportingText", 2);
11349
+ __decorateClass([
11350
+ property37({ type: String, reflect: true })
11351
+ ], RelSelect.prototype, "size", 2);
11352
+ __decorateClass([
11353
+ property37({ type: String })
11354
+ ], RelSelect.prototype, "border", 2);
11355
+ __decorateClass([
11356
+ property37({ type: String, attribute: "left-icon" })
11357
+ ], RelSelect.prototype, "leftIcon", 2);
11358
+ __decorateClass([
11359
+ property37({ type: String, attribute: "right-icon" })
11360
+ ], RelSelect.prototype, "rightIcon", 2);
11361
+ __decorateClass([
11362
+ property37({ type: String })
11363
+ ], RelSelect.prototype, "placeholder", 2);
11364
+ __decorateClass([
11365
+ property37({ type: String, attribute: "search-placeholder" })
11366
+ ], RelSelect.prototype, "searchPlaceholder", 2);
11367
+ __decorateClass([
11368
+ property37({ type: String, attribute: "select-all-label" })
11369
+ ], RelSelect.prototype, "selectAllLabel", 2);
11370
+ __decorateClass([
11371
+ property37({ type: Number, attribute: "max-visible-chips" })
11372
+ ], RelSelect.prototype, "maxVisibleChips", 2);
11373
+ __decorateClass([
11374
+ property37({ type: Boolean, attribute: "no-search" })
11375
+ ], RelSelect.prototype, "noSearch", 2);
11376
+ __decorateClass([
11377
+ state14()
11378
+ ], RelSelect.prototype, "open", 2);
11379
+ __decorateClass([
11380
+ state14()
11381
+ ], RelSelect.prototype, "highlightedIndex", 2);
11382
+ __decorateClass([
11383
+ state14()
11384
+ ], RelSelect.prototype, "panelStyle", 2);
11385
+ __decorateClass([
11386
+ state14()
11387
+ ], RelSelect.prototype, "searchValue", 2);
11388
+ __decorateClass([
11389
+ state14()
11390
+ ], RelSelect.prototype, "internalState", 2);
11391
+ __decorateClass([
11392
+ query7(".select-trigger")
11393
+ ], RelSelect.prototype, "triggerEl", 2);
11394
+ __decorateClass([
11395
+ query7(".search-input")
11396
+ ], RelSelect.prototype, "searchInputEl", 2);
11397
+ __decorateClass([
11398
+ query7(".select-listbox")
11399
+ ], RelSelect.prototype, "listboxEl", 2);
11400
+ RelSelect = __decorateClass([
11401
+ customElement44("rel-select")
11402
+ ], RelSelect);
11403
+
11404
+ // src/components/rel-skeleton/rel-skeleton.ts
11405
+ import { LitElement as LitElement45, html as html45, css as css42 } from "lit";
11406
+ import { customElement as customElement45, property as property38 } from "lit/decorators.js";
11407
+ var RelSkeleton = class extends LitElement45 {
11408
+ constructor() {
11409
+ super(...arguments);
11410
+ this.shape = "block";
11411
+ this.lines = 1;
11412
+ this.width = "";
11413
+ this.height = "";
11414
+ this.animation = "pulse";
11415
+ this.loaded = false;
11416
+ }
11417
+ updated(changed) {
11418
+ if (changed.has("width") && this.width) this.style.width = this.width;
11419
+ if (changed.has("height") && this.height) this.style.height = this.height;
11420
+ }
11421
+ render() {
11422
+ if (this.loaded) return html45``;
11423
+ if (this.shape === "line") {
11424
+ const count = Math.max(1, this.lines);
11425
+ return html45`
11426
+ <div class="skeleton-lines">
11427
+ ${Array.from({ length: count }, (_, i) => html45`
11428
+ <div class="skeleton-bar ${i === count - 1 && count > 1 ? "is-last" : ""}"></div>
11429
+ `)}
11430
+ </div>
11431
+ `;
10288
11432
  }
10289
-
10290
- .with-right-icon.select-medium select {
10291
- padding-right: var(--rel-spacing-space-3xl);
11433
+ return html45`<div class="skeleton-shape"></div>`;
11434
+ }
11435
+ };
11436
+ RelSkeleton.styles = css42`
11437
+ :host {
11438
+ display: block;
10292
11439
  }
10293
11440
 
10294
- .with-right-icon.select-large select {
10295
- padding-right: 4rem;
11441
+ :host([loaded]) {
11442
+ display: none;
10296
11443
  }
10297
11444
 
10298
- /* Border */
10299
- .border-rounded select {
10300
- border-radius: var(--rel-borders-radius-border-radius-100);
11445
+ /* ── Circle: aspect-ratio keeps it square without requiring explicit height ── */
11446
+ :host([shape="circle"]) {
11447
+ aspect-ratio: 1 / 1;
10301
11448
  }
10302
11449
 
10303
- .border-sharp select {
10304
- border-radius: 0;
11450
+ /* ── Base skeleton surface ── */
11451
+ .skeleton-shape,
11452
+ .skeleton-bar {
11453
+ background: var(--rel-skeleton-color, #c8c8c8);
11454
+ border-radius: 4px;
10305
11455
  }
10306
11456
 
10307
- /* Supporting text */
10308
- .supporting-text {
10309
- font-size: var(--rel-fontSizes-xs);
10310
- margin-top: var(--rel-spacing-space-3xs);
10311
- color: var(--rel-color-text-placeholder);
11457
+ /* ── Lines layout ── */
11458
+ .skeleton-lines {
11459
+ display: flex;
11460
+ flex-direction: column;
11461
+ gap: 8px;
11462
+ width: 100%;
10312
11463
  }
10313
11464
 
10314
- .error-text {
10315
- color: var(--rel-error-surface-default, #D50000);
11465
+ .skeleton-bar {
11466
+ height: 14px;
11467
+ width: 100%;
10316
11468
  }
10317
11469
 
10318
- .select-error .select-label {
10319
- color: var(--rel-error-surface-default, #D50000);
11470
+ /* Last line shortens to 65% — mimics real paragraph text that doesn't reach the edge */
11471
+ .skeleton-bar.is-last {
11472
+ width: 65%;
10320
11473
  }
10321
11474
 
10322
- /* Dark mode — flip select background, text, border */
10323
- :host-context([data-theme="dark"]) select,
10324
- :host-context(.dark) select {
10325
- background-color: var(--rel-color-bg-secondary);
10326
- color: #ffffff;
10327
- border-color: var(--rel-color-border-default);
11475
+ /* ── Shape (circle / block) ── */
11476
+ .skeleton-shape {
11477
+ width: 100%;
11478
+ height: 100%;
11479
+ min-height: 16px;
10328
11480
  }
10329
11481
 
10330
- :host-context([data-theme="dark"]) select.error,
10331
- :host-context(.dark) select.error {
10332
- border-color: var(--rel-error-surface-default, #FF5252);
10333
- border-width: 2px;
11482
+ :host([shape="circle"]) .skeleton-shape {
11483
+ border-radius: 50%;
11484
+ /* No min-height — circle is sized entirely by host width + aspect-ratio */
11485
+ min-height: unset;
10334
11486
  }
10335
11487
 
10336
- /* Error — placeholder text red */
10337
- select.error::placeholder {
10338
- color: var(--rel-error-surface-default, #D50000);
11488
+ /* ── Pulse animation ── */
11489
+ @keyframes rel-skeleton-pulse {
11490
+ 0%, 100% { opacity: 1; }
11491
+ 50% { opacity: 0.4; }
10339
11492
  }
10340
11493
 
10341
- /* Error — selected/placeholder option text red */
10342
- .select-error select {
10343
- color: var(--rel-error-surface-default, #D50000);
11494
+ :host([animation="pulse"]) .skeleton-shape,
11495
+ :host([animation="pulse"]) .skeleton-bar {
11496
+ animation: rel-skeleton-pulse 1.5s ease-in-out infinite;
10344
11497
  }
10345
11498
 
10346
- /* Error — icon red */
10347
- .select-error .icon,
10348
- .select-error rel-icon {
10349
- color: var(--rel-error-surface-default, #D50000);
11499
+ /* ── Shimmer animation ── */
11500
+ @keyframes rel-skeleton-shimmer {
11501
+ 0% { background-position: 200% center; }
11502
+ 100% { background-position: -200% center; }
10350
11503
  }
10351
11504
 
10352
- :host-context([data-theme="dark"]) .select-error select,
10353
- :host-context(.dark) .select-error select {
10354
- color: var(--rel-error-surface-default, #FF5252);
11505
+ :host([animation="shimmer"]) .skeleton-shape,
11506
+ :host([animation="shimmer"]) .skeleton-bar {
11507
+ background: linear-gradient(
11508
+ 90deg,
11509
+ var(--rel-skeleton-color, #c8c8c8) 25%,
11510
+ var(--rel-skeleton-highlight, #e2e2e2) 50%,
11511
+ var(--rel-skeleton-color, #c8c8c8) 75%
11512
+ );
11513
+ background-size: 200% 100%;
11514
+ animation: rel-skeleton-shimmer 1.5s linear infinite;
10355
11515
  }
10356
11516
 
10357
- :host-context([data-theme="dark"]) .select-error .icon,
10358
- :host-context([data-theme="dark"]) .select-error rel-icon,
10359
- :host-context(.dark) .select-error .icon,
10360
- :host-context(.dark) .select-error rel-icon {
10361
- color: var(--rel-error-surface-default, #FF5252);
11517
+ /* ── Dark mode ── */
11518
+ :host-context([data-theme="dark"]) {
11519
+ --rel-skeleton-color: #2a2a2a;
11520
+ --rel-skeleton-highlight: #3d3d3d;
10362
11521
  }
10363
11522
 
10364
- /* Disabled label */
10365
- .select-disabled .select-label {
10366
- color: var(--rel-color-text-disabled);
10367
- cursor: not-allowed;
10368
- user-select: none;
11523
+ /* ── Respect reduced-motion preference ── */
11524
+ @media (prefers-reduced-motion: reduce) {
11525
+ .skeleton-shape,
11526
+ .skeleton-bar {
11527
+ animation: none !important;
11528
+ }
10369
11529
  }
10370
-
10371
11530
  `;
10372
11531
  __decorateClass([
10373
- property37({ type: String })
10374
- ], RelSelect.prototype, "label", 2);
10375
- __decorateClass([
10376
- property37({ type: Array })
10377
- ], RelSelect.prototype, "options", 2);
10378
- __decorateClass([
10379
- property37({ type: String })
10380
- ], RelSelect.prototype, "selected", 2);
10381
- __decorateClass([
10382
- property37({ type: String })
10383
- ], RelSelect.prototype, "state", 2);
11532
+ property38({ type: String, reflect: true })
11533
+ ], RelSkeleton.prototype, "shape", 2);
10384
11534
  __decorateClass([
10385
- property37({ type: String })
10386
- ], RelSelect.prototype, "supportingText", 2);
11535
+ property38({ type: Number })
11536
+ ], RelSkeleton.prototype, "lines", 2);
10387
11537
  __decorateClass([
10388
- property37({ type: String })
10389
- ], RelSelect.prototype, "size", 2);
11538
+ property38({ type: String })
11539
+ ], RelSkeleton.prototype, "width", 2);
10390
11540
  __decorateClass([
10391
- property37({ type: String })
10392
- ], RelSelect.prototype, "border", 2);
11541
+ property38({ type: String })
11542
+ ], RelSkeleton.prototype, "height", 2);
10393
11543
  __decorateClass([
10394
- property37({ type: String })
10395
- ], RelSelect.prototype, "leftIcon", 2);
11544
+ property38({ type: String, reflect: true })
11545
+ ], RelSkeleton.prototype, "animation", 2);
10396
11546
  __decorateClass([
10397
- property37({ type: String })
10398
- ], RelSelect.prototype, "rightIcon", 2);
10399
- RelSelect = __decorateClass([
10400
- customElement44("rel-select")
10401
- ], RelSelect);
11547
+ property38({ type: Boolean, reflect: true })
11548
+ ], RelSkeleton.prototype, "loaded", 2);
11549
+ RelSkeleton = __decorateClass([
11550
+ customElement45("rel-skeleton")
11551
+ ], RelSkeleton);
10402
11552
 
10403
11553
  // src/components/rel-sheet/rel-sheet.ts
10404
- import { LitElement as LitElement45, html as html45, css as css42 } from "lit";
10405
- import { customElement as customElement45, property as property38, query as query7 } from "lit/decorators.js";
11554
+ import { LitElement as LitElement46, html as html46, css as css43 } from "lit";
11555
+ import { customElement as customElement46, property as property39, query as query8 } from "lit/decorators.js";
10406
11556
  import "./vars-v2-VMGWTFJZ.css";
10407
11557
  import "@reliability-design/icons/rel-icon";
10408
- var RelModal = class extends LitElement45 {
11558
+ var RelModal = class extends LitElement46 {
10409
11559
  constructor() {
10410
11560
  super(...arguments);
10411
11561
  this.open = false;
@@ -10515,7 +11665,7 @@ var RelModal = class extends LitElement45 {
10515
11665
  const hasTitle = !!this.title;
10516
11666
  const hasDescription = !!this.description;
10517
11667
  const showHeader = hasTitle || hasDescription || this.dismissible;
10518
- return html45`
11668
+ return html46`
10519
11669
  <div class="modal-container ${this.open ? "open" : ""}">
10520
11670
  <div
10521
11671
  part="overlay"
@@ -10532,10 +11682,10 @@ var RelModal = class extends LitElement45 {
10532
11682
 
10533
11683
  <div part="header" class="header ${!showHeader ? "empty" : ""}">
10534
11684
  <div class="header-text">
10535
- ${hasTitle ? html45`<h2 class="title">${this.title}</h2>` : ""}
10536
- ${hasDescription ? html45`<p class="description">${this.description}</p>` : ""}
11685
+ ${hasTitle ? html46`<h2 class="title">${this.title}</h2>` : ""}
11686
+ ${hasDescription ? html46`<p class="description">${this.description}</p>` : ""}
10537
11687
  </div>
10538
- ${this.dismissible ? html45`<button
11688
+ ${this.dismissible ? html46`<button
10539
11689
  part="close-button"
10540
11690
  class="close-button"
10541
11691
  @click="${this.handleCloseButtonClick}"
@@ -10556,7 +11706,7 @@ var RelModal = class extends LitElement45 {
10556
11706
  `;
10557
11707
  }
10558
11708
  };
10559
- RelModal.styles = css42`
11709
+ RelModal.styles = css43`
10560
11710
  :host {
10561
11711
  --modal-transition-duration: 0.3s;
10562
11712
  --modal-transition-timing: cubic-bezier(0.32, 0.72, 0, 1);
@@ -10606,7 +11756,8 @@ RelModal.styles = css42`
10606
11756
  font-family: var(--rel-fontFamilies-primary);
10607
11757
  width: clamp(360px, 49vw, 708px);
10608
11758
  left: 50%;
10609
- transition: transform var(--modal-transition-duration) var(--modal-transition-timing);
11759
+ transition: transform var(--modal-transition-duration) var(--modal-transition-timing),
11760
+ opacity var(--modal-transition-duration) var(--modal-transition-timing);
10610
11761
  }
10611
11762
 
10612
11763
  .panel[data-side="bottom"] {
@@ -10641,11 +11792,13 @@ RelModal.styles = css42`
10641
11792
  width: clamp(360px, 49vw, 708px);
10642
11793
  max-height: calc(100vh - 96px);
10643
11794
  border-radius: var(--rel-borders-radius-border-radius-200);
10644
- transform: translate(-50%, -50%);
11795
+ transform: translate(-50%, -50%) scale(0.96);
11796
+ opacity: 0;
10645
11797
  }
10646
11798
 
10647
11799
  .modal-container.open .panel[data-side="center"] {
10648
- transform: translate(-50%, -50%);
11800
+ transform: translate(-50%, -50%) scale(1);
11801
+ opacity: 1;
10649
11802
  }
10650
11803
 
10651
11804
  .header {
@@ -10739,35 +11892,35 @@ RelModal.styles = css42`
10739
11892
  }
10740
11893
  `;
10741
11894
  __decorateClass([
10742
- property38({ type: Boolean, reflect: true })
11895
+ property39({ type: Boolean, reflect: true })
10743
11896
  ], RelModal.prototype, "open", 2);
10744
11897
  __decorateClass([
10745
- property38({ type: String })
11898
+ property39({ type: String })
10746
11899
  ], RelModal.prototype, "side", 2);
10747
11900
  __decorateClass([
10748
- property38({ type: String })
11901
+ property39({ type: String })
10749
11902
  ], RelModal.prototype, "title", 2);
10750
11903
  __decorateClass([
10751
- property38({ type: String })
11904
+ property39({ type: String })
10752
11905
  ], RelModal.prototype, "description", 2);
10753
11906
  __decorateClass([
10754
- property38({ type: Boolean })
11907
+ property39({ type: Boolean })
10755
11908
  ], RelModal.prototype, "dismissible", 2);
10756
11909
  __decorateClass([
10757
- property38({ type: Boolean })
11910
+ property39({ type: Boolean })
10758
11911
  ], RelModal.prototype, "modal", 2);
10759
11912
  __decorateClass([
10760
- query7(".overlay")
11913
+ query8(".overlay")
10761
11914
  ], RelModal.prototype, "overlayElement", 2);
10762
11915
  RelModal = __decorateClass([
10763
- customElement45("rel-modal")
11916
+ customElement46("rel-modal")
10764
11917
  ], RelModal);
10765
11918
 
10766
11919
  // src/components/rel-slider/rel-slider.ts
10767
- import { LitElement as LitElement46, html as html46, css as css43 } from "lit";
10768
- import { customElement as customElement46, property as property39, state as state13 } from "lit/decorators.js";
11920
+ import { LitElement as LitElement47, html as html47, css as css44 } from "lit";
11921
+ import { customElement as customElement47, property as property40, state as state15 } from "lit/decorators.js";
10769
11922
  import "./vars-v2-VMGWTFJZ.css";
10770
- var RelSlider = class extends LitElement46 {
11923
+ var RelSlider = class extends LitElement47 {
10771
11924
  constructor() {
10772
11925
  super(...arguments);
10773
11926
  this.type = "continuous";
@@ -10864,9 +12017,9 @@ var RelSlider = class extends LitElement46 {
10864
12017
  }
10865
12018
  }
10866
12019
  renderThumbContainer() {
10867
- return html46`
12020
+ return html47`
10868
12021
  <div class="thumb-container" style="left: ${this.percentage}%">
10869
- ${this.showBubble ? html46`
12022
+ ${this.showBubble ? html47`
10870
12023
  <div class="value-marker">
10871
12024
  <svg viewBox="0 0 24 32" xmlns="http://www.w3.org/2000/svg">
10872
12025
  <path
@@ -10891,10 +12044,10 @@ var RelSlider = class extends LitElement46 {
10891
12044
  }
10892
12045
  renderTicks() {
10893
12046
  if (this.type !== "discrete") return "";
10894
- return html46`
12047
+ return html47`
10895
12048
  <div class="ticks">
10896
12049
  ${this.ticks.map(
10897
- (tick) => html46`
12050
+ (tick) => html47`
10898
12051
  <div
10899
12052
  class="tick ${this.isTickActive(tick) ? "active" : ""}"
10900
12053
  style="left: ${this.getTickLeftPct(tick)}%"></div>
@@ -10905,10 +12058,10 @@ var RelSlider = class extends LitElement46 {
10905
12058
  }
10906
12059
  renderTickLabels() {
10907
12060
  if (this.type !== "discrete" || !this.showTickLabels) return "";
10908
- return html46`
12061
+ return html47`
10909
12062
  <div class="tick-labels">
10910
12063
  ${this.ticks.map(
10911
- (tick) => html46`
12064
+ (tick) => html47`
10912
12065
  <div
10913
12066
  class="tick-label"
10914
12067
  style="left: ${this.getTickLeftPct(tick)}%">
@@ -10929,7 +12082,7 @@ var RelSlider = class extends LitElement46 {
10929
12082
  "track-active",
10930
12083
  this.track === "dotted" ? "dotted" : ""
10931
12084
  ].filter(Boolean).join(" ");
10932
- return html46`
12085
+ return html47`
10933
12086
  <div class="${sliderClasses}">
10934
12087
  <div class="track"></div>
10935
12088
  <div class="${trackActiveClasses}"></div>
@@ -10952,7 +12105,7 @@ var RelSlider = class extends LitElement46 {
10952
12105
  `;
10953
12106
  }
10954
12107
  };
10955
- RelSlider.styles = css43`
12108
+ RelSlider.styles = css44`
10956
12109
  :host {
10957
12110
  --track-height: 5px;
10958
12111
  --thumb-size: 10px;
@@ -11227,45 +12380,45 @@ RelSlider.styles = css43`
11227
12380
  }
11228
12381
  `;
11229
12382
  __decorateClass([
11230
- property39({ type: String })
12383
+ property40({ type: String })
11231
12384
  ], RelSlider.prototype, "type", 2);
11232
12385
  __decorateClass([
11233
- property39({ type: Number })
12386
+ property40({ type: Number })
11234
12387
  ], RelSlider.prototype, "min", 2);
11235
12388
  __decorateClass([
11236
- property39({ type: Number })
12389
+ property40({ type: Number })
11237
12390
  ], RelSlider.prototype, "max", 2);
11238
12391
  __decorateClass([
11239
- property39({ type: Number })
12392
+ property40({ type: Number })
11240
12393
  ], RelSlider.prototype, "step", 2);
11241
12394
  __decorateClass([
11242
- property39({ type: Boolean })
12395
+ property40({ type: Boolean })
11243
12396
  ], RelSlider.prototype, "disabled", 2);
11244
12397
  __decorateClass([
11245
- property39({ type: String })
12398
+ property40({ type: String })
11246
12399
  ], RelSlider.prototype, "track", 2);
11247
12400
  __decorateClass([
11248
- property39({ type: Boolean })
12401
+ property40({ type: Boolean })
11249
12402
  ], RelSlider.prototype, "showTickLabels", 2);
11250
12403
  __decorateClass([
11251
- property39({ type: Boolean })
12404
+ property40({ type: Boolean })
11252
12405
  ], RelSlider.prototype, "showBubble", 2);
11253
12406
  __decorateClass([
11254
- property39({ type: Number })
12407
+ property40({ type: Number })
11255
12408
  ], RelSlider.prototype, "value", 2);
11256
12409
  __decorateClass([
11257
- state13()
12410
+ state15()
11258
12411
  ], RelSlider.prototype, "ticks", 2);
11259
12412
  RelSlider = __decorateClass([
11260
- customElement46("rel-slider")
12413
+ customElement47("rel-slider")
11261
12414
  ], RelSlider);
11262
12415
 
11263
12416
  // src/components/rel-snackbar/rel-snackbar.ts
11264
- import { LitElement as LitElement47, html as html47, css as css44 } from "lit";
11265
- import { customElement as customElement47, property as property40, state as state14 } from "lit/decorators.js";
12417
+ import { LitElement as LitElement48, html as html48, css as css45 } from "lit";
12418
+ import { customElement as customElement48, property as property41, state as state16 } from "lit/decorators.js";
11266
12419
  import "./vars-v2-VMGWTFJZ.css";
11267
12420
  import "@reliability-design/icons/rel-icon";
11268
- var RelSnackbar = class extends LitElement47 {
12421
+ var RelSnackbar = class extends LitElement48 {
11269
12422
  constructor() {
11270
12423
  super(...arguments);
11271
12424
  this.message = "This is a snackbar message";
@@ -11339,8 +12492,8 @@ var RelSnackbar = class extends LitElement47 {
11339
12492
  warning: "warning"
11340
12493
  };
11341
12494
  const name = iconMap[this.type];
11342
- if (!name) return html47``;
11343
- return html47`<rel-icon name="${name}" size="lg" class="snackbar-icon"></rel-icon>`;
12495
+ if (!name) return html48``;
12496
+ return html48`<rel-icon name="${name}" size="lg" class="snackbar-icon"></rel-icon>`;
11344
12497
  }
11345
12498
  render() {
11346
12499
  const snackbarClasses = [
@@ -11349,7 +12502,7 @@ var RelSnackbar = class extends LitElement47 {
11349
12502
  !this.visible ? "hidden" : "",
11350
12503
  this.type !== "default" ? `type-${this.type}` : ""
11351
12504
  ].filter(Boolean).join(" ");
11352
- return html47`
12505
+ return html48`
11353
12506
  <div class="${snackbarClasses}">
11354
12507
  <div class="snackbar-body">
11355
12508
  ${this.type !== "default" ? this.renderIcon() : ""}
@@ -11357,12 +12510,12 @@ var RelSnackbar = class extends LitElement47 {
11357
12510
  </div>
11358
12511
 
11359
12512
  <div class="snackbar-actions">
11360
- ${this.action ? html47`
12513
+ ${this.action ? html48`
11361
12514
  <button class="snackbar-action" @click="${this.onActionClick}">
11362
12515
  ${this.action}
11363
12516
  </button>
11364
12517
  ` : ""}
11365
- ${this.iconClose ? html47`
12518
+ ${this.iconClose ? html48`
11366
12519
  <button class="snackbar-close" @click="${this.dismiss}">
11367
12520
  <rel-icon name="close" size="md"></rel-icon>
11368
12521
  </button>
@@ -11372,7 +12525,7 @@ var RelSnackbar = class extends LitElement47 {
11372
12525
  `;
11373
12526
  }
11374
12527
  };
11375
- RelSnackbar.styles = css44`
12528
+ RelSnackbar.styles = css45`
11376
12529
  :host {
11377
12530
  display: block;
11378
12531
  font-family: var(--rel-fontFamilies-primary);
@@ -11546,41 +12699,41 @@ RelSnackbar.styles = css44`
11546
12699
  }
11547
12700
  `;
11548
12701
  __decorateClass([
11549
- property40({ type: String })
12702
+ property41({ type: String })
11550
12703
  ], RelSnackbar.prototype, "message", 2);
11551
12704
  __decorateClass([
11552
- property40({ type: String })
12705
+ property41({ type: String })
11553
12706
  ], RelSnackbar.prototype, "action", 2);
11554
12707
  __decorateClass([
11555
- property40({ type: Boolean })
12708
+ property41({ type: Boolean })
11556
12709
  ], RelSnackbar.prototype, "longerAction", 2);
11557
12710
  __decorateClass([
11558
- property40({ type: Boolean })
12711
+ property41({ type: Boolean })
11559
12712
  ], RelSnackbar.prototype, "iconClose", 2);
11560
12713
  __decorateClass([
11561
- property40({ type: String })
12714
+ property41({ type: String })
11562
12715
  ], RelSnackbar.prototype, "lines", 2);
11563
12716
  __decorateClass([
11564
- property40({ type: Number })
12717
+ property41({ type: Number })
11565
12718
  ], RelSnackbar.prototype, "duration", 2);
11566
12719
  __decorateClass([
11567
- property40({ type: String })
12720
+ property41({ type: String })
11568
12721
  ], RelSnackbar.prototype, "type", 2);
11569
12722
  __decorateClass([
11570
- property40({ type: Boolean, reflect: true })
12723
+ property41({ type: Boolean, reflect: true })
11571
12724
  ], RelSnackbar.prototype, "show", 2);
11572
12725
  __decorateClass([
11573
- state14()
12726
+ state16()
11574
12727
  ], RelSnackbar.prototype, "visible", 2);
11575
12728
  RelSnackbar = __decorateClass([
11576
- customElement47("rel-snackbar")
12729
+ customElement48("rel-snackbar")
11577
12730
  ], RelSnackbar);
11578
12731
 
11579
12732
  // src/components/rel-stepper/rel-stepper.ts
11580
- import { LitElement as LitElement48, html as html48, css as css45 } from "lit";
11581
- import { customElement as customElement48, property as property41 } from "lit/decorators.js";
12733
+ import { LitElement as LitElement49, html as html49, css as css46 } from "lit";
12734
+ import { customElement as customElement49, property as property42 } from "lit/decorators.js";
11582
12735
  import "./vars-v2-VMGWTFJZ.css";
11583
- var RelStepper = class extends LitElement48 {
12736
+ var RelStepper = class extends LitElement49 {
11584
12737
  constructor() {
11585
12738
  super(...arguments);
11586
12739
  this.steps = [];
@@ -11619,7 +12772,7 @@ var RelStepper = class extends LitElement48 {
11619
12772
  }
11620
12773
  renderIndicator(step, index) {
11621
12774
  if (step.status === "done") {
11622
- return html48`
12775
+ return html49`
11623
12776
  <svg
11624
12777
  xmlns="http://www.w3.org/2000/svg"
11625
12778
  width="14"
@@ -11635,7 +12788,7 @@ var RelStepper = class extends LitElement48 {
11635
12788
  </svg>
11636
12789
  `;
11637
12790
  }
11638
- return html48`<span>${index + 1}</span>`;
12791
+ return html49`<span>${index + 1}</span>`;
11639
12792
  }
11640
12793
  render() {
11641
12794
  const stepperClasses = [
@@ -11646,26 +12799,26 @@ var RelStepper = class extends LitElement48 {
11646
12799
  ].filter(Boolean).join(" ");
11647
12800
  const isVertical = this.orientation === "vertical";
11648
12801
  const isTextRight = this.textAlign === "right";
11649
- return html48`
12802
+ return html49`
11650
12803
  <div class="${stepperClasses}">
11651
12804
  ${this.steps.map(
11652
- (step, idx) => html48`
12805
+ (step, idx) => html49`
11653
12806
  <div
11654
12807
  class="${this.getStepClasses(step)}"
11655
12808
  @click="${() => this.onStepClick(step, idx)}"
11656
12809
  >
11657
- ${isVertical && isTextRight ? html48`
12810
+ ${isVertical && isTextRight ? html49`
11658
12811
  <!-- Indicator with connector below -->
11659
12812
  <div class="indicator-wrapper">
11660
12813
  <div class="indicator">
11661
12814
  ${this.renderIndicator(step, idx)}
11662
12815
  </div>
11663
- ${idx < this.steps.length - 1 ? html48`<div class="connector"></div>` : ""}
12816
+ ${idx < this.steps.length - 1 ? html49`<div class="connector"></div>` : ""}
11664
12817
  </div>
11665
12818
 
11666
12819
  <!-- Step Label to the right -->
11667
12820
  <div class="step-label">${step.title}</div>
11668
- ` : isVertical ? html48`
12821
+ ` : isVertical ? html49`
11669
12822
  <div class="step-content text-below-content">
11670
12823
  <!-- Step Indicator -->
11671
12824
  <div class="indicator">
@@ -11677,8 +12830,8 @@ var RelStepper = class extends LitElement48 {
11677
12830
  </div>
11678
12831
 
11679
12832
  <!-- Connector -->
11680
- ${idx < this.steps.length - 1 ? html48`<div class="connector"></div>` : ""}
11681
- ` : html48`
12833
+ ${idx < this.steps.length - 1 ? html49`<div class="connector"></div>` : ""}
12834
+ ` : html49`
11682
12835
  <!-- Step Indicator -->
11683
12836
  <div class="indicator">
11684
12837
  ${this.renderIndicator(step, idx)}
@@ -11688,7 +12841,7 @@ var RelStepper = class extends LitElement48 {
11688
12841
  <div class="step-label">${step.title}</div>
11689
12842
 
11690
12843
  <!-- Connector (for horizontal only) -->
11691
- ${!isVertical && idx < this.steps.length - 1 ? html48`<div class="connector"></div>` : ""}
12844
+ ${!isVertical && idx < this.steps.length - 1 ? html49`<div class="connector"></div>` : ""}
11692
12845
  `}
11693
12846
  </div>
11694
12847
  `
@@ -11697,7 +12850,7 @@ var RelStepper = class extends LitElement48 {
11697
12850
  `;
11698
12851
  }
11699
12852
  };
11700
- RelStepper.styles = css45`
12853
+ RelStepper.styles = css46`
11701
12854
  :host {
11702
12855
  display: block;
11703
12856
  font-family: var(--rel-fontFamilies-primary);
@@ -12001,26 +13154,26 @@ RelStepper.styles = css45`
12001
13154
  }
12002
13155
  `;
12003
13156
  __decorateClass([
12004
- property41({ type: Array })
13157
+ property42({ type: Array })
12005
13158
  ], RelStepper.prototype, "steps", 2);
12006
13159
  __decorateClass([
12007
- property41({ type: String })
13160
+ property42({ type: String })
12008
13161
  ], RelStepper.prototype, "textAlign", 2);
12009
13162
  __decorateClass([
12010
- property41({ type: String })
13163
+ property42({ type: String })
12011
13164
  ], RelStepper.prototype, "orientation", 2);
12012
13165
  __decorateClass([
12013
- property41({ type: String })
13166
+ property42({ type: String })
12014
13167
  ], RelStepper.prototype, "size", 2);
12015
13168
  RelStepper = __decorateClass([
12016
- customElement48("rel-stepper")
13169
+ customElement49("rel-stepper")
12017
13170
  ], RelStepper);
12018
13171
 
12019
13172
  // src/components/rel-switch/rel-switch.ts
12020
- import { LitElement as LitElement49, html as html49, css as css46 } from "lit";
12021
- import { customElement as customElement49, property as property42, state as state15 } from "lit/decorators.js";
13173
+ import { LitElement as LitElement50, html as html50, css as css47 } from "lit";
13174
+ import { customElement as customElement50, property as property43, state as state17 } from "lit/decorators.js";
12022
13175
  import "./vars-v2-VMGWTFJZ.css";
12023
- var RelSwitch = class extends LitElement49 {
13176
+ var RelSwitch = class extends LitElement50 {
12024
13177
  constructor() {
12025
13178
  super(...arguments);
12026
13179
  this.checked = false;
@@ -12079,7 +13232,7 @@ var RelSwitch = class extends LitElement49 {
12079
13232
  this.isFocused && "switch-focused",
12080
13233
  this.isPressed && "switch-pressed"
12081
13234
  ].filter(Boolean).join(" ");
12082
- return html49`
13235
+ return html50`
12083
13236
  <label class="${wrapperClasses}">
12084
13237
  <input
12085
13238
  type="checkbox"
@@ -12098,7 +13251,7 @@ var RelSwitch = class extends LitElement49 {
12098
13251
  `;
12099
13252
  }
12100
13253
  };
12101
- RelSwitch.styles = css46`
13254
+ RelSwitch.styles = css47`
12102
13255
  :host {
12103
13256
  --switch-track: var(--rel-color-text-placeholder);
12104
13257
  --switch-knob-on: var(--rel-color-text-primary);
@@ -12198,29 +13351,29 @@ RelSwitch.styles = css46`
12198
13351
  }
12199
13352
  `;
12200
13353
  __decorateClass([
12201
- property42({ type: Boolean })
13354
+ property43({ type: Boolean })
12202
13355
  ], RelSwitch.prototype, "checked", 2);
12203
13356
  __decorateClass([
12204
- property42({ type: Boolean })
13357
+ property43({ type: Boolean })
12205
13358
  ], RelSwitch.prototype, "disabled", 2);
12206
13359
  __decorateClass([
12207
- property42({ type: String })
13360
+ property43({ type: String })
12208
13361
  ], RelSwitch.prototype, "value", 2);
12209
13362
  __decorateClass([
12210
- state15()
13363
+ state17()
12211
13364
  ], RelSwitch.prototype, "isFocused", 2);
12212
13365
  __decorateClass([
12213
- state15()
13366
+ state17()
12214
13367
  ], RelSwitch.prototype, "isPressed", 2);
12215
13368
  RelSwitch = __decorateClass([
12216
- customElement49("rel-switch")
13369
+ customElement50("rel-switch")
12217
13370
  ], RelSwitch);
12218
13371
 
12219
13372
  // src/components/rel-tab/rel-tab.ts
12220
- import { LitElement as LitElement50, html as html50, css as css47 } from "lit";
12221
- import { customElement as customElement50, property as property43, state as state16 } from "lit/decorators.js";
13373
+ import { LitElement as LitElement51, html as html51, css as css48 } from "lit";
13374
+ import { customElement as customElement51, property as property44, state as state18 } from "lit/decorators.js";
12222
13375
  import "./vars-v2-VMGWTFJZ.css";
12223
- var RelTabItem = class extends LitElement50 {
13376
+ var RelTabItem = class extends LitElement51 {
12224
13377
  constructor() {
12225
13378
  super(...arguments);
12226
13379
  this.label = "";
@@ -12229,25 +13382,25 @@ var RelTabItem = class extends LitElement50 {
12229
13382
  this.disabled = false;
12230
13383
  }
12231
13384
  render() {
12232
- return html50``;
13385
+ return html51``;
12233
13386
  }
12234
13387
  };
12235
13388
  __decorateClass([
12236
- property43({ type: String })
13389
+ property44({ type: String })
12237
13390
  ], RelTabItem.prototype, "label", 2);
12238
13391
  __decorateClass([
12239
- property43({ type: String })
13392
+ property44({ type: String })
12240
13393
  ], RelTabItem.prototype, "value", 2);
12241
13394
  __decorateClass([
12242
- property43({ type: Number })
13395
+ property44({ type: Number })
12243
13396
  ], RelTabItem.prototype, "badge", 2);
12244
13397
  __decorateClass([
12245
- property43({ type: Boolean })
13398
+ property44({ type: Boolean })
12246
13399
  ], RelTabItem.prototype, "disabled", 2);
12247
13400
  RelTabItem = __decorateClass([
12248
- customElement50("rel-tab-item")
13401
+ customElement51("rel-tab-item")
12249
13402
  ], RelTabItem);
12250
- var RelTab = class extends LitElement50 {
13403
+ var RelTab = class extends LitElement51 {
12251
13404
  constructor() {
12252
13405
  super(...arguments);
12253
13406
  this.tabs = [];
@@ -12304,11 +13457,11 @@ var RelTab = class extends LitElement50 {
12304
13457
  }
12305
13458
  render() {
12306
13459
  const tabs = this._effectiveTabs;
12307
- return html50`
13460
+ return html51`
12308
13461
  <slot name="items" style="display:none;" @slotchange="${this._onSlotChange}"></slot>
12309
13462
  <div class="tabs-wrapper" role="tablist">
12310
13463
  ${tabs.map(
12311
- (tab, i) => html50`
13464
+ (tab, i) => html51`
12312
13465
  <div
12313
13466
  class="tab ${i === this.activeIndex ? "active" : ""} ${tab.disabled ? "disabled" : ""}"
12314
13467
  role="tab"
@@ -12319,7 +13472,7 @@ var RelTab = class extends LitElement50 {
12319
13472
  @keydown="${(e) => this.onKeyDown(e, i)}"
12320
13473
  >
12321
13474
  <span class="tab-label">${tab.label}</span>
12322
- ${tab.badge ? html50`<rel-badge number="${tab.badge}" variant="number" size="sm"></rel-badge>` : ""}
13475
+ ${tab.badge ? html51`<rel-badge number="${tab.badge}" variant="number" size="sm"></rel-badge>` : ""}
12323
13476
  <span class="tab-underline"></span>
12324
13477
  </div>
12325
13478
  `
@@ -12331,7 +13484,7 @@ var RelTab = class extends LitElement50 {
12331
13484
  `;
12332
13485
  }
12333
13486
  };
12334
- RelTab.styles = css47`
13487
+ RelTab.styles = css48`
12335
13488
  :host {
12336
13489
  --tab-active-color: var(--rel-colors-green-primary);
12337
13490
  --tab-text-default: var(--rel-color-text-primary);
@@ -12403,24 +13556,24 @@ RelTab.styles = css47`
12403
13556
  }
12404
13557
  `;
12405
13558
  __decorateClass([
12406
- property43({ type: Array })
13559
+ property44({ type: Array })
12407
13560
  ], RelTab.prototype, "tabs", 2);
12408
13561
  __decorateClass([
12409
- property43({ type: Number, reflect: true })
13562
+ property44({ type: Number, reflect: true })
12410
13563
  ], RelTab.prototype, "activeIndex", 2);
12411
13564
  __decorateClass([
12412
- state16()
13565
+ state18()
12413
13566
  ], RelTab.prototype, "_tabItems", 2);
12414
13567
  RelTab = __decorateClass([
12415
- customElement50("rel-tab")
13568
+ customElement51("rel-tab")
12416
13569
  ], RelTab);
12417
13570
 
12418
13571
  // src/components/rel-textfield/rel-textfield.ts
12419
- import { LitElement as LitElement51, html as html51, css as css48 } from "lit";
12420
- import { customElement as customElement51, property as property44, state as state17 } from "lit/decorators.js";
13572
+ import { LitElement as LitElement52, html as html52, css as css49 } from "lit";
13573
+ import { customElement as customElement52, property as property45, state as state19 } from "lit/decorators.js";
12421
13574
  import "./vars-v2-VMGWTFJZ.css";
12422
13575
  import "@reliability-design/icons/rel-icon";
12423
- var RelTextfield = class extends LitElement51 {
13576
+ var RelTextfield = class extends LitElement52 {
12424
13577
  constructor() {
12425
13578
  super(...arguments);
12426
13579
  this.placeholder = "";
@@ -12429,6 +13582,7 @@ var RelTextfield = class extends LitElement51 {
12429
13582
  this.state = "default";
12430
13583
  this.size = "medium";
12431
13584
  this.floatingLabel = false;
13585
+ this.variant = "default";
12432
13586
  this.internalState = "default";
12433
13587
  this._wasError = false;
12434
13588
  this.uniqueId = `textfield-${Math.random().toString(36).slice(2)}`;
@@ -12481,17 +13635,17 @@ var RelTextfield = class extends LitElement51 {
12481
13635
  this.leftIcon ? "has-left-icon" : "",
12482
13636
  this.rightIcon ? "has-right-icon" : ""
12483
13637
  ].filter(Boolean).join(" ");
12484
- return html51`
13638
+ return html52`
12485
13639
  <div class="${wrapperClasses}">
12486
- ${!this.floatingLabel && this.label ? html51`<label class="textfield-label" for="${this.uniqueId}">${this.label}</label>` : ""}
13640
+ ${!this.floatingLabel && this.label ? html52`<label class="textfield-label" for="${this.uniqueId}">${this.label}</label>` : ""}
12487
13641
 
12488
13642
  <div
12489
13643
  class="textfield-container ${this.state === "disabled" ? "disabled" : ""}"
12490
13644
  >
12491
- ${this.floatingLabel && this.label ? html51`<label
13645
+ ${this.floatingLabel && this.label ? html52`<label
12492
13646
  class="textfield-label${this.leftIcon ? " has-left-icon" : ""}"
12493
13647
  for="${this.uniqueId}">${this.label}</label>` : ""}
12494
- ${this.leftIcon ? html51`<rel-icon name="${this.leftIcon}" size="sm" class="icon left"></rel-icon>` : ""}
13648
+ ${this.leftIcon ? html52`<rel-icon name="${this.leftIcon}" size="sm" class="icon left"></rel-icon>` : ""}
12495
13649
 
12496
13650
  <input
12497
13651
  type="${this.type}"
@@ -12506,10 +13660,10 @@ var RelTextfield = class extends LitElement51 {
12506
13660
  @input="${this.handleInput}"
12507
13661
  />
12508
13662
 
12509
- ${this.rightIcon ? html51`<rel-icon name="${this.rightIcon}" size="sm" class="icon right"></rel-icon>` : ""}
13663
+ ${this.rightIcon ? html52`<rel-icon name="${this.rightIcon}" size="sm" class="icon right"></rel-icon>` : ""}
12510
13664
  </div>
12511
13665
 
12512
- ${this.supportingText ? html51`<div
13666
+ ${this.supportingText ? html52`<div
12513
13667
  class="textfield-support ${this.state === "error" ? "error" : ""}"
12514
13668
  >
12515
13669
  ${this.supportingText}
@@ -12518,7 +13672,7 @@ var RelTextfield = class extends LitElement51 {
12518
13672
  `;
12519
13673
  }
12520
13674
  };
12521
- RelTextfield.styles = css48`
13675
+ RelTextfield.styles = css49`
12522
13676
  :host {
12523
13677
  display: block;
12524
13678
  font-family: var(--rel-fontFamilies-primary);
@@ -12717,7 +13871,7 @@ RelTextfield.styles = css48`
12717
13871
  }
12718
13872
 
12719
13873
  .textfield-support.error {
12720
- color: var(--rel-error-text);
13874
+ color: var(--rel-error-surface-default, #CC0000);
12721
13875
  }
12722
13876
 
12723
13877
  /* Placeholder */
@@ -12725,6 +13879,14 @@ RelTextfield.styles = css48`
12725
13879
  color: var(--rel-color-text-placeholder);
12726
13880
  }
12727
13881
 
13882
+ :host([floatinglabel]) .textfield-input::placeholder {
13883
+ opacity: 0;
13884
+ }
13885
+
13886
+ :host([floatinglabel]) .textfield-wrapper.focused .textfield-input::placeholder {
13887
+ opacity: 1;
13888
+ }
13889
+
12728
13890
  /* Suppress Chrome autofill blue background */
12729
13891
  .textfield-input:-webkit-autofill,
12730
13892
  .textfield-input:-webkit-autofill:hover,
@@ -12732,49 +13894,90 @@ RelTextfield.styles = css48`
12732
13894
  -webkit-box-shadow: 0 0 0px 1000px var(--rel-color-bg-primary) inset;
12733
13895
  -webkit-text-fill-color: var(--rel-color-text-primary);
12734
13896
  }
13897
+
13898
+ /* ── Underline variant ── */
13899
+ :host([variant="underline"]) .textfield-container {
13900
+ border: none;
13901
+ border-bottom: 2px solid var(--rel-color-border-default);
13902
+ border-radius: 0;
13903
+ background: var(--rel-color-bg-tertiary, #f5f5f5);
13904
+ box-shadow: none;
13905
+ overflow: visible;
13906
+ }
13907
+
13908
+ :host([variant="underline"]) .textfield-wrapper.focused .textfield-container,
13909
+ :host([variant="underline"]) .textfield-container:focus-within {
13910
+ border-bottom: 2px solid var(--rel-color-text-primary);
13911
+ box-shadow: none;
13912
+ }
13913
+
13914
+ :host([variant="underline"]) .textfield-wrapper.error .textfield-container {
13915
+ border-bottom: 2px solid var(--rel-error-surface-default, #CC0000);
13916
+ box-shadow: none;
13917
+ }
13918
+
13919
+ :host([variant="underline"]) .textfield-wrapper.disabled .textfield-container {
13920
+ border-bottom: 2px solid var(--rel-color-border-default);
13921
+ background: var(--rel-color-bg-tertiary);
13922
+ }
13923
+
13924
+ /* Remove border radius on input for underline variant */
13925
+ :host([variant="underline"]) .textfield-input {
13926
+ background: transparent;
13927
+ }
13928
+
13929
+ /* Dark mode — underline variant uses same border colors as default */
13930
+ :host-context([data-theme="dark"]) :host([variant="underline"]) .textfield-container,
13931
+ :host-context(.dark) :host([variant="underline"]) .textfield-container {
13932
+ background: var(--rel-color-bg-tertiary);
13933
+ border-bottom-color: var(--rel-color-border-default);
13934
+ }
12735
13935
  `;
12736
13936
  __decorateClass([
12737
- property44({ type: String })
13937
+ property45({ type: String })
12738
13938
  ], RelTextfield.prototype, "label", 2);
12739
13939
  __decorateClass([
12740
- property44({ type: String })
13940
+ property45({ type: String })
12741
13941
  ], RelTextfield.prototype, "placeholder", 2);
12742
13942
  __decorateClass([
12743
- property44({ type: String })
13943
+ property45({ type: String })
12744
13944
  ], RelTextfield.prototype, "type", 2);
12745
13945
  __decorateClass([
12746
- property44({ type: String })
13946
+ property45({ type: String })
12747
13947
  ], RelTextfield.prototype, "value", 2);
12748
13948
  __decorateClass([
12749
- property44({ type: String })
13949
+ property45({ type: String })
12750
13950
  ], RelTextfield.prototype, "leftIcon", 2);
12751
13951
  __decorateClass([
12752
- property44({ type: String })
13952
+ property45({ type: String })
12753
13953
  ], RelTextfield.prototype, "rightIcon", 2);
12754
13954
  __decorateClass([
12755
- property44({ type: String })
13955
+ property45({ type: String })
12756
13956
  ], RelTextfield.prototype, "supportingText", 2);
12757
13957
  __decorateClass([
12758
- property44({ type: String })
13958
+ property45({ type: String })
12759
13959
  ], RelTextfield.prototype, "state", 2);
12760
13960
  __decorateClass([
12761
- property44({ type: String })
13961
+ property45({ type: String })
12762
13962
  ], RelTextfield.prototype, "size", 2);
12763
13963
  __decorateClass([
12764
- property44({ type: Boolean, reflect: true })
13964
+ property45({ type: Boolean, reflect: true })
12765
13965
  ], RelTextfield.prototype, "floatingLabel", 2);
12766
13966
  __decorateClass([
12767
- state17()
13967
+ property45({ type: String, reflect: true })
13968
+ ], RelTextfield.prototype, "variant", 2);
13969
+ __decorateClass([
13970
+ state19()
12768
13971
  ], RelTextfield.prototype, "internalState", 2);
12769
13972
  RelTextfield = __decorateClass([
12770
- customElement51("rel-textfield")
13973
+ customElement52("rel-textfield")
12771
13974
  ], RelTextfield);
12772
13975
 
12773
13976
  // src/components/rel-toast/rel-toast.ts
12774
- import { LitElement as LitElement52, html as html52, css as css49 } from "lit";
12775
- import { customElement as customElement52, property as property45, state as state18 } from "lit/decorators.js";
13977
+ import { LitElement as LitElement53, html as html53, css as css50 } from "lit";
13978
+ import { customElement as customElement53, property as property46, state as state20 } from "lit/decorators.js";
12776
13979
  import "./vars-v2-VMGWTFJZ.css";
12777
- var RelToast = class extends LitElement52 {
13980
+ var RelToast = class extends LitElement53 {
12778
13981
  constructor() {
12779
13982
  super(...arguments);
12780
13983
  this.message = "";
@@ -12832,11 +14035,11 @@ var RelToast = class extends LitElement52 {
12832
14035
  this.close();
12833
14036
  }
12834
14037
  render() {
12835
- return html52`
14038
+ return html53`
12836
14039
  <div class="toast ${this.type} ${this.visible ? "" : "hidden"}" role="status" aria-live="polite">
12837
14040
  <span class="toast-message">${this.message}</span>
12838
14041
 
12839
- ${this.actionLabel ? html52`<button
14042
+ ${this.actionLabel ? html53`<button
12840
14043
  class="toast-action"
12841
14044
  @click="${this.handleActionClick}"
12842
14045
  >
@@ -12848,7 +14051,7 @@ var RelToast = class extends LitElement52 {
12848
14051
  `;
12849
14052
  }
12850
14053
  };
12851
- RelToast.styles = css49`
14054
+ RelToast.styles = css50`
12852
14055
  :host {
12853
14056
  position: fixed;
12854
14057
  bottom: 24px;
@@ -12895,7 +14098,7 @@ RelToast.styles = css49`
12895
14098
  .toast-action {
12896
14099
  background: transparent;
12897
14100
  border: none;
12898
- color: var(--rel-colors-green-primary);
14101
+ color: inherit;
12899
14102
  font-weight: 600;
12900
14103
  font-size: 0.85rem;
12901
14104
  cursor: pointer;
@@ -12936,11 +14139,6 @@ RelToast.styles = css49`
12936
14139
  }
12937
14140
 
12938
14141
  /* Dark mode overrides */
12939
- :host-context([data-theme="dark"]) .toast-action,
12940
- :host-context(.dark) .toast-action {
12941
- color: var(--rel-colors-green-tertiary);
12942
- }
12943
-
12944
14142
  :host-context([data-theme="dark"]) .toast.error,
12945
14143
  :host-context(.dark) .toast.error {
12946
14144
  background-color: var(--rel-error-surface-default);
@@ -12966,31 +14164,31 @@ RelToast.styles = css49`
12966
14164
  }
12967
14165
  `;
12968
14166
  __decorateClass([
12969
- property45({ type: String })
14167
+ property46({ type: String })
12970
14168
  ], RelToast.prototype, "message", 2);
12971
14169
  __decorateClass([
12972
- property45({ type: String })
14170
+ property46({ type: String })
12973
14171
  ], RelToast.prototype, "type", 2);
12974
14172
  __decorateClass([
12975
- property45({ type: String })
14173
+ property46({ type: String })
12976
14174
  ], RelToast.prototype, "actionLabel", 2);
12977
14175
  __decorateClass([
12978
- property45({ type: Number })
14176
+ property46({ type: Number })
12979
14177
  ], RelToast.prototype, "duration", 2);
12980
14178
  __decorateClass([
12981
- property45({ type: Boolean, reflect: true })
14179
+ property46({ type: Boolean, reflect: true })
12982
14180
  ], RelToast.prototype, "show", 2);
12983
14181
  __decorateClass([
12984
- state18()
14182
+ state20()
12985
14183
  ], RelToast.prototype, "visible", 2);
12986
14184
  RelToast = __decorateClass([
12987
- customElement52("rel-toast")
14185
+ customElement53("rel-toast")
12988
14186
  ], RelToast);
12989
14187
 
12990
14188
  // src/components/rel-tooltip/rel-tooltip.ts
12991
- import { LitElement as LitElement53, html as html53, css as css50 } from "lit";
12992
- import { customElement as customElement53, property as property46 } from "lit/decorators.js";
12993
- var RelTooltip = class extends LitElement53 {
14189
+ import { LitElement as LitElement54, html as html54, css as css51 } from "lit";
14190
+ import { customElement as customElement54, property as property47 } from "lit/decorators.js";
14191
+ var RelTooltip = class extends LitElement54 {
12994
14192
  constructor() {
12995
14193
  super(...arguments);
12996
14194
  this.text = "";
@@ -13011,7 +14209,7 @@ var RelTooltip = class extends LitElement53 {
13011
14209
  }
13012
14210
  }
13013
14211
  render() {
13014
- return html53`
14212
+ return html54`
13015
14213
  <slot @slotchange="${this.linkTrigger}"></slot>
13016
14214
  <div
13017
14215
  class="tooltip-bubble ${this.position}"
@@ -13019,12 +14217,12 @@ var RelTooltip = class extends LitElement53 {
13019
14217
  role="tooltip"
13020
14218
  >
13021
14219
  ${this.text}
13022
- ${this.showTail ? html53`<span class="tooltip-tail"></span>` : ""}
14220
+ ${this.showTail ? html54`<span class="tooltip-tail"></span>` : ""}
13023
14221
  </div>
13024
14222
  `;
13025
14223
  }
13026
14224
  };
13027
- RelTooltip.styles = css50`
14225
+ RelTooltip.styles = css51`
13028
14226
  :host {
13029
14227
  display: inline-block;
13030
14228
  position: relative;
@@ -13105,16 +14303,16 @@ RelTooltip.styles = css50`
13105
14303
  }
13106
14304
  `;
13107
14305
  __decorateClass([
13108
- property46({ type: String })
14306
+ property47({ type: String })
13109
14307
  ], RelTooltip.prototype, "text", 2);
13110
14308
  __decorateClass([
13111
- property46({ type: String })
14309
+ property47({ type: String })
13112
14310
  ], RelTooltip.prototype, "position", 2);
13113
14311
  __decorateClass([
13114
- property46({ type: Boolean, attribute: "show-tail" })
14312
+ property47({ type: Boolean, attribute: "show-tail" })
13115
14313
  ], RelTooltip.prototype, "showTail", 2);
13116
14314
  RelTooltip = __decorateClass([
13117
- customElement53("rel-tooltip")
14315
+ customElement54("rel-tooltip")
13118
14316
  ], RelTooltip);
13119
14317
 
13120
14318
  // src/index.ts
@@ -13157,6 +14355,7 @@ export {
13157
14355
  RelResizablePanel,
13158
14356
  RelSegmentedButton,
13159
14357
  RelSelect,
14358
+ RelSkeleton,
13160
14359
  RelSlider,
13161
14360
  RelSnackbar,
13162
14361
  RelStepper,