@reliability-design/web 1.3.0 → 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 +161 -159
- 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 +69 -17
- 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 +327 -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 +257 -83
- 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 +73 -23
- 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 +718 -397
- 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 +5 -2
- package/dist/components/rel-topbar/rel-topbar-brand.ts +12 -5
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +14 -8
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +8 -5
- package/dist/components/rel-topbar/rel-topbar-item.ts +27 -22
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +4 -1
- package/dist/components/rel-topbar/rel-topbar-profile.ts +71 -50
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +5 -2
- package/dist/components/rel-topbar/rel-topbar.ts +37 -29
- package/dist/index.d.mts +227 -40
- package/dist/index.d.ts +227 -40
- package/dist/index.js +3930 -2247
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4311 -2629
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +653 -346
- 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-I2PC74XD.css +0 -346
- package/dist/vars-v2-VMGWTFJZ.css +0 -525
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { LitElement, html, css } from "lit";
|
|
2
2
|
import { customElement, property, state } from "lit/decorators.js";
|
|
3
|
-
import "../../styles/vars-v2.css";
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* "continuous"/"discrete" are the legacy tick-mode values; Figma's Type axis
|
|
6
|
+
* adds "default" (alias of continuous) and "range" (dual-thumb interval).
|
|
7
|
+
*/
|
|
8
|
+
export type SliderType = "continuous" | "discrete" | "default" | "range";
|
|
6
9
|
export type TrackStyle = "solid" | "dotted";
|
|
7
10
|
|
|
8
11
|
@customElement("rel-slider")
|
|
9
12
|
export class RelSlider extends LitElement {
|
|
10
|
-
@property({ type: String }) type: SliderType = "continuous";
|
|
13
|
+
@property({ type: String, reflect: true }) type: SliderType = "continuous";
|
|
14
|
+
|
|
15
|
+
/** Figma Size axis (S/M/L): scales track, thumb and ticks. */
|
|
16
|
+
@property({ type: String, reflect: true }) size: "sm" | "md" | "lg" = "md";
|
|
11
17
|
|
|
12
18
|
@property({ type: Number }) min: number = 0;
|
|
13
19
|
|
|
@@ -21,10 +27,13 @@ export class RelSlider extends LitElement {
|
|
|
21
27
|
|
|
22
28
|
@property({ type: Boolean }) showTickLabels: boolean = false;
|
|
23
29
|
|
|
24
|
-
@property({ type: Boolean }) showBubble: boolean = true;
|
|
30
|
+
@property({ type: Boolean }) showBubble: boolean = true;
|
|
25
31
|
|
|
26
32
|
@property({ type: Number }) value: number = 0;
|
|
27
33
|
|
|
34
|
+
/** Upper value when type="range" (attribute value-end). */
|
|
35
|
+
@property({ type: Number, attribute: "value-end" }) valueEnd: number = 100;
|
|
36
|
+
|
|
28
37
|
@state() private ticks: number[] = [];
|
|
29
38
|
|
|
30
39
|
private _onChange: (value: number) => void = () => {};
|
|
@@ -32,18 +41,42 @@ export class RelSlider extends LitElement {
|
|
|
32
41
|
|
|
33
42
|
static styles = css`
|
|
34
43
|
:host {
|
|
35
|
-
--
|
|
36
|
-
--
|
|
44
|
+
color: var(--rel-text-default);
|
|
45
|
+
--track-height: 8px;
|
|
46
|
+
--thumb-size: 20px;
|
|
37
47
|
--thumb-stroke: 7px;
|
|
38
|
-
--thumb-halo-color: var(--rel-
|
|
48
|
+
--thumb-halo-color: var(--rel-border-default);
|
|
39
49
|
--tick-size: 4px;
|
|
40
50
|
--shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
|
|
41
|
-
--halo: 0 2px 0 var(--rel-
|
|
51
|
+
--halo: 0 2px 0 var(--rel-bg-neutral-elevated-1), 0 6px 10px rgba(0, 0, 0, 0.07);
|
|
42
52
|
--marker-width: 24px;
|
|
43
53
|
--marker-height: 28px;
|
|
44
54
|
|
|
45
55
|
display: block;
|
|
46
|
-
font-family: var(--rel-
|
|
56
|
+
font-family: var(--rel-label-md-font-family);
|
|
57
|
+
font-weight: var(--rel-label-md-font-weight);
|
|
58
|
+
font-size: var(--rel-label-md-font-size);
|
|
59
|
+
line-height: var(--rel-label-md-line-height);
|
|
60
|
+
letter-spacing: var(--rel-label-md-letter-spacing);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Figma Size axis: S = 6px track / 16px thumb · M = 8/20 · L = 10/24 */
|
|
64
|
+
:host([size="sm"]) {
|
|
65
|
+
--track-height: 6px;
|
|
66
|
+
--thumb-size: 16px;
|
|
67
|
+
--tick-size: 4px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
:host([size="md"]) {
|
|
71
|
+
--track-height: 8px;
|
|
72
|
+
--thumb-size: 20px;
|
|
73
|
+
--tick-size: 5px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
:host([size="lg"]) {
|
|
77
|
+
--track-height: 10px;
|
|
78
|
+
--thumb-size: 24px;
|
|
79
|
+
--tick-size: 6px;
|
|
47
80
|
}
|
|
48
81
|
|
|
49
82
|
.rel-slider {
|
|
@@ -60,7 +93,7 @@ export class RelSlider extends LitElement {
|
|
|
60
93
|
left: 0;
|
|
61
94
|
width: 100%;
|
|
62
95
|
height: var(--track-height);
|
|
63
|
-
background: var(--rel-
|
|
96
|
+
background: var(--rel-bg-neutral-elevated-3);
|
|
64
97
|
border-radius: 2px;
|
|
65
98
|
transform: translateY(-50%);
|
|
66
99
|
pointer-events: none;
|
|
@@ -71,7 +104,7 @@ export class RelSlider extends LitElement {
|
|
|
71
104
|
top: 50%;
|
|
72
105
|
left: 0;
|
|
73
106
|
height: var(--track-height);
|
|
74
|
-
background: var(--rel-
|
|
107
|
+
background: var(--rel-text-default);
|
|
75
108
|
border-radius: 2px;
|
|
76
109
|
transform: translateY(-50%);
|
|
77
110
|
pointer-events: none;
|
|
@@ -80,9 +113,19 @@ export class RelSlider extends LitElement {
|
|
|
80
113
|
.track-active.dotted {
|
|
81
114
|
background: radial-gradient(
|
|
82
115
|
circle,
|
|
83
|
-
var(--rel-
|
|
116
|
+
var(--rel-text-default) 0 2px,
|
|
84
117
|
transparent 2px
|
|
85
|
-
) 0 50%/
|
|
118
|
+
) 0 50%/var(--rel-spacing-sm) 5px repeat-x;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Range mode: pointer interaction is handled by the container so each
|
|
122
|
+
thumb can be grabbed; the native inputs stay for keyboard/AT. */
|
|
123
|
+
.rel-slider.range .slider-input {
|
|
124
|
+
pointer-events: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.rel-slider.range {
|
|
128
|
+
touch-action: none;
|
|
86
129
|
}
|
|
87
130
|
|
|
88
131
|
/* Input */
|
|
@@ -177,7 +220,14 @@ export class RelSlider extends LitElement {
|
|
|
177
220
|
.value-marker {
|
|
178
221
|
width: var(--marker-width);
|
|
179
222
|
height: var(--marker-height);
|
|
180
|
-
margin-bottom:
|
|
223
|
+
margin-bottom: var(--rel-spacing-3xs);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.value-marker text {
|
|
227
|
+
font-family: var(--rel-label-sm-font-family);
|
|
228
|
+
font-weight: var(--rel-label-sm-font-weight);
|
|
229
|
+
font-size: var(--rel-label-sm-font-size);
|
|
230
|
+
line-height: var(--rel-label-sm-line-height);
|
|
181
231
|
}
|
|
182
232
|
|
|
183
233
|
.value-marker svg {
|
|
@@ -190,13 +240,18 @@ export class RelSlider extends LitElement {
|
|
|
190
240
|
.custom-thumb {
|
|
191
241
|
width: var(--thumb-size);
|
|
192
242
|
height: var(--thumb-size);
|
|
193
|
-
background: var(--rel-
|
|
243
|
+
background: var(--rel-border-strong);
|
|
194
244
|
border-radius: 50%;
|
|
195
245
|
transition: box-shadow 0.15s ease;
|
|
196
246
|
}
|
|
197
247
|
|
|
248
|
+
.slider-input:hover:not(:disabled) ~ .thumb-container .custom-thumb {
|
|
249
|
+
box-shadow: 0 0 0 var(--thumb-stroke) var(--rel-action-overlay-hover),
|
|
250
|
+
var(--shadow), var(--halo);
|
|
251
|
+
}
|
|
252
|
+
|
|
198
253
|
.slider-input:active ~ .thumb-container .custom-thumb {
|
|
199
|
-
box-shadow: 0 0 0 var(--thumb-stroke) var(--
|
|
254
|
+
box-shadow: 0 0 0 var(--thumb-stroke) var(--rel-action-overlay-pressed),
|
|
200
255
|
var(--shadow), var(--halo);
|
|
201
256
|
}
|
|
202
257
|
|
|
@@ -214,7 +269,7 @@ export class RelSlider extends LitElement {
|
|
|
214
269
|
position: absolute;
|
|
215
270
|
width: var(--tick-size);
|
|
216
271
|
height: var(--tick-size);
|
|
217
|
-
background: var(--rel-
|
|
272
|
+
background: var(--rel-text-default);
|
|
218
273
|
border-radius: 50%;
|
|
219
274
|
transform: translate(-50%, -50%);
|
|
220
275
|
transition: background 0.2s;
|
|
@@ -222,18 +277,22 @@ export class RelSlider extends LitElement {
|
|
|
222
277
|
}
|
|
223
278
|
|
|
224
279
|
.tick.active {
|
|
225
|
-
background: var(--rel-
|
|
280
|
+
background: var(--rel-bg-neutral);
|
|
226
281
|
}
|
|
227
282
|
|
|
228
283
|
/* Tick labels */
|
|
229
284
|
.tick-labels {
|
|
230
285
|
position: absolute;
|
|
231
|
-
top: calc(50% + var(--tick-size) +
|
|
286
|
+
top: calc(50% + var(--tick-size) + var(--rel-spacing-2xs));
|
|
232
287
|
left: 0;
|
|
233
288
|
width: 100%;
|
|
234
|
-
|
|
235
|
-
color: var(--rel-color-text-heading);
|
|
289
|
+
color: var(--rel-text-label);
|
|
236
290
|
pointer-events: none;
|
|
291
|
+
font-family: var(--rel-label-xs-font-family);
|
|
292
|
+
font-weight: var(--rel-label-xs-font-weight);
|
|
293
|
+
font-size: var(--rel-label-xs-font-size);
|
|
294
|
+
line-height: var(--rel-label-xs-line-height);
|
|
295
|
+
letter-spacing: var(--rel-label-xs-letter-spacing);
|
|
237
296
|
}
|
|
238
297
|
|
|
239
298
|
.tick-label {
|
|
@@ -243,29 +302,29 @@ export class RelSlider extends LitElement {
|
|
|
243
302
|
|
|
244
303
|
/* Disabled State */
|
|
245
304
|
.rel-slider.disabled .track {
|
|
246
|
-
background: var(--rel-
|
|
305
|
+
background: var(--rel-border-default);
|
|
247
306
|
}
|
|
248
307
|
|
|
249
308
|
.rel-slider.disabled .track-active {
|
|
250
|
-
background: var(--rel-
|
|
309
|
+
background: var(--rel-text-placeholder);
|
|
251
310
|
}
|
|
252
311
|
|
|
253
312
|
.rel-slider.disabled .track-active.dotted {
|
|
254
313
|
background: radial-gradient(
|
|
255
314
|
circle,
|
|
256
|
-
var(--rel-
|
|
315
|
+
var(--rel-bg-neutral-elevated-1) 0 1px,
|
|
257
316
|
transparent 1px
|
|
258
317
|
)
|
|
259
|
-
center/
|
|
260
|
-
var(--rel-
|
|
318
|
+
center/var(--rel-spacing-sm) 4px repeat-x,
|
|
319
|
+
var(--rel-text-placeholder);
|
|
261
320
|
}
|
|
262
321
|
|
|
263
322
|
.rel-slider.disabled .tick {
|
|
264
|
-
background: var(--rel-
|
|
323
|
+
background: var(--rel-text-placeholder);
|
|
265
324
|
}
|
|
266
325
|
|
|
267
326
|
.rel-slider.disabled .tick-label {
|
|
268
|
-
color: var(--rel-
|
|
327
|
+
color: var(--rel-text-placeholder);
|
|
269
328
|
}
|
|
270
329
|
|
|
271
330
|
.rel-slider.disabled .slider-input {
|
|
@@ -273,7 +332,7 @@ export class RelSlider extends LitElement {
|
|
|
273
332
|
}
|
|
274
333
|
|
|
275
334
|
.rel-slider.disabled .custom-thumb {
|
|
276
|
-
background: var(--rel-
|
|
335
|
+
background: var(--rel-text-placeholder);
|
|
277
336
|
box-shadow: none;
|
|
278
337
|
}
|
|
279
338
|
|
|
@@ -283,26 +342,17 @@ export class RelSlider extends LitElement {
|
|
|
283
342
|
}
|
|
284
343
|
|
|
285
344
|
.rel-slider.disabled .value-marker svg path {
|
|
286
|
-
fill: var(--rel-
|
|
345
|
+
fill: var(--rel-text-placeholder);
|
|
287
346
|
}
|
|
288
347
|
|
|
289
348
|
/* Dark mode overrides */
|
|
290
349
|
:host-context([data-theme="dark"]),
|
|
291
350
|
:host-context(.dark) {
|
|
292
|
-
--thumb-halo-color: var(--rel-
|
|
293
|
-
--halo: 0 2px 0 var(--rel-
|
|
351
|
+
--thumb-halo-color: var(--rel-border-default);
|
|
352
|
+
--halo: 0 2px 0 var(--rel-bg-neutral-elevated-2),
|
|
294
353
|
0 6px 10px rgba(0, 0, 0, 0.3);
|
|
295
354
|
}
|
|
296
355
|
|
|
297
|
-
:host-context([data-theme="dark"]) .value-marker svg path,
|
|
298
|
-
:host-context(.dark) .value-marker svg path {
|
|
299
|
-
fill: #2B2B2B;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
:host-context([data-theme="dark"]) .value-marker text,
|
|
303
|
-
:host-context(.dark) .value-marker text {
|
|
304
|
-
fill: #FFFFFF;
|
|
305
|
-
}
|
|
306
356
|
`;
|
|
307
357
|
|
|
308
358
|
connectedCallback() {
|
|
@@ -319,16 +369,94 @@ export class RelSlider extends LitElement {
|
|
|
319
369
|
) {
|
|
320
370
|
this.setupTicks();
|
|
321
371
|
}
|
|
322
|
-
if (
|
|
372
|
+
if (
|
|
373
|
+
changedProperties.has("value") ||
|
|
374
|
+
changedProperties.has("valueEnd") ||
|
|
375
|
+
changedProperties.has("type")
|
|
376
|
+
) {
|
|
323
377
|
this.updateActiveWidth();
|
|
324
378
|
}
|
|
325
379
|
}
|
|
326
380
|
|
|
381
|
+
private get isRange(): boolean {
|
|
382
|
+
return this.type === "range";
|
|
383
|
+
}
|
|
384
|
+
|
|
327
385
|
private get percentage(): number {
|
|
328
386
|
if (this.max === this.min) return 0;
|
|
329
387
|
return ((this.value - this.min) / (this.max - this.min)) * 100;
|
|
330
388
|
}
|
|
331
389
|
|
|
390
|
+
private get percentageEnd(): number {
|
|
391
|
+
if (this.max === this.min) return 0;
|
|
392
|
+
return ((this.valueEnd - this.min) / (this.max - this.min)) * 100;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private dragThumb: "start" | "end" | null = null;
|
|
396
|
+
|
|
397
|
+
private valueFromPointer(e: PointerEvent): number {
|
|
398
|
+
const el = this.shadowRoot?.querySelector(".rel-slider") as HTMLElement;
|
|
399
|
+
if (!el) return this.min;
|
|
400
|
+
const rect = el.getBoundingClientRect();
|
|
401
|
+
const pct = Math.min(1, Math.max(0, (e.clientX - rect.left) / rect.width));
|
|
402
|
+
let v = this.min + pct * (this.max - this.min);
|
|
403
|
+
v = Math.round(v / this.step) * this.step;
|
|
404
|
+
return Math.min(this.max, Math.max(this.min, v));
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
private onRangePointerDown(e: PointerEvent) {
|
|
408
|
+
if (!this.isRange || this.disabled) return;
|
|
409
|
+
const v = this.valueFromPointer(e);
|
|
410
|
+
this.dragThumb =
|
|
411
|
+
Math.abs(v - this.value) <= Math.abs(v - this.valueEnd) ? "start" : "end";
|
|
412
|
+
(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
|
|
413
|
+
this.applyRangeValue(v);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
private onRangePointerMove(e: PointerEvent) {
|
|
417
|
+
if (!this.dragThumb) return;
|
|
418
|
+
this.applyRangeValue(this.valueFromPointer(e));
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private onRangePointerUp() {
|
|
422
|
+
this.dragThumb = null;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
private applyRangeValue(v: number) {
|
|
426
|
+
if (this.dragThumb === "start") {
|
|
427
|
+
this.value = Math.min(v, this.valueEnd);
|
|
428
|
+
} else if (this.dragThumb === "end") {
|
|
429
|
+
this.valueEnd = Math.max(v, this.value);
|
|
430
|
+
}
|
|
431
|
+
this.updateActiveWidth();
|
|
432
|
+
this.emitRangeChange();
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
private emitRangeChange() {
|
|
436
|
+
this.dispatchEvent(
|
|
437
|
+
new CustomEvent("rel-change", {
|
|
438
|
+
detail: { value: this.value, valueEnd: this.valueEnd },
|
|
439
|
+
bubbles: true,
|
|
440
|
+
composed: true,
|
|
441
|
+
})
|
|
442
|
+
);
|
|
443
|
+
this._onChange(this.value);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
private onRangeInputStart(ev: Event) {
|
|
447
|
+
const next = Number((ev.target as HTMLInputElement).value);
|
|
448
|
+
this.value = Math.min(next, this.valueEnd);
|
|
449
|
+
this.updateActiveWidth();
|
|
450
|
+
this.emitRangeChange();
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
private onRangeInputEnd(ev: Event) {
|
|
454
|
+
const next = Number((ev.target as HTMLInputElement).value);
|
|
455
|
+
this.valueEnd = Math.max(next, this.value);
|
|
456
|
+
this.updateActiveWidth();
|
|
457
|
+
this.emitRangeChange();
|
|
458
|
+
}
|
|
459
|
+
|
|
332
460
|
private setupTicks() {
|
|
333
461
|
if (this.type !== "discrete") {
|
|
334
462
|
this.ticks = [];
|
|
@@ -384,40 +512,43 @@ export class RelSlider extends LitElement {
|
|
|
384
512
|
|
|
385
513
|
private updateActiveWidth() {
|
|
386
514
|
const activeEl = this.shadowRoot?.querySelector(".track-active") as HTMLDivElement;
|
|
387
|
-
if (activeEl)
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
515
|
+
if (!activeEl) return;
|
|
516
|
+
|
|
517
|
+
if (this.isRange) {
|
|
518
|
+
activeEl.style.left = `${this.percentage}%`;
|
|
519
|
+
activeEl.style.width = `${Math.max(0, this.percentageEnd - this.percentage)}%`;
|
|
520
|
+
} else if (this.type === "discrete") {
|
|
521
|
+
const stepPercent = (this.step / (this.max - this.min)) * 100;
|
|
522
|
+
const snappedPct = Math.round(this.percentage / stepPercent) * stepPercent;
|
|
523
|
+
activeEl.style.width = `${snappedPct}%`;
|
|
524
|
+
} else {
|
|
525
|
+
activeEl.style.width = `${this.percentage}%`;
|
|
395
526
|
}
|
|
396
527
|
}
|
|
397
528
|
|
|
398
|
-
private renderThumbContainer() {
|
|
529
|
+
private renderThumbContainer(pct: number = this.percentage, val: number = this.value) {
|
|
399
530
|
return html`
|
|
400
|
-
<div class="thumb-container" style="left: ${
|
|
531
|
+
<div class="thumb-container" style="left: ${pct}%">
|
|
401
532
|
${this.showBubble ? html`
|
|
402
533
|
<div class="value-marker">
|
|
403
534
|
<svg viewBox="0 0 24 32" xmlns="http://www.w3.org/2000/svg">
|
|
404
535
|
<path
|
|
405
536
|
d="M12 0C18.6274 0 24 5.37258 24 12C24 21 12 32 12 32C12 32 0 21 0 12C0 5.37258 5.37258 0 12 0Z"
|
|
406
|
-
fill="var(--rel-
|
|
537
|
+
fill="var(--rel-bg-neutral-inverse-2)" />
|
|
407
538
|
<text
|
|
408
539
|
x="12"
|
|
409
540
|
y="16"
|
|
410
541
|
text-anchor="middle"
|
|
411
|
-
fill="var(--rel-
|
|
542
|
+
fill="var(--rel-text-inverse)"
|
|
412
543
|
font-size="12"
|
|
413
544
|
font-family="Poppins"
|
|
414
545
|
font-weight="600">
|
|
415
|
-
${
|
|
546
|
+
${val}
|
|
416
547
|
</text>
|
|
417
548
|
</svg>
|
|
418
549
|
</div>
|
|
419
550
|
` : ""}
|
|
420
|
-
<div class="custom-thumb"></div>
|
|
551
|
+
<div part="thumb" class="custom-thumb"></div>
|
|
421
552
|
</div>
|
|
422
553
|
`;
|
|
423
554
|
}
|
|
@@ -461,6 +592,7 @@ export class RelSlider extends LitElement {
|
|
|
461
592
|
"rel-slider",
|
|
462
593
|
this.disabled ? "disabled" : "",
|
|
463
594
|
this.type === "discrete" ? "has-ticks" : "",
|
|
595
|
+
this.isRange ? "range" : "",
|
|
464
596
|
]
|
|
465
597
|
.filter(Boolean)
|
|
466
598
|
.join(" ");
|
|
@@ -472,9 +604,50 @@ export class RelSlider extends LitElement {
|
|
|
472
604
|
.filter(Boolean)
|
|
473
605
|
.join(" ");
|
|
474
606
|
|
|
607
|
+
if (this.isRange) {
|
|
608
|
+
return html`
|
|
609
|
+
<div
|
|
610
|
+
class="${sliderClasses}"
|
|
611
|
+
@pointerdown="${this.onRangePointerDown}"
|
|
612
|
+
@pointermove="${this.onRangePointerMove}"
|
|
613
|
+
@pointerup="${this.onRangePointerUp}"
|
|
614
|
+
@pointercancel="${this.onRangePointerUp}"
|
|
615
|
+
>
|
|
616
|
+
<div part="track" class="track"></div>
|
|
617
|
+
<div class="${trackActiveClasses}"></div>
|
|
618
|
+
|
|
619
|
+
<input
|
|
620
|
+
class="slider-input"
|
|
621
|
+
type="range"
|
|
622
|
+
aria-label="Range start"
|
|
623
|
+
.min="${String(this.min)}"
|
|
624
|
+
.max="${String(this.max)}"
|
|
625
|
+
.step="${String(this.step)}"
|
|
626
|
+
.value="${String(this.value)}"
|
|
627
|
+
?disabled="${this.disabled}"
|
|
628
|
+
@input="${this.onRangeInputStart}"
|
|
629
|
+
@blur="${() => this._onTouched()}" />
|
|
630
|
+
<input
|
|
631
|
+
class="slider-input"
|
|
632
|
+
type="range"
|
|
633
|
+
aria-label="Range end"
|
|
634
|
+
.min="${String(this.min)}"
|
|
635
|
+
.max="${String(this.max)}"
|
|
636
|
+
.step="${String(this.step)}"
|
|
637
|
+
.value="${String(this.valueEnd)}"
|
|
638
|
+
?disabled="${this.disabled}"
|
|
639
|
+
@input="${this.onRangeInputEnd}"
|
|
640
|
+
@blur="${() => this._onTouched()}" />
|
|
641
|
+
|
|
642
|
+
${this.renderThumbContainer(this.percentage, this.value)}
|
|
643
|
+
${this.renderThumbContainer(this.percentageEnd, this.valueEnd)}
|
|
644
|
+
</div>
|
|
645
|
+
`;
|
|
646
|
+
}
|
|
647
|
+
|
|
475
648
|
return html`
|
|
476
649
|
<div class="${sliderClasses}">
|
|
477
|
-
<div class="track"></div>
|
|
650
|
+
<div part="track" class="track"></div>
|
|
478
651
|
<div class="${trackActiveClasses}"></div>
|
|
479
652
|
|
|
480
653
|
<input
|
|
@@ -87,24 +87,24 @@ None exposed.
|
|
|
87
87
|
## Tokens / CSS Variables
|
|
88
88
|
|
|
89
89
|
### Semantic Tokens
|
|
90
|
-
- `--rel-
|
|
91
|
-
- `--rel-
|
|
92
|
-
- `--rel-
|
|
93
|
-
- `--rel-
|
|
90
|
+
- `--rel-fonts-font-family` - Font family
|
|
91
|
+
- `--rel-body-sm-regular-font-size` - Font size
|
|
92
|
+
- `--rel-fonts-weight-body-semibold` - Action button font weight
|
|
93
|
+
- `--rel-body-md-regular-line-height` - Message line height
|
|
94
94
|
|
|
95
95
|
### Spacing Tokens
|
|
96
|
-
- `--rel-spacing-
|
|
96
|
+
- `--rel-spacing-2xs` - Action button gap, close button padding
|
|
97
97
|
|
|
98
98
|
### Color Tokens
|
|
99
|
-
- `--rel-
|
|
100
|
-
- `--rel-
|
|
101
|
-
- `--rel-
|
|
99
|
+
- `--rel-text-default` - Background color
|
|
100
|
+
- `--rel-bg-surface` - Text and focus outline color
|
|
101
|
+
- `--rel-bg-success-light` - Action button text color
|
|
102
102
|
|
|
103
103
|
### Shadow Tokens
|
|
104
104
|
- `--rel-shadows-shadow-300` - Drop shadow
|
|
105
105
|
|
|
106
106
|
### Border Tokens
|
|
107
|
-
- `--rel-
|
|
107
|
+
- `--rel-border-radius-sm` - Border radius
|
|
108
108
|
|
|
109
109
|
## Accessibility
|
|
110
110
|
- Snackbars are informational and do not interrupt workflows
|