@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.
@@ -70,7 +70,8 @@ export class RelModal extends LitElement {
70
70
  font-family: var(--rel-fontFamilies-primary);
71
71
  width: clamp(360px, 49vw, 708px);
72
72
  left: 50%;
73
- transition: transform var(--modal-transition-duration) var(--modal-transition-timing);
73
+ transition: transform var(--modal-transition-duration) var(--modal-transition-timing),
74
+ opacity var(--modal-transition-duration) var(--modal-transition-timing);
74
75
  }
75
76
 
76
77
  .panel[data-side="bottom"] {
@@ -105,11 +106,13 @@ export class RelModal extends LitElement {
105
106
  width: clamp(360px, 49vw, 708px);
106
107
  max-height: calc(100vh - 96px);
107
108
  border-radius: var(--rel-borders-radius-border-radius-200);
108
- transform: translate(-50%, -50%);
109
+ transform: translate(-50%, -50%) scale(0.96);
110
+ opacity: 0;
109
111
  }
110
112
 
111
113
  .modal-container.open .panel[data-side="center"] {
112
- transform: translate(-50%, -50%);
114
+ transform: translate(-50%, -50%) scale(1);
115
+ opacity: 1;
113
116
  }
114
117
 
115
118
  .header {
@@ -0,0 +1,139 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+
4
+ export type SkeletonShape = "line" | "circle" | "block";
5
+ export type SkeletonAnimation = "pulse" | "shimmer" | "none";
6
+
7
+ @customElement("rel-skeleton")
8
+ export class RelSkeleton extends LitElement {
9
+ @property({ type: String, reflect: true }) shape: SkeletonShape = "block";
10
+ @property({ type: Number }) lines = 1;
11
+ @property({ type: String }) width = "";
12
+ @property({ type: String }) height = "";
13
+ @property({ type: String, reflect: true }) animation: SkeletonAnimation = "pulse";
14
+ @property({ type: Boolean, reflect: true }) loaded = false;
15
+
16
+ protected override updated(changed: Map<string, unknown>) {
17
+ if (changed.has("width") && this.width) this.style.width = this.width;
18
+ if (changed.has("height") && this.height) this.style.height = this.height;
19
+ }
20
+
21
+ static styles = css`
22
+ :host {
23
+ display: block;
24
+ }
25
+
26
+ :host([loaded]) {
27
+ display: none;
28
+ }
29
+
30
+ /* ── Circle: aspect-ratio keeps it square without requiring explicit height ── */
31
+ :host([shape="circle"]) {
32
+ aspect-ratio: 1 / 1;
33
+ }
34
+
35
+ /* ── Base skeleton surface ── */
36
+ .skeleton-shape,
37
+ .skeleton-bar {
38
+ background: var(--rel-skeleton-color, #c8c8c8);
39
+ border-radius: 4px;
40
+ }
41
+
42
+ /* ── Lines layout ── */
43
+ .skeleton-lines {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: 8px;
47
+ width: 100%;
48
+ }
49
+
50
+ .skeleton-bar {
51
+ height: 14px;
52
+ width: 100%;
53
+ }
54
+
55
+ /* Last line shortens to 65% — mimics real paragraph text that doesn't reach the edge */
56
+ .skeleton-bar.is-last {
57
+ width: 65%;
58
+ }
59
+
60
+ /* ── Shape (circle / block) ── */
61
+ .skeleton-shape {
62
+ width: 100%;
63
+ height: 100%;
64
+ min-height: 16px;
65
+ }
66
+
67
+ :host([shape="circle"]) .skeleton-shape {
68
+ border-radius: 50%;
69
+ /* No min-height — circle is sized entirely by host width + aspect-ratio */
70
+ min-height: unset;
71
+ }
72
+
73
+ /* ── Pulse animation ── */
74
+ @keyframes rel-skeleton-pulse {
75
+ 0%, 100% { opacity: 1; }
76
+ 50% { opacity: 0.4; }
77
+ }
78
+
79
+ :host([animation="pulse"]) .skeleton-shape,
80
+ :host([animation="pulse"]) .skeleton-bar {
81
+ animation: rel-skeleton-pulse 1.5s ease-in-out infinite;
82
+ }
83
+
84
+ /* ── Shimmer animation ── */
85
+ @keyframes rel-skeleton-shimmer {
86
+ 0% { background-position: 200% center; }
87
+ 100% { background-position: -200% center; }
88
+ }
89
+
90
+ :host([animation="shimmer"]) .skeleton-shape,
91
+ :host([animation="shimmer"]) .skeleton-bar {
92
+ background: linear-gradient(
93
+ 90deg,
94
+ var(--rel-skeleton-color, #c8c8c8) 25%,
95
+ var(--rel-skeleton-highlight, #e2e2e2) 50%,
96
+ var(--rel-skeleton-color, #c8c8c8) 75%
97
+ );
98
+ background-size: 200% 100%;
99
+ animation: rel-skeleton-shimmer 1.5s linear infinite;
100
+ }
101
+
102
+ /* ── Dark mode ── */
103
+ :host-context([data-theme="dark"]) {
104
+ --rel-skeleton-color: #2a2a2a;
105
+ --rel-skeleton-highlight: #3d3d3d;
106
+ }
107
+
108
+ /* ── Respect reduced-motion preference ── */
109
+ @media (prefers-reduced-motion: reduce) {
110
+ .skeleton-shape,
111
+ .skeleton-bar {
112
+ animation: none !important;
113
+ }
114
+ }
115
+ `;
116
+
117
+ render() {
118
+ if (this.loaded) return html``;
119
+
120
+ if (this.shape === "line") {
121
+ const count = Math.max(1, this.lines);
122
+ return html`
123
+ <div class="skeleton-lines">
124
+ ${Array.from({ length: count }, (_, i) => html`
125
+ <div class="skeleton-bar ${i === count - 1 && count > 1 ? "is-last" : ""}"></div>
126
+ `)}
127
+ </div>
128
+ `;
129
+ }
130
+
131
+ return html`<div class="skeleton-shape"></div>`;
132
+ }
133
+ }
134
+
135
+ declare global {
136
+ interface HTMLElementTagNameMap {
137
+ "rel-skeleton": RelSkeleton;
138
+ }
139
+ }
@@ -5,6 +5,7 @@ import "@reliability-design/icons/rel-icon";
5
5
 
6
6
  export type TextFieldState = "default" | "error" | "disabled";
7
7
  export type TextFieldSize = "small" | "medium" | "large";
8
+ export type TextFieldVariant = "default" | "underline";
8
9
 
9
10
  @customElement("rel-textfield")
10
11
  export class RelTextfield extends LitElement {
@@ -18,6 +19,7 @@ export class RelTextfield extends LitElement {
18
19
  @property({ type: String }) state: TextFieldState = "default";
19
20
  @property({ type: String }) size: TextFieldSize = "medium";
20
21
  @property({ type: Boolean, reflect: true }) floatingLabel = false;
22
+ @property({ type: String, reflect: true }) variant: TextFieldVariant = "default";
21
23
 
22
24
  @state() private internalState: "default" | "focused" = "default";
23
25
  private _wasError = false;
@@ -223,7 +225,7 @@ export class RelTextfield extends LitElement {
223
225
  }
224
226
 
225
227
  .textfield-support.error {
226
- color: var(--rel-error-text);
228
+ color: var(--rel-error-surface-default, #CC0000);
227
229
  }
228
230
 
229
231
  /* Placeholder */
@@ -231,6 +233,14 @@ export class RelTextfield extends LitElement {
231
233
  color: var(--rel-color-text-placeholder);
232
234
  }
233
235
 
236
+ :host([floatinglabel]) .textfield-input::placeholder {
237
+ opacity: 0;
238
+ }
239
+
240
+ :host([floatinglabel]) .textfield-wrapper.focused .textfield-input::placeholder {
241
+ opacity: 1;
242
+ }
243
+
234
244
  /* Suppress Chrome autofill blue background */
235
245
  .textfield-input:-webkit-autofill,
236
246
  .textfield-input:-webkit-autofill:hover,
@@ -238,6 +248,44 @@ export class RelTextfield extends LitElement {
238
248
  -webkit-box-shadow: 0 0 0px 1000px var(--rel-color-bg-primary) inset;
239
249
  -webkit-text-fill-color: var(--rel-color-text-primary);
240
250
  }
251
+
252
+ /* ── Underline variant ── */
253
+ :host([variant="underline"]) .textfield-container {
254
+ border: none;
255
+ border-bottom: 2px solid var(--rel-color-border-default);
256
+ border-radius: 0;
257
+ background: var(--rel-color-bg-tertiary, #f5f5f5);
258
+ box-shadow: none;
259
+ overflow: visible;
260
+ }
261
+
262
+ :host([variant="underline"]) .textfield-wrapper.focused .textfield-container,
263
+ :host([variant="underline"]) .textfield-container:focus-within {
264
+ border-bottom: 2px solid var(--rel-color-text-primary);
265
+ box-shadow: none;
266
+ }
267
+
268
+ :host([variant="underline"]) .textfield-wrapper.error .textfield-container {
269
+ border-bottom: 2px solid var(--rel-error-surface-default, #CC0000);
270
+ box-shadow: none;
271
+ }
272
+
273
+ :host([variant="underline"]) .textfield-wrapper.disabled .textfield-container {
274
+ border-bottom: 2px solid var(--rel-color-border-default);
275
+ background: var(--rel-color-bg-tertiary);
276
+ }
277
+
278
+ /* Remove border radius on input for underline variant */
279
+ :host([variant="underline"]) .textfield-input {
280
+ background: transparent;
281
+ }
282
+
283
+ /* Dark mode — underline variant uses same border colors as default */
284
+ :host-context([data-theme="dark"]) :host([variant="underline"]) .textfield-container,
285
+ :host-context(.dark) :host([variant="underline"]) .textfield-container {
286
+ background: var(--rel-color-bg-tertiary);
287
+ border-bottom-color: var(--rel-color-border-default);
288
+ }
241
289
  `;
242
290
 
243
291
  connectedCallback() {
@@ -62,7 +62,7 @@ export class RelToast extends LitElement {
62
62
  .toast-action {
63
63
  background: transparent;
64
64
  border: none;
65
- color: var(--rel-colors-green-primary);
65
+ color: inherit;
66
66
  font-weight: 600;
67
67
  font-size: 0.85rem;
68
68
  cursor: pointer;
@@ -103,11 +103,6 @@ export class RelToast extends LitElement {
103
103
  }
104
104
 
105
105
  /* Dark mode overrides */
106
- :host-context([data-theme="dark"]) .toast-action,
107
- :host-context(.dark) .toast-action {
108
- color: var(--rel-colors-green-tertiary);
109
- }
110
-
111
106
  :host-context([data-theme="dark"]) .toast.error,
112
107
  :host-context(.dark) .toast.error {
113
108
  background-color: var(--rel-error-surface-default);
package/dist/index.d.mts CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as lit_html from 'lit-html';
2
2
  import * as lit from 'lit';
3
- import { LitElement } from 'lit';
3
+ import { LitElement, PropertyValues } from 'lit';
4
4
  export * from '@reliability-design/icons';
5
5
 
6
6
  declare class RelAccordion extends LitElement {
7
7
  title: string;
8
8
  open: boolean;
9
+ size: "md" | "sm";
10
+ type: "default" | "action";
9
11
  static styles: lit.CSSResult;
10
12
  private toggle;
11
- private chevron;
12
13
  render(): lit_html.TemplateResult<1>;
13
14
  }
14
15
 
@@ -29,10 +30,12 @@ declare class RelAlert extends LitElement {
29
30
  declare class RelAvatar extends LitElement {
30
31
  size: "lg" | "md" | "sm" | "xs";
31
32
  type: "image" | "text" | "icon";
33
+ variant: "fill" | "subtle" | "outline";
32
34
  src: string;
33
35
  text: string;
34
36
  alt: string;
35
37
  bg: string;
38
+ color: string;
36
39
  static styles: lit.CSSResult;
37
40
  render(): lit_html.TemplateResult<1>;
38
41
  }
@@ -43,8 +46,23 @@ declare class RelBadge extends LitElement {
43
46
  suffix: string;
44
47
  size: "sm" | "md" | "lg";
45
48
  variant: "dot" | "number";
49
+ /**
50
+ * Direct CSS color override for the badge background. Accepts any valid
51
+ * CSS color value: hex, rgb(...), hsl(...), named color, or var(--token).
52
+ *
53
+ * Clear it (set to `''`) to fall back to the default token.
54
+ */
55
+ color: string;
56
+ /**
57
+ * Direct CSS color override for the badge text/icon color. Accepts any
58
+ * valid CSS color value: hex, rgb(...), hsl(...), named color, or var(--token).
59
+ *
60
+ * Clear it (set to `''`) to fall back to the default (white).
61
+ */
62
+ textColor: string;
46
63
  static styles: lit.CSSResult;
47
64
  private get classes();
65
+ updated(changedProperties: Map<PropertyKey, unknown>): void;
48
66
  render(): lit_html.TemplateResult<1>;
49
67
  }
50
68
 
@@ -66,6 +84,9 @@ declare class RelButton extends LitElement {
66
84
  disabled: boolean;
67
85
  ariaLabel: string | null;
68
86
  static styles: lit.CSSResult;
87
+ connectedCallback(): void;
88
+ disconnectedCallback(): void;
89
+ private handleHostClick;
69
90
  private get classes();
70
91
  private handleClick;
71
92
  render(): lit_html.TemplateResult<1>;
@@ -246,6 +267,14 @@ declare class RelRangePicker extends LitElement {
246
267
  disabled: boolean;
247
268
  open: boolean;
248
269
  mode: "popover" | "popup";
270
+ width: string;
271
+ minWidth: string;
272
+ maxWidth: string;
273
+ height: string;
274
+ minHeight: string;
275
+ maxHeight: string;
276
+ placeholder: string;
277
+ triggerVariant: "default" | "icon";
249
278
  private draftFrom;
250
279
  private draftTo;
251
280
  private draftActivePreset;
@@ -257,6 +286,7 @@ declare class RelRangePicker extends LitElement {
257
286
  static styles: lit.CSSResult;
258
287
  connectedCallback(): void;
259
288
  disconnectedCallback(): void;
289
+ updated(): void;
260
290
  private handleClickOutside;
261
291
  private handleGlobalKeydown;
262
292
  private toggleOpen;
@@ -265,6 +295,8 @@ declare class RelRangePicker extends LitElement {
265
295
  private applySelection;
266
296
  private resetDraft;
267
297
  private getTriggerLabel;
298
+ /** Formatted "MM/DD/YYYY → MM/DD/YYYY" (or single date / "") for the current committed `from`/`to`. */
299
+ get displayLabel(): string;
268
300
  private parseISODate;
269
301
  private formatISODate;
270
302
  private formatDisplayDate;
@@ -287,9 +319,18 @@ declare global {
287
319
  }
288
320
  }
289
321
 
322
+ type ChipTone = "neutral" | "danger" | "warning" | "success" | "info";
323
+ type ChipVariant = "fill" | "subtle";
324
+ type ChipSize = "sm" | "md" | "lg";
325
+ type ChipBorder = "default" | "rounded";
290
326
  declare class RelChip extends LitElement {
327
+ static shadowRootOptions: ShadowRootInit;
291
328
  label: string;
292
- tone: "default" | "blue" | "orange" | "red" | "green";
329
+ tone: ChipTone;
330
+ variant: ChipVariant;
331
+ size: ChipSize;
332
+ border: ChipBorder;
333
+ /** Icon name from the generated icon dictionary (e.g. "settings") — rendered via <rel-icon>. */
293
334
  leadingIcon?: string;
294
335
  trailingIcon?: string;
295
336
  /** Initials text for the avatar (e.g. "JD"). Mutually exclusive with leadingIcon. */
@@ -297,11 +338,22 @@ declare class RelChip extends LitElement {
297
338
  removable: boolean;
298
339
  /** IMPORTANT: reflected so CSS + Angular can see it */
299
340
  removed: boolean;
341
+ /** Opt-in native drag-and-drop — reflects the Figma "Dragged" state automatically during a real drag gesture. */
342
+ draggableChip: boolean;
343
+ /** Reflected so CSS can target the Figma "Dragged" visual state. Driven automatically by dragstart/dragend when draggableChip is set. */
344
+ private dragging;
300
345
  static styles: lit.CSSResult;
301
346
  private get classes();
302
347
  private handleRemove;
348
+ private onDragStart;
349
+ private onDragEnd;
350
+ protected updated(changed: Map<string, unknown>): void;
303
351
  render(): lit_html.TemplateResult<1>;
304
- private renderIcon;
352
+ }
353
+ declare global {
354
+ interface HTMLElementTagNameMap {
355
+ "rel-chip": RelChip;
356
+ }
305
357
  }
306
358
 
307
359
  declare class RelContainer extends LitElement {
@@ -460,6 +512,7 @@ declare class RelRadio extends LitElement {
460
512
  registerOnChange(fn: (value: string) => void): void;
461
513
  registerOnTouched(fn: () => void): void;
462
514
  writeValue(value: string): void;
515
+ private get hasSelection();
463
516
  private renderOption;
464
517
  render(): lit_html.TemplateResult<1>;
465
518
  }
@@ -472,7 +525,7 @@ declare class RelMenubar extends LitElement {
472
525
  private openSubmenuElement;
473
526
  private hoverSwitchEnabled;
474
527
  private _onScroll?;
475
- static readonly _css = "\n :host {\n display: block;\n }\n\n :host > slot {\n display: none;\n }\n\n .menubar-container {\n display: flex;\n align-items: stretch;\n background: var(--rel-color-bg-secondary);\n border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);\n border-radius: var(--rel-borders-radius-border-radius-200);\n overflow: hidden;\n padding: 0;\n gap: var(--rel-spacing-space-3xs);\n font-family: var(--rel-fontFamilies-primary);\n font-size: var(--rel-fontSizes-sm);\n height: 40px;\n }\n\n .menubar-trigger {\n display: flex;\n align-items: center;\n align-self: stretch;\n height: 100%;\n padding: 0 var(--rel-spacing-space-sm);\n background: transparent;\n border: none;\n cursor: pointer;\n font-family: inherit;\n font-size: inherit;\n color: var(--rel-color-text-heading);\n transition: background 0.15s ease;\n user-select: none;\n outline: none;\n }\n\n .menubar-trigger:hover,\n .menubar-trigger.active {\n background: var(--rel-color-bg-selected);\n }\n\n .menubar-trigger:focus-visible {\n outline: 2px solid var(--rel-color-border-focus);\n outline-offset: 2px;\n }\n\n .menubar-panel {\n position: fixed;\n min-width: 220px;\n background: var(--rel-color-bg-primary);\n border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);\n border-radius: var(--rel-borders-radius-border-radius-200);\n box-shadow: var(--rel-shadows-shadow-300);\n padding: 0;\n overflow: hidden;\n z-index: 1000;\n display: none;\n }\n\n .menubar-panel.open {\n display: block;\n }\n\n .menu-item {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--rel-spacing-space-sm);\n padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-md);\n cursor: pointer;\n transition: background 0.15s ease;\n user-select: none;\n color: var(--rel-color-text-heading);\n line-height: var(--rel-lineHeights-sm);\n }\n\n .menu-item:hover,\n .menu-item.focused {\n background: var(--rel-color-bg-selected);\n }\n\n .menu-item[data-disabled=\"true\"] {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .menu-separator {\n height: var(--rel-borders-width-stroke-100);\n background: var(--rel-color-border-divider);\n margin: 0;\n padding: 0;\n }\n\n rel-icon {\n display: inline-flex;\n pointer-events: none;\n }\n\n .menu-submenu-trigger {\n position: relative;\n }\n\n .menu-submenu-trigger rel-icon {\n opacity: 0.6;\n }\n\n .submenu-panel {\n position: fixed;\n min-width: 200px;\n background: var(--rel-color-bg-primary);\n border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);\n border-radius: var(--rel-borders-radius-border-radius-200);\n box-shadow: var(--rel-shadows-shadow-300);\n padding: 0;\n overflow: hidden;\n z-index: 1001;\n display: none;\n }\n\n .submenu-panel.open {\n display: block;\n }\n\n .menu-shortcut {\n opacity: 0.6;\n font-size: var(--rel-fontSizes-xs);\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: var(--rel-spacing-space-3xs);\n }\n\n .menubar-panel rel-checkbox {\n display: block;\n width: 100%;\n padding: var(--rel-spacing-space-xs, 8px) var(--rel-spacing-space-md, 16px);\n box-sizing: border-box;\n cursor: pointer;\n }\n ";
528
+ static readonly _css = "\n :host {\n display: block;\n }\n\n :host > slot {\n display: none;\n }\n\n .menubar-container {\n display: flex;\n align-items: stretch;\n background: var(--rel-color-bg-secondary);\n border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);\n border-radius: var(--rel-borders-radius-border-radius-200);\n overflow: hidden;\n padding: 0;\n gap: var(--rel-spacing-space-3xs);\n font-family: var(--rel-fontFamilies-primary);\n font-size: var(--rel-fontSizes-sm);\n height: 40px;\n width: fit-content;\n }\n\n .menubar-trigger {\n display: flex;\n align-items: center;\n align-self: stretch;\n height: 100%;\n padding: 0 var(--rel-spacing-space-sm);\n background: transparent;\n border: none;\n cursor: pointer;\n font-family: inherit;\n font-size: inherit;\n color: var(--rel-color-text-heading);\n transition: background 0.15s ease;\n user-select: none;\n outline: none;\n }\n\n .menubar-trigger:hover,\n .menubar-trigger.active {\n background: var(--rel-color-bg-selected);\n }\n\n .menubar-trigger:focus-visible {\n outline: 2px solid var(--rel-color-border-focus);\n outline-offset: 2px;\n }\n\n .menubar-panel {\n position: fixed;\n min-width: 220px;\n background: var(--rel-color-bg-primary);\n border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);\n border-radius: var(--rel-borders-radius-border-radius-200);\n box-shadow: var(--rel-shadows-shadow-300);\n padding: 0;\n overflow: hidden;\n z-index: 1000;\n display: none;\n }\n\n .menubar-panel.open {\n display: block;\n }\n\n .menu-item {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--rel-spacing-space-sm);\n padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-md);\n cursor: pointer;\n transition: background 0.15s ease;\n user-select: none;\n color: var(--rel-color-text-heading);\n line-height: var(--rel-lineHeights-sm);\n }\n\n .menu-item:hover,\n .menu-item.focused {\n background: var(--rel-color-bg-selected);\n }\n\n .menu-item[data-disabled=\"true\"] {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .menu-separator {\n height: var(--rel-borders-width-stroke-100);\n background: var(--rel-color-border-divider);\n margin: 0;\n padding: 0;\n }\n\n rel-icon {\n display: inline-flex;\n pointer-events: none;\n }\n\n .menu-submenu-trigger {\n position: relative;\n }\n\n .menu-submenu-trigger rel-icon {\n opacity: 0.6;\n }\n\n .submenu-panel {\n position: fixed;\n min-width: 200px;\n background: var(--rel-color-bg-primary);\n border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);\n border-radius: var(--rel-borders-radius-border-radius-200);\n box-shadow: var(--rel-shadows-shadow-300);\n padding: 0;\n overflow: hidden;\n z-index: 1001;\n display: none;\n }\n\n .submenu-panel.open {\n display: block;\n }\n\n .menu-shortcut {\n opacity: 0.6;\n font-size: var(--rel-fontSizes-xs);\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: var(--rel-spacing-space-3xs);\n }\n\n .menubar-panel rel-checkbox {\n display: block;\n width: 100%;\n padding: var(--rel-spacing-space-xs, 8px) var(--rel-spacing-space-md, 16px);\n box-sizing: border-box;\n cursor: pointer;\n }\n ";
476
529
  createRenderRoot(): this;
477
530
  connectedCallback(): void;
478
531
  disconnectedCallback(): void;
@@ -759,31 +812,38 @@ declare global {
759
812
  }
760
813
  }
761
814
 
762
- type DensityType = "comfortable" | "compact";
763
- type VariantType = "default" | "icons";
764
815
  declare class RelPagination extends LitElement {
816
+ /** Layout type from Figma: extended (numbered pages), compact (prev/next + page text), count-text (range + nav) */
817
+ type: "extended" | "compact" | "count-text";
818
+ /** Controlled current page */
765
819
  page?: number;
820
+ /** Uncontrolled starting page */
766
821
  defaultPage: number;
822
+ /** Total number of pages */
767
823
  totalPages: number;
768
- siblingCount: number;
769
- boundaryCount: number;
824
+ /** Total items (used with perPage to auto-compute totalPages in count-text mode) */
825
+ totalItems: number;
826
+ /** Items per page (count-text mode) */
827
+ perPage: number;
828
+ /** Show "Viewing page X of Y" label below extended pagination */
829
+ showLabel: boolean;
770
830
  disabled: boolean;
771
- density: DensityType;
772
- variant: VariantType;
773
831
  hrefTemplate: string;
774
832
  ariaLabel: string;
775
833
  private currentPage;
776
834
  static styles: lit.CSSResult;
777
835
  connectedCallback(): void;
778
- updated(changedProperties: Map<string, any>): void;
836
+ updated(changedProperties: Map<string, unknown>): void;
779
837
  private get activePage();
780
- private generatePageItems;
838
+ private get computedTotalPages();
839
+ private generatePageNumbers;
781
840
  private handlePageChange;
782
- private getHref;
783
- private handleKeyDown;
784
- private renderPrevIcon;
785
- private renderNextIcon;
786
- private renderItem;
841
+ private renderChevronLeft;
842
+ private renderChevronRight;
843
+ private renderNavBtn;
844
+ private renderExtended;
845
+ private renderCompact;
846
+ private renderCountText;
787
847
  render(): lit_html.TemplateResult<1>;
788
848
  }
789
849
 
@@ -945,21 +1005,101 @@ declare class RelSegmentedButton extends LitElement {
945
1005
  type SelectState = "default" | "error" | "disabled";
946
1006
  type SelectSize = "small" | "medium" | "large";
947
1007
  type SelectBorder = "rounded" | "sharp";
1008
+ type SelectLabelStyle = "default" | "floating";
1009
+ interface SelectOptionObject {
1010
+ value: string;
1011
+ label?: string;
1012
+ supportingText?: string;
1013
+ }
1014
+ type SelectOption = string | SelectOptionObject;
948
1015
  declare class RelSelect extends LitElement {
949
1016
  label: string;
950
- options: string[];
1017
+ labelStyle: SelectLabelStyle;
1018
+ options: SelectOption[];
1019
+ /** Enables multi-select: selected values render as removable chips and options as checkboxes. */
1020
+ multiple: boolean;
1021
+ /** Selected value — single-select mode only. */
951
1022
  selected: string;
1023
+ /** Selected values — multi-select mode only. */
1024
+ selectedValues: string[];
952
1025
  state: SelectState;
953
1026
  supportingText: string;
954
1027
  size: SelectSize;
955
1028
  border: SelectBorder;
956
1029
  leftIcon: string;
957
1030
  rightIcon: string;
1031
+ placeholder: string;
1032
+ searchPlaceholder: string;
1033
+ selectAllLabel: string;
1034
+ /** Max selected chips shown before collapsing the rest into a "+N" badge. */
1035
+ maxVisibleChips: number;
1036
+ /** Hides the in-panel search field. Figma's "Single Option" dropdown has no search bar at all — use this for short, non-searchable lists. */
1037
+ noSearch: boolean;
1038
+ private open;
1039
+ private highlightedIndex;
1040
+ private panelStyle;
1041
+ private searchValue;
1042
+ private internalState;
1043
+ private triggerEl;
1044
+ private searchInputEl;
1045
+ private listboxEl;
1046
+ private uniqueId;
958
1047
  static styles: lit.CSSResult;
959
- connectedCallback(): void;
960
- private onChange;
1048
+ disconnectedCallback(): void;
1049
+ protected willUpdate(changed: PropertyValues<this>): void;
1050
+ private get normalizedOptions();
1051
+ /** Options matching the current search text (substring match, case-insensitive). */
1052
+ private get filteredOptions();
1053
+ private get hasValue();
1054
+ /** Icon size scales with the select's own size, matching the trigger. */
1055
+ private get iconSize();
1056
+ /** The search field uses "small" sizing for both small and medium select — only "large" select bumps it to "medium". */
1057
+ private get searchIconSize();
1058
+ private get selectAllStatus();
1059
+ private addGlobalListeners;
1060
+ private removeGlobalListeners;
1061
+ private onOutsidePointerDown;
1062
+ private onPageScroll;
1063
+ private emitChange;
1064
+ private openListbox;
1065
+ private closeListbox;
1066
+ private updatePosition;
1067
+ private selectSingleOption;
1068
+ private toggleMultiOption;
1069
+ private toggleSelectAll;
1070
+ private removeChip;
1071
+ private onTriggerClick;
1072
+ private onTriggerKeyDown;
1073
+ private onSearchInput;
1074
+ private onSearchKeyDown;
1075
+ private handleListNavigation;
1076
+ private renderChips;
961
1077
  render(): lit_html.TemplateResult<1>;
962
1078
  }
1079
+ declare global {
1080
+ interface HTMLElementTagNameMap {
1081
+ "rel-select": RelSelect;
1082
+ }
1083
+ }
1084
+
1085
+ type SkeletonShape = "line" | "circle" | "block";
1086
+ type SkeletonAnimation = "pulse" | "shimmer" | "none";
1087
+ declare class RelSkeleton extends LitElement {
1088
+ shape: SkeletonShape;
1089
+ lines: number;
1090
+ width: string;
1091
+ height: string;
1092
+ animation: SkeletonAnimation;
1093
+ loaded: boolean;
1094
+ protected updated(changed: Map<string, unknown>): void;
1095
+ static styles: lit.CSSResult;
1096
+ render(): lit_html.TemplateResult<1>;
1097
+ }
1098
+ declare global {
1099
+ interface HTMLElementTagNameMap {
1100
+ "rel-skeleton": RelSkeleton;
1101
+ }
1102
+ }
963
1103
 
964
1104
  type ModalSide = "top" | "bottom" | "center";
965
1105
  declare class RelModal extends LitElement {
@@ -1120,6 +1260,7 @@ declare class RelTab extends LitElement {
1120
1260
 
1121
1261
  type TextFieldState = "default" | "error" | "disabled";
1122
1262
  type TextFieldSize = "small" | "medium" | "large";
1263
+ type TextFieldVariant = "default" | "underline";
1123
1264
  declare class RelTextfield extends LitElement {
1124
1265
  label?: string;
1125
1266
  placeholder: string;
@@ -1131,6 +1272,7 @@ declare class RelTextfield extends LitElement {
1131
1272
  state: TextFieldState;
1132
1273
  size: TextFieldSize;
1133
1274
  floatingLabel: boolean;
1275
+ variant: TextFieldVariant;
1134
1276
  private internalState;
1135
1277
  private _wasError;
1136
1278
  private uniqueId;
@@ -1172,4 +1314,4 @@ declare class RelTooltip extends LitElement {
1172
1314
  render(): lit_html.TemplateResult<1>;
1173
1315
  }
1174
1316
 
1175
- export { type BreadcrumbItem, type DrawerCloseReason, type DrawerSide, type MenuItem, type MenuType, type ModalSide, type Orientation, type OtpType, type ProgressMode, type RadioOption, RelAccordion, RelAlert, RelAvatar, RelBadge, RelBreadcrumbs, RelButton, RelCalendar, RelCard, RelCardMedia, RelCarousel, RelCheckbox, RelChip, RelContainer, RelDatePicker, RelDivider, RelDrawer, RelDrawerFooter, RelKbd, RelLayout, RelMenu, RelMenuItem, RelMenubar, RelMenubarMenu, RelModal, RelNavbar, RelOtp, RelPagination, RelPopover, RelPopoverContent, RelProgress, RelRadio, RelRangePicker, RelResizableGroup, RelResizableHandle, RelResizablePanel, RelSegmentedButton, RelSelect, RelSlider, RelSnackbar, RelStepper, RelSwitch, RelTab, RelTabItem, RelTextfield, RelToast, RelTooltip, RelTopbar, RelTopbarActions, RelTopbarBrand, RelTopbarDropdown, RelTopbarDropdownItem, RelTopbarItem, RelTopbarMobilePanel, RelTopbarProfile, RelTopbarUtilities, type SegmentAlign, type SegmentOption, type SegmentSize, type SelectBorder, type SelectSize, type SelectState, type SliderType, type SnackbarLines, type SnackbarType, type Step, type StepStatus, type StepperSize, type TabItem, type TextAlign, type TextFieldSize, type TextFieldState, type ToastType, type TooltipPosition, type TopbarForceLayout, type TopbarProfileType, type TopbarRewardTier, type TopbarVariant, type TrackStyle };
1317
+ export { type BreadcrumbItem, type ChipBorder, type ChipSize, type ChipTone, type ChipVariant, type DrawerCloseReason, type DrawerSide, type MenuItem, type MenuType, type ModalSide, type Orientation, type OtpType, type ProgressMode, type RadioOption, RelAccordion, RelAlert, RelAvatar, RelBadge, RelBreadcrumbs, RelButton, RelCalendar, RelCard, RelCardMedia, RelCarousel, RelCheckbox, RelChip, RelContainer, RelDatePicker, RelDivider, RelDrawer, RelDrawerFooter, RelKbd, RelLayout, RelMenu, RelMenuItem, RelMenubar, RelMenubarMenu, RelModal, RelNavbar, RelOtp, RelPagination, RelPopover, RelPopoverContent, RelProgress, RelRadio, RelRangePicker, RelResizableGroup, RelResizableHandle, RelResizablePanel, RelSegmentedButton, RelSelect, RelSkeleton, RelSlider, RelSnackbar, RelStepper, RelSwitch, RelTab, RelTabItem, RelTextfield, RelToast, RelTooltip, RelTopbar, RelTopbarActions, RelTopbarBrand, RelTopbarDropdown, RelTopbarDropdownItem, RelTopbarItem, RelTopbarMobilePanel, RelTopbarProfile, RelTopbarUtilities, type SegmentAlign, type SegmentOption, type SegmentSize, type SelectBorder, type SelectLabelStyle, type SelectOption, type SelectOptionObject, type SelectSize, type SelectState, type SkeletonAnimation, type SkeletonShape, type SliderType, type SnackbarLines, type SnackbarType, type Step, type StepStatus, type StepperSize, type TabItem, type TextAlign, type TextFieldSize, type TextFieldState, type TextFieldVariant, type ToastType, type TooltipPosition, type TopbarForceLayout, type TopbarProfileType, type TopbarRewardTier, type TopbarVariant, type TrackStyle };