@reliability-design/web 1.3.1 → 1.4.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/components/rel-accordion/README.md +13 -13
- package/dist/components/rel-accordion/rel-accordion.ts +80 -45
- package/dist/components/rel-alert/README.md +15 -15
- package/dist/components/rel-alert/rel-alert.ts +153 -158
- package/dist/components/rel-avatar/README.md +15 -15
- package/dist/components/rel-avatar/rel-avatar.ts +42 -38
- package/dist/components/rel-badge/README.md +5 -5
- package/dist/components/rel-badge/rel-badge.ts +46 -11
- package/dist/components/rel-breadcrumb/README.md +7 -7
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +16 -13
- package/dist/components/rel-button/README.md +20 -20
- package/dist/components/rel-button/rel-button.ts +292 -105
- package/dist/components/rel-calendar/README.md +5 -5
- package/dist/components/rel-calendar/rel-calendar.ts +61 -45
- package/dist/components/rel-card/README.md +6 -6
- package/dist/components/rel-card/rel-card.ts +88 -35
- package/dist/components/rel-cardmedia/README.md +9 -9
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +27 -20
- package/dist/components/rel-carousel/README.md +3 -3
- package/dist/components/rel-carousel/rel-carousel.ts +174 -90
- package/dist/components/rel-chart/README.md +8 -8
- package/dist/components/rel-chart/rel-chart.ts +59 -41
- package/dist/components/rel-checkbox/README.md +7 -7
- package/dist/components/rel-checkbox/rel-checkbox.ts +61 -61
- package/dist/components/rel-chip/README.md +16 -16
- package/dist/components/rel-chip/rel-chip.ts +143 -111
- package/dist/components/rel-container/README.md +11 -11
- package/dist/components/rel-container/rel-container.ts +35 -9
- package/dist/components/rel-date-picker/README.md +43 -7
- package/dist/components/rel-date-picker/date-format.test.ts +43 -0
- package/dist/components/rel-date-picker/date-format.ts +47 -0
- package/dist/components/rel-date-picker/rel-date-picker.ts +154 -82
- package/dist/components/rel-divider/README.md +9 -9
- package/dist/components/rel-divider/rel-divider.ts +10 -9
- package/dist/components/rel-drawer/README.md +1 -1
- package/dist/components/rel-drawer/rel-drawer-footer.ts +1 -1
- package/dist/components/rel-drawer/rel-drawer.ts +56 -28
- package/dist/components/rel-kbd/README.md +20 -20
- package/dist/components/rel-kbd/rel-kbd.ts +119 -25
- package/dist/components/rel-layout/README.md +1 -1
- package/dist/components/rel-layout/rel-layout.ts +2 -2
- package/dist/components/rel-menu/README.md +15 -15
- package/dist/components/rel-menu/rel-menu.ts +155 -88
- package/dist/components/rel-menubar/README.md +20 -20
- package/dist/components/rel-menubar/rel-menubar.ts +47 -31
- package/dist/components/rel-nav-menu/README.md +21 -21
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +17 -14
- package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +33 -14
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +14 -7
- package/dist/components/rel-navbar/README.md +7 -7
- package/dist/components/rel-navbar/rel-navbar.ts +12 -11
- package/dist/components/rel-otp/README.md +3 -3
- package/dist/components/rel-otp/rel-otp.ts +46 -30
- package/dist/components/rel-pagination/README.md +18 -18
- package/dist/components/rel-pagination/rel-pagination.ts +141 -90
- package/dist/components/rel-popover/README.md +13 -13
- package/dist/components/rel-popover/rel-popover-content.ts +39 -14
- package/dist/components/rel-popover/rel-popover.ts +18 -7
- package/dist/components/rel-progress/README.md +5 -5
- package/dist/components/rel-progress/rel-progress.ts +16 -12
- package/dist/components/rel-radio/README.md +9 -9
- package/dist/components/rel-radio/rel-radio.ts +64 -50
- package/dist/components/rel-range-picker/rel-range-picker.ts +120 -117
- package/dist/components/rel-resizable/README.md +4 -4
- package/dist/components/rel-resizable/rel-resizable-group.ts +15 -4
- package/dist/components/rel-resizable/rel-resizable-handle.ts +13 -9
- package/dist/components/rel-resizable/rel-resizable-panel.ts +11 -0
- package/dist/components/rel-segmented-button/README.md +10 -10
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +39 -40
- package/dist/components/rel-select/README.md +14 -14
- package/dist/components/rel-select/rel-select.ts +120 -188
- package/dist/components/rel-sheet/README.md +10 -10
- package/dist/components/rel-sheet/rel-sheet.ts +82 -23
- package/dist/components/rel-sidebar/README.md +5 -5
- package/dist/components/rel-sidebar/rel-sidebar.ts +75 -60
- package/dist/components/rel-skeleton/rel-skeleton.ts +8 -13
- package/dist/components/rel-slider/README.md +10 -10
- package/dist/components/rel-slider/rel-slider.ts +230 -57
- package/dist/components/rel-snackbar/README.md +9 -9
- package/dist/components/rel-snackbar/rel-snackbar.ts +44 -32
- package/dist/components/rel-stepper/README.md +10 -10
- package/dist/components/rel-stepper/rel-stepper.ts +110 -46
- package/dist/components/rel-switch/README.md +5 -5
- package/dist/components/rel-switch/rel-switch.ts +23 -12
- package/dist/components/rel-tab/README.md +13 -13
- package/dist/components/rel-tab/rel-tab.ts +63 -19
- package/dist/components/rel-table/README.md +7 -7
- package/dist/components/rel-table/rel-table-body.ts +2 -1
- package/dist/components/rel-table/rel-table-caption.ts +10 -7
- package/dist/components/rel-table/rel-table-cell.ts +7 -6
- package/dist/components/rel-table/rel-table-footer.ts +4 -3
- package/dist/components/rel-table/rel-table-head.ts +11 -9
- package/dist/components/rel-table/rel-table-header.ts +2 -1
- package/dist/components/rel-table/rel-table-row.ts +5 -4
- package/dist/components/rel-table/rel-table.ts +16 -7
- package/dist/components/rel-textfield/README.md +11 -11
- package/dist/components/rel-textfield/rel-textfield.ts +172 -91
- package/dist/components/rel-toast/README.md +11 -11
- package/dist/components/rel-toast/rel-toast.ts +33 -30
- package/dist/components/rel-tooltip/README.md +7 -7
- package/dist/components/rel-tooltip/rel-tooltip.ts +160 -123
- package/dist/components/rel-topbar/rel-topbar-actions.ts +1 -2
- package/dist/components/rel-topbar/rel-topbar-brand.ts +8 -5
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +10 -8
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +4 -5
- package/dist/components/rel-topbar/rel-topbar-item.ts +23 -22
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +0 -1
- package/dist/components/rel-topbar/rel-topbar-profile.ts +68 -50
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +1 -2
- package/dist/components/rel-topbar/rel-topbar.ts +31 -29
- package/dist/index.d.mts +151 -39
- package/dist/index.d.ts +151 -39
- package/dist/index.js +3544 -2289
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3876 -2622
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +653 -363
- package/dist/vars-WY2XCF5G.css +653 -0
- package/package.json +3 -2
- package/dist/components/rel-range-picker/rel-range-picker.css +0 -349
- package/dist/styles/vars-v2.css +0 -525
- package/dist/vars-F54UGCHM.css +0 -363
- package/dist/vars-v2-VMGWTFJZ.css +0 -525
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { LitElement, html, css, nothing } from "lit";
|
|
2
2
|
import { customElement, property, state, query } from "lit/decorators.js";
|
|
3
|
-
import "../../styles/vars-v2.css";
|
|
4
3
|
|
|
5
4
|
@customElement("rel-carousel")
|
|
6
5
|
export class RelCarousel extends LitElement {
|
|
@@ -11,7 +10,17 @@ export class RelCarousel extends LitElement {
|
|
|
11
10
|
@property({ type: Boolean, attribute: "pause-on-hover" }) pauseOnHover = true;
|
|
12
11
|
@property({ type: Boolean, attribute: "show-buttons" }) showButtons = false;
|
|
13
12
|
@property({ type: Boolean, attribute: "show-dots" }) showDots = false;
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Figma "Type" axis. When set it drives which controls render:
|
|
16
|
+
* default = content only · only-indicators = dots · side-arrows = overlaid
|
|
17
|
+
* arrows + dots · bottom-arrows = dots flanked by arrows below the slide.
|
|
18
|
+
* When unset, the legacy show-buttons/show-dots booleans apply unchanged.
|
|
19
|
+
*/
|
|
20
|
+
@property({ type: String, reflect: true })
|
|
21
|
+
type?: "default" | "only-indicators" | "side-arrows" | "bottom-arrows";
|
|
22
|
+
|
|
23
|
+
@property({ type: String, reflect: true }) orientation: "horizontal" | "vertical" = "horizontal";
|
|
15
24
|
@property({ type: String }) label: string = "Carousel";
|
|
16
25
|
@property({ type: Number }) gap?: number;
|
|
17
26
|
@property({ type: Boolean, reflect: true }) disabled = false;
|
|
@@ -36,8 +45,9 @@ export class RelCarousel extends LitElement {
|
|
|
36
45
|
|
|
37
46
|
static styles = css`
|
|
38
47
|
:host {
|
|
48
|
+
color: var(--rel-text-default);
|
|
39
49
|
display: block;
|
|
40
|
-
font-family: var(--rel-
|
|
50
|
+
font-family: var(--rel-fonts-font-family);
|
|
41
51
|
position: relative;
|
|
42
52
|
user-select: none;
|
|
43
53
|
}
|
|
@@ -62,6 +72,21 @@ export class RelCarousel extends LitElement {
|
|
|
62
72
|
will-change: transform;
|
|
63
73
|
}
|
|
64
74
|
|
|
75
|
+
/* Vertical orientation: column track inside a fixed-height viewport */
|
|
76
|
+
:host([orientation="vertical"]) .viewport {
|
|
77
|
+
height: var(--rel-carousel-height, 320px);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:host([orientation="vertical"]) .track {
|
|
81
|
+
flex-direction: column;
|
|
82
|
+
height: 100%;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:host([orientation="vertical"]) ::slotted(*) {
|
|
86
|
+
width: 100% !important;
|
|
87
|
+
height: var(--rel-carousel-slide-height, 100%) !important;
|
|
88
|
+
}
|
|
89
|
+
|
|
65
90
|
.track.dragging {
|
|
66
91
|
transition: none;
|
|
67
92
|
}
|
|
@@ -85,9 +110,30 @@ export class RelCarousel extends LitElement {
|
|
|
85
110
|
display: flex;
|
|
86
111
|
align-items: center;
|
|
87
112
|
justify-content: center;
|
|
88
|
-
background: var(--rel-
|
|
113
|
+
background: var(--rel-bg-neutral-elevated-1);
|
|
89
114
|
}
|
|
90
115
|
|
|
116
|
+
/* Default typography for slotted slide captions (Figma roles) */
|
|
117
|
+
::slotted(h1), ::slotted(h2), ::slotted(h3), ::slotted(h4) {
|
|
118
|
+
font-family: var(--rel-headings-sm-font-family);
|
|
119
|
+
font-weight: var(--rel-headings-sm-font-weight);
|
|
120
|
+
font-size: var(--rel-headings-xs-font-size);
|
|
121
|
+
line-height: var(--rel-headings-xs-line-height);
|
|
122
|
+
letter-spacing: var(--rel-headings-xs-letter-spacing);
|
|
123
|
+
margin: 0 0 var(--rel-spacing-2xs) 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
::slotted(p) {
|
|
127
|
+
font-family: var(--rel-body-sm-regular-font-family);
|
|
128
|
+
font-weight: var(--rel-body-sm-regular-font-weight);
|
|
129
|
+
font-size: var(--rel-body-sm-regular-font-size);
|
|
130
|
+
line-height: var(--rel-body-sm-regular-line-height);
|
|
131
|
+
letter-spacing: var(--rel-body-sm-regular-letter-spacing);
|
|
132
|
+
color: var(--rel-text-body);
|
|
133
|
+
margin: 0 0 var(--rel-spacing-lg) 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
91
137
|
/* Navigation buttons */
|
|
92
138
|
.nav-button {
|
|
93
139
|
position: absolute;
|
|
@@ -97,9 +143,9 @@ export class RelCarousel extends LitElement {
|
|
|
97
143
|
width: var(--rel-carousel-nav-size, 40px);
|
|
98
144
|
height: var(--rel-carousel-nav-size, 40px);
|
|
99
145
|
border-radius: 50%;
|
|
100
|
-
border: 1px solid var(--rel-
|
|
101
|
-
background: var(--rel-
|
|
102
|
-
color: var(--rel-
|
|
146
|
+
border: 1px solid var(--rel-border-default);
|
|
147
|
+
background: var(--rel-bg-neutral);
|
|
148
|
+
color: var(--rel-action-neutral-label-icons-ghost);
|
|
103
149
|
cursor: pointer;
|
|
104
150
|
display: flex;
|
|
105
151
|
align-items: center;
|
|
@@ -109,11 +155,11 @@ export class RelCarousel extends LitElement {
|
|
|
109
155
|
}
|
|
110
156
|
|
|
111
157
|
.nav-button:hover:not(:disabled) {
|
|
112
|
-
background: var(--rel-
|
|
158
|
+
background: var(--rel-bg-surface-elevated);
|
|
113
159
|
}
|
|
114
160
|
|
|
115
161
|
.nav-button:focus-visible {
|
|
116
|
-
outline: 2px solid var(--rel-
|
|
162
|
+
outline: 2px solid var(--rel-border-focus);
|
|
117
163
|
outline-offset: 2px;
|
|
118
164
|
}
|
|
119
165
|
|
|
@@ -123,11 +169,20 @@ export class RelCarousel extends LitElement {
|
|
|
123
169
|
}
|
|
124
170
|
|
|
125
171
|
.nav-button.prev {
|
|
126
|
-
left:
|
|
172
|
+
left: var(--rel-spacing-sm);
|
|
127
173
|
}
|
|
128
174
|
|
|
129
175
|
.nav-button.next {
|
|
130
|
-
right:
|
|
176
|
+
right: var(--rel-spacing-sm);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* Bottom arrows (Figma Type=Bottom Arrows): inline with the dots row */
|
|
180
|
+
.dots .nav-button {
|
|
181
|
+
position: static;
|
|
182
|
+
transform: none;
|
|
183
|
+
width: 32px;
|
|
184
|
+
height: 32px;
|
|
185
|
+
box-shadow: none;
|
|
131
186
|
}
|
|
132
187
|
|
|
133
188
|
.nav-button svg {
|
|
@@ -138,9 +193,10 @@ export class RelCarousel extends LitElement {
|
|
|
138
193
|
/* Dots indicator */
|
|
139
194
|
.dots {
|
|
140
195
|
display: flex;
|
|
196
|
+
align-items: center;
|
|
141
197
|
justify-content: center;
|
|
142
|
-
gap: var(--rel-spacing-
|
|
143
|
-
margin-top: var(--rel-spacing-
|
|
198
|
+
gap: var(--rel-spacing-xs);
|
|
199
|
+
margin-top: var(--rel-spacing-md);
|
|
144
200
|
}
|
|
145
201
|
|
|
146
202
|
.dot {
|
|
@@ -148,24 +204,24 @@ export class RelCarousel extends LitElement {
|
|
|
148
204
|
height: var(--rel-carousel-dot-size, 8px);
|
|
149
205
|
border-radius: 50%;
|
|
150
206
|
border: none;
|
|
151
|
-
background: var(--rel-
|
|
207
|
+
background: var(--rel-bg-neutral-elevated-2);
|
|
152
208
|
cursor: pointer;
|
|
153
209
|
padding: 0;
|
|
154
210
|
transition: all 0.15s ease;
|
|
155
211
|
}
|
|
156
212
|
|
|
157
213
|
.dot:hover {
|
|
158
|
-
background: var(--rel-
|
|
214
|
+
background: var(--rel-bg-neutral-elevated-2);
|
|
159
215
|
}
|
|
160
216
|
|
|
161
217
|
.dot.active {
|
|
162
|
-
background: var(--rel-
|
|
218
|
+
background: var(--rel-bg-surface-brand);
|
|
163
219
|
width: var(--rel-carousel-dot-size-active, 24px);
|
|
164
|
-
border-radius:
|
|
220
|
+
border-radius: var(--rel-border-radius-xs);
|
|
165
221
|
}
|
|
166
222
|
|
|
167
223
|
.dot:focus-visible {
|
|
168
|
-
outline: 2px solid var(--rel-
|
|
224
|
+
outline: 2px solid var(--rel-border-focus);
|
|
169
225
|
outline-offset: 2px;
|
|
170
226
|
}
|
|
171
227
|
|
|
@@ -178,14 +234,14 @@ export class RelCarousel extends LitElement {
|
|
|
178
234
|
|
|
179
235
|
:host-context([data-theme="dark"]) .nav-button,
|
|
180
236
|
:host-context(.dark) .nav-button {
|
|
181
|
-
background: var(--rel-
|
|
182
|
-
border-color: var(--rel-
|
|
183
|
-
color: var(--rel-
|
|
237
|
+
background: var(--rel-bg-surface-elevated);
|
|
238
|
+
border-color: var(--rel-border-default);
|
|
239
|
+
color: var(--rel-text-default);
|
|
184
240
|
}
|
|
185
241
|
|
|
186
242
|
:host-context([data-theme="dark"]) .nav-button:hover,
|
|
187
243
|
:host-context(.dark) .nav-button:hover {
|
|
188
|
-
background: var(--rel-
|
|
244
|
+
background: var(--rel-bg-neutral-elevated-1);
|
|
189
245
|
}
|
|
190
246
|
`;
|
|
191
247
|
|
|
@@ -203,10 +259,13 @@ export class RelCarousel extends LitElement {
|
|
|
203
259
|
firstUpdated() {
|
|
204
260
|
const ro = new ResizeObserver(() => {
|
|
205
261
|
const w = this.viewport?.offsetWidth ?? 0;
|
|
206
|
-
|
|
262
|
+
const h = this.viewport?.offsetHeight ?? 0;
|
|
263
|
+
if (w === 0 && h === 0) return;
|
|
207
264
|
this.style.setProperty('--rel-carousel-slide-width', `${w}px`);
|
|
265
|
+
this.style.setProperty('--rel-carousel-slide-height', `${h}px`);
|
|
208
266
|
this.renderRoot.querySelectorAll('.carousel-clone').forEach(el => {
|
|
209
|
-
(el as HTMLElement).style.
|
|
267
|
+
if (this.vertical) (el as HTMLElement).style.height = `${h}px`;
|
|
268
|
+
else (el as HTMLElement).style.width = `${w}px`;
|
|
210
269
|
});
|
|
211
270
|
this.updateTransform();
|
|
212
271
|
});
|
|
@@ -215,8 +274,10 @@ export class RelCarousel extends LitElement {
|
|
|
215
274
|
|
|
216
275
|
requestAnimationFrame(() => {
|
|
217
276
|
const w = this.viewport?.offsetWidth ?? 0;
|
|
218
|
-
|
|
277
|
+
const h = this.viewport?.offsetHeight ?? 0;
|
|
278
|
+
if (w > 0 || h > 0) {
|
|
219
279
|
this.style.setProperty('--rel-carousel-slide-width', `${w}px`);
|
|
280
|
+
this.style.setProperty('--rel-carousel-slide-height', `${h}px`);
|
|
220
281
|
this.updateTransform();
|
|
221
282
|
}
|
|
222
283
|
});
|
|
@@ -251,13 +312,18 @@ export class RelCarousel extends LitElement {
|
|
|
251
312
|
if (useClones) {
|
|
252
313
|
this.clonesBefore = 1;
|
|
253
314
|
|
|
315
|
+
const sizeClone = (clone: HTMLElement) => {
|
|
316
|
+
if (this.vertical) clone.style.height = `${this.viewport?.offsetHeight ?? 0}px`;
|
|
317
|
+
else clone.style.width = `${this.viewport?.offsetWidth ?? 0}px`;
|
|
318
|
+
clone.style.boxSizing = 'border-box';
|
|
319
|
+
};
|
|
320
|
+
|
|
254
321
|
// Clone last slide → prepend before <slot>
|
|
255
322
|
const lastEl = elements[this.slideCount - 1] as HTMLElement;
|
|
256
323
|
const lastClone = lastEl.cloneNode(true) as HTMLElement;
|
|
257
324
|
lastClone.classList.add("carousel-clone");
|
|
258
325
|
lastClone.setAttribute("aria-hidden", "true");
|
|
259
|
-
lastClone
|
|
260
|
-
lastClone.style.boxSizing = 'border-box';
|
|
326
|
+
sizeClone(lastClone);
|
|
261
327
|
track.insertBefore(lastClone, slot);
|
|
262
328
|
|
|
263
329
|
// Clone first slide → append after <slot>
|
|
@@ -265,8 +331,7 @@ export class RelCarousel extends LitElement {
|
|
|
265
331
|
const firstClone = firstEl.cloneNode(true) as HTMLElement;
|
|
266
332
|
firstClone.classList.add("carousel-clone");
|
|
267
333
|
firstClone.setAttribute("aria-hidden", "true");
|
|
268
|
-
firstClone
|
|
269
|
-
firstClone.style.boxSizing = 'border-box';
|
|
334
|
+
sizeClone(firstClone);
|
|
270
335
|
track.appendChild(firstClone);
|
|
271
336
|
} else {
|
|
272
337
|
this.clonesBefore = 0;
|
|
@@ -285,10 +350,19 @@ export class RelCarousel extends LitElement {
|
|
|
285
350
|
}
|
|
286
351
|
}
|
|
287
352
|
|
|
353
|
+
private get vertical(): boolean {
|
|
354
|
+
return this.orientation === "vertical";
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** Translate along the orientation axis. */
|
|
358
|
+
private axisTransform(px: number): string {
|
|
359
|
+
return this.vertical ? `translateY(${px}px)` : `translateX(${px}px)`;
|
|
360
|
+
}
|
|
361
|
+
|
|
288
362
|
private unit(): number {
|
|
289
|
-
const
|
|
363
|
+
const slideSize = (this.vertical ? this.viewport?.offsetHeight : this.viewport?.offsetWidth) ?? 0;
|
|
290
364
|
const gapValue = this.gap && this.gap > 0 ? this.gap : 0;
|
|
291
|
-
return
|
|
365
|
+
return slideSize + gapValue;
|
|
292
366
|
}
|
|
293
367
|
|
|
294
368
|
private updateTransform() {
|
|
@@ -299,7 +373,7 @@ export class RelCarousel extends LitElement {
|
|
|
299
373
|
|
|
300
374
|
this.currentTranslate = translate;
|
|
301
375
|
this.prevTranslate = translate;
|
|
302
|
-
this.track.style.transform =
|
|
376
|
+
this.track.style.transform = this.axisTransform(translate);
|
|
303
377
|
this.track.style.gap = this.gap && this.gap > 0 ? `${this.gap}px` : "";
|
|
304
378
|
}
|
|
305
379
|
|
|
@@ -315,7 +389,7 @@ export class RelCarousel extends LitElement {
|
|
|
315
389
|
const translate = 0;
|
|
316
390
|
this.currentTranslate = translate;
|
|
317
391
|
this.prevTranslate = translate;
|
|
318
|
-
this.track!.style.transform =
|
|
392
|
+
this.track!.style.transform = this.axisTransform(translate);
|
|
319
393
|
this.track!.addEventListener(
|
|
320
394
|
"transitionend",
|
|
321
395
|
() => this.silentJump(this.slideCount - 1),
|
|
@@ -337,7 +411,7 @@ export class RelCarousel extends LitElement {
|
|
|
337
411
|
const translate = -(cloneFirstPos * this.unit());
|
|
338
412
|
this.currentTranslate = translate;
|
|
339
413
|
this.prevTranslate = translate;
|
|
340
|
-
this.track!.style.transform =
|
|
414
|
+
this.track!.style.transform = this.axisTransform(translate);
|
|
341
415
|
this.track!.addEventListener(
|
|
342
416
|
"transitionend",
|
|
343
417
|
() => this.silentJump(0),
|
|
@@ -400,7 +474,7 @@ export class RelCarousel extends LitElement {
|
|
|
400
474
|
if (this.disabled || !this.track) return;
|
|
401
475
|
|
|
402
476
|
this.isDragging = true;
|
|
403
|
-
this.dragStartX = e.clientX;
|
|
477
|
+
this.dragStartX = this.vertical ? e.clientY : e.clientX;
|
|
404
478
|
this.prevTranslate = this.currentTranslate;
|
|
405
479
|
|
|
406
480
|
this.track.classList.add("dragging");
|
|
@@ -415,9 +489,9 @@ export class RelCarousel extends LitElement {
|
|
|
415
489
|
private handlePointerMove(e: PointerEvent) {
|
|
416
490
|
if (!this.isDragging || !this.track) return;
|
|
417
491
|
|
|
418
|
-
const
|
|
419
|
-
const
|
|
420
|
-
this.currentTranslate = this.prevTranslate +
|
|
492
|
+
const current = this.vertical ? e.clientY : e.clientX;
|
|
493
|
+
const delta = current - this.dragStartX;
|
|
494
|
+
this.currentTranslate = this.prevTranslate + delta;
|
|
421
495
|
|
|
422
496
|
if (!this.prefersReducedMotion && this.animationId) {
|
|
423
497
|
cancelAnimationFrame(this.animationId);
|
|
@@ -425,7 +499,7 @@ export class RelCarousel extends LitElement {
|
|
|
425
499
|
|
|
426
500
|
this.animationId = requestAnimationFrame(() => {
|
|
427
501
|
if (this.track) {
|
|
428
|
-
this.track.style.transform =
|
|
502
|
+
this.track.style.transform = this.axisTransform(this.currentTranslate);
|
|
429
503
|
}
|
|
430
504
|
});
|
|
431
505
|
}
|
|
@@ -436,14 +510,14 @@ export class RelCarousel extends LitElement {
|
|
|
436
510
|
this.isDragging = false;
|
|
437
511
|
this.track.classList.remove("dragging");
|
|
438
512
|
|
|
439
|
-
const
|
|
440
|
-
const
|
|
441
|
-
const threshold =
|
|
513
|
+
const delta = (this.vertical ? e.clientY : e.clientX) - this.dragStartX;
|
|
514
|
+
const slideSize = this.vertical ? this.viewport.offsetHeight : this.viewport.offsetWidth;
|
|
515
|
+
const threshold = slideSize * 0.2; // 20% threshold
|
|
442
516
|
|
|
443
|
-
if (Math.abs(
|
|
444
|
-
if (
|
|
517
|
+
if (Math.abs(delta) > threshold) {
|
|
518
|
+
if (delta > 0 && (this.value > 0 || this.clonesBefore > 0)) {
|
|
445
519
|
this.goToPrevious();
|
|
446
|
-
} else if (
|
|
520
|
+
} else if (delta < 0 && (this.value < this.slideCount - 1 || this.clonesBefore > 0)) {
|
|
447
521
|
this.goToNext();
|
|
448
522
|
} else {
|
|
449
523
|
this.updateTransform();
|
|
@@ -462,10 +536,12 @@ export class RelCarousel extends LitElement {
|
|
|
462
536
|
|
|
463
537
|
switch (e.key) {
|
|
464
538
|
case "ArrowLeft":
|
|
539
|
+
case "ArrowUp":
|
|
465
540
|
e.preventDefault();
|
|
466
541
|
this.goToPrevious();
|
|
467
542
|
break;
|
|
468
543
|
case "ArrowRight":
|
|
544
|
+
case "ArrowDown":
|
|
469
545
|
e.preventDefault();
|
|
470
546
|
this.goToNext();
|
|
471
547
|
break;
|
|
@@ -509,6 +585,43 @@ export class RelCarousel extends LitElement {
|
|
|
509
585
|
}
|
|
510
586
|
}
|
|
511
587
|
|
|
588
|
+
/** Where nav arrows render, honouring the Figma type when set. */
|
|
589
|
+
private get buttonPlacement(): "side" | "bottom" | "none" {
|
|
590
|
+
if (this.type === "side-arrows") return "side";
|
|
591
|
+
if (this.type === "bottom-arrows") return "bottom";
|
|
592
|
+
if (this.type === "only-indicators" || this.type === "default") return "none";
|
|
593
|
+
return this.showButtons ? "side" : "none";
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
private get dotsVisible(): boolean {
|
|
597
|
+
if (this.type === "default") return false;
|
|
598
|
+
if (this.type) return true;
|
|
599
|
+
return this.showDots;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
private renderNavButton(direction: "prev" | "next", enabled: boolean) {
|
|
603
|
+
const path = direction === "prev" ? "M10 12L6 8L10 4" : "M6 4L10 8L6 12";
|
|
604
|
+
return html`
|
|
605
|
+
<button
|
|
606
|
+
class="nav-button ${direction}"
|
|
607
|
+
part="${direction}-button"
|
|
608
|
+
aria-label="${direction === "prev" ? "Previous" : "Next"} slide"
|
|
609
|
+
?disabled=${!enabled || this.disabled}
|
|
610
|
+
@click=${direction === "prev" ? this.goToPrevious : this.goToNext}
|
|
611
|
+
>
|
|
612
|
+
<svg viewBox="0 0 16 16" fill="none">
|
|
613
|
+
<path
|
|
614
|
+
d="${path}"
|
|
615
|
+
stroke="currentColor"
|
|
616
|
+
stroke-width="2"
|
|
617
|
+
stroke-linecap="round"
|
|
618
|
+
stroke-linejoin="round"
|
|
619
|
+
/>
|
|
620
|
+
</svg>
|
|
621
|
+
</button>
|
|
622
|
+
`;
|
|
623
|
+
}
|
|
624
|
+
|
|
512
625
|
render() {
|
|
513
626
|
const canGoPrev = this.clonesBefore > 0 || this.value > 0;
|
|
514
627
|
const canGoNext = this.clonesBefore > 0 || this.value < this.slideCount - 1;
|
|
@@ -536,58 +649,29 @@ export class RelCarousel extends LitElement {
|
|
|
536
649
|
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
537
650
|
</div>
|
|
538
651
|
|
|
539
|
-
${this.
|
|
652
|
+
${this.buttonPlacement === "side"
|
|
540
653
|
? html`
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
part="prev-button"
|
|
544
|
-
aria-label="Previous slide"
|
|
545
|
-
?disabled=${!canGoPrev || this.disabled}
|
|
546
|
-
@click=${this.goToPrevious}
|
|
547
|
-
>
|
|
548
|
-
<svg viewBox="0 0 16 16" fill="none">
|
|
549
|
-
<path
|
|
550
|
-
d="M10 12L6 8L10 4"
|
|
551
|
-
stroke="currentColor"
|
|
552
|
-
stroke-width="2"
|
|
553
|
-
stroke-linecap="round"
|
|
554
|
-
stroke-linejoin="round"
|
|
555
|
-
/>
|
|
556
|
-
</svg>
|
|
557
|
-
</button>
|
|
558
|
-
|
|
559
|
-
<button
|
|
560
|
-
class="nav-button next"
|
|
561
|
-
part="next-button"
|
|
562
|
-
aria-label="Next slide"
|
|
563
|
-
?disabled=${!canGoNext || this.disabled}
|
|
564
|
-
@click=${this.goToNext}
|
|
565
|
-
>
|
|
566
|
-
<svg viewBox="0 0 16 16" fill="none">
|
|
567
|
-
<path
|
|
568
|
-
d="M6 4L10 8L6 12"
|
|
569
|
-
stroke="currentColor"
|
|
570
|
-
stroke-width="2"
|
|
571
|
-
stroke-linecap="round"
|
|
572
|
-
stroke-linejoin="round"
|
|
573
|
-
/>
|
|
574
|
-
</svg>
|
|
575
|
-
</button>
|
|
654
|
+
${this.renderNavButton("prev", canGoPrev)}
|
|
655
|
+
${this.renderNavButton("next", canGoNext)}
|
|
576
656
|
`
|
|
577
657
|
: nothing}
|
|
578
658
|
</div>
|
|
579
659
|
|
|
580
|
-
${this.
|
|
660
|
+
${(this.dotsVisible || this.buttonPlacement === "bottom") && this.slideCount > 1
|
|
581
661
|
? html`
|
|
582
662
|
<div class="dots" part="dots">
|
|
583
|
-
${
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
663
|
+
${this.buttonPlacement === "bottom" ? this.renderNavButton("prev", canGoPrev) : nothing}
|
|
664
|
+
${this.dotsVisible
|
|
665
|
+
? Array.from({ length: this.slideCount }, (_, i) => html`
|
|
666
|
+
<button
|
|
667
|
+
class="dot ${i === this.value ? "active" : ""}"
|
|
668
|
+
part="dot"
|
|
669
|
+
aria-label="Go to slide ${i + 1}"
|
|
670
|
+
@click=${() => this.goToSlide(i)}
|
|
671
|
+
></button>
|
|
672
|
+
`)
|
|
673
|
+
: nothing}
|
|
674
|
+
${this.buttonPlacement === "bottom" ? this.renderNavButton("next", canGoNext) : nothing}
|
|
591
675
|
</div>
|
|
592
676
|
`
|
|
593
677
|
: nothing}
|
|
@@ -90,12 +90,12 @@ chart.series = [
|
|
|
90
90
|
{
|
|
91
91
|
key: 'desktop',
|
|
92
92
|
label: 'Desktop',
|
|
93
|
-
colorToken: 'var(--rel-
|
|
93
|
+
colorToken: 'var(--rel-bg-info)'
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
96
|
key: 'mobile',
|
|
97
97
|
label: 'Mobile',
|
|
98
|
-
colorToken: 'var(--rel-
|
|
98
|
+
colorToken: 'var(--rel-bg-brand)'
|
|
99
99
|
}
|
|
100
100
|
];
|
|
101
101
|
```
|
|
@@ -223,8 +223,8 @@ Available parts:
|
|
|
223
223
|
];
|
|
224
224
|
|
|
225
225
|
chart.series = [
|
|
226
|
-
{ key: 'desktop', label: 'Desktop', colorToken: 'var(--rel-
|
|
227
|
-
{ key: 'mobile', label: 'Mobile', colorToken: 'var(--rel-
|
|
226
|
+
{ key: 'desktop', label: 'Desktop', colorToken: 'var(--rel-bg-info)' },
|
|
227
|
+
{ key: 'mobile', label: 'Mobile', colorToken: 'var(--rel-bg-brand)' }
|
|
228
228
|
];
|
|
229
229
|
|
|
230
230
|
chart.addEventListener('rel-hover', (e) => {
|
|
@@ -256,7 +256,7 @@ Available parts:
|
|
|
256
256
|
];
|
|
257
257
|
|
|
258
258
|
chart.series = [
|
|
259
|
-
{ key: 'revenue', label: 'Revenue', colorToken: 'var(--rel-
|
|
259
|
+
{ key: 'revenue', label: 'Revenue', colorToken: 'var(--rel-text-success)' }
|
|
260
260
|
];
|
|
261
261
|
</script>
|
|
262
262
|
```
|
|
@@ -274,10 +274,10 @@ Available parts:
|
|
|
274
274
|
The component uses design tokens from the Reliability Design System. All colors, spacing, and typography are inherited from CSS variables.
|
|
275
275
|
|
|
276
276
|
Key tokens used:
|
|
277
|
-
- `--rel-
|
|
277
|
+
- `--rel-bg-*` / `--rel-text-*` semantic colors
|
|
278
278
|
- `--rel-spacing-*` for spacing
|
|
279
|
-
- `--rel-
|
|
280
|
-
- `--rel-
|
|
279
|
+
- `--rel-body-*` composite typography roles
|
|
280
|
+
- `--rel-border-*` / `--rel-border-radius-*` tokens
|
|
281
281
|
- `--rel-shadows-*` for shadows
|
|
282
282
|
- Default series colors use system color tokens
|
|
283
283
|
|