@antadesign/anta 0.3.16 → 0.3.17
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/README.md +10 -9
- package/dist/anta_helpers.d.ts +7 -12
- package/dist/anta_helpers.js +11 -3
- package/dist/components/ButtonCopy.d.ts +9 -6
- package/dist/components/ButtonCopy.js +5 -3
- package/dist/components/InputTime.d.ts +5 -4
- package/dist/components/Slider.d.ts +89 -0
- package/dist/components/Slider.js +144 -0
- package/dist/components/copy-props.d.ts +2 -0
- package/dist/components/copy-props.js +2 -1
- package/dist/elements/a-copy.d.ts +1 -1
- package/dist/elements/a-copy.js +103 -109
- package/dist/elements/a-input-time.css +1 -1
- package/dist/elements/a-input-time.js +297 -377
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +0 -3
- package/dist/elements/a-input.js +13 -45
- package/dist/elements/a-slider.css +1 -0
- package/dist/elements/a-slider.d.ts +24 -0
- package/dist/elements/a-slider.js +479 -0
- package/dist/elements/copy-behavior.d.ts +3 -3
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/index.js +3 -0
- package/dist/general_types.d.ts +57 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/jsx-runtime.d.ts +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
import { HTMLElementBase } from "../anta_helpers";
|
|
2
|
+
import "./a-slider.css";
|
|
3
|
+
const finiteNumber = (value, fallback) => {
|
|
4
|
+
if (value == null || value === "") return fallback;
|
|
5
|
+
const number = Number(value);
|
|
6
|
+
return Number.isFinite(number) ? number : fallback;
|
|
7
|
+
};
|
|
8
|
+
const precisionOf = (value) => {
|
|
9
|
+
const exponent = value.toString().match(/(?:\.(\d+))?(?:e([+-]?\d+))?$/i);
|
|
10
|
+
return Math.max(0, (exponent?.[1]?.length ?? 0) - Number(exponent?.[2] ?? 0));
|
|
11
|
+
};
|
|
12
|
+
class ASliderElement extends HTMLElementBase {
|
|
13
|
+
static formAssociated = true;
|
|
14
|
+
static observedAttributes = [
|
|
15
|
+
"value",
|
|
16
|
+
"defaultvalue",
|
|
17
|
+
"min",
|
|
18
|
+
"max",
|
|
19
|
+
"step",
|
|
20
|
+
"disabled",
|
|
21
|
+
"track-click",
|
|
22
|
+
"value-display",
|
|
23
|
+
"value-prefix",
|
|
24
|
+
"value-suffix"
|
|
25
|
+
];
|
|
26
|
+
#internals;
|
|
27
|
+
#control;
|
|
28
|
+
#railArea;
|
|
29
|
+
#fill;
|
|
30
|
+
#thumb;
|
|
31
|
+
#header;
|
|
32
|
+
#label;
|
|
33
|
+
#inlineValue;
|
|
34
|
+
#inlineValuePrefix;
|
|
35
|
+
#inlineValueSuffix;
|
|
36
|
+
#endValue;
|
|
37
|
+
#endValuePrefix;
|
|
38
|
+
#endValueSuffix;
|
|
39
|
+
#thumbValue;
|
|
40
|
+
#thumbValuePrefix;
|
|
41
|
+
#thumbValueSuffix;
|
|
42
|
+
#markers;
|
|
43
|
+
#extras;
|
|
44
|
+
#value = 0;
|
|
45
|
+
#seeded = false;
|
|
46
|
+
#dirty = false;
|
|
47
|
+
#drag;
|
|
48
|
+
get value() {
|
|
49
|
+
return this.#value;
|
|
50
|
+
}
|
|
51
|
+
set value(value) {
|
|
52
|
+
this.setAttribute("value", String(value));
|
|
53
|
+
}
|
|
54
|
+
get defaultValue() {
|
|
55
|
+
return finiteNumber(this.getAttribute("defaultvalue"), this.#min);
|
|
56
|
+
}
|
|
57
|
+
set defaultValue(value) {
|
|
58
|
+
this.setAttribute("defaultvalue", String(value));
|
|
59
|
+
}
|
|
60
|
+
constructor() {
|
|
61
|
+
super();
|
|
62
|
+
this.#internals = this.attachInternals?.();
|
|
63
|
+
const shadow = this.attachShadow({ mode: "open" });
|
|
64
|
+
const style = document.createElement("style");
|
|
65
|
+
style.textContent = `
|
|
66
|
+
:host {
|
|
67
|
+
display: grid;
|
|
68
|
+
grid-template-columns: minmax(0, 1fr);
|
|
69
|
+
gap: 1px;
|
|
70
|
+
outline: none;
|
|
71
|
+
}
|
|
72
|
+
[hidden] { display: none !important; }
|
|
73
|
+
.header {
|
|
74
|
+
display: flex;
|
|
75
|
+
align-items: baseline;
|
|
76
|
+
gap: 1px;
|
|
77
|
+
min-width: 0;
|
|
78
|
+
}
|
|
79
|
+
slot[name="label"] {
|
|
80
|
+
display: block;
|
|
81
|
+
min-width: 0;
|
|
82
|
+
color: var(--slider-label);
|
|
83
|
+
font-family: var(--sans-serif);
|
|
84
|
+
font-size: var(--slider-label-size);
|
|
85
|
+
font-weight: 500;
|
|
86
|
+
line-height: var(--slider-label-line-height);
|
|
87
|
+
}
|
|
88
|
+
.inline-value,
|
|
89
|
+
.end-value {
|
|
90
|
+
color: var(--slider-value);
|
|
91
|
+
font-family: var(--sans-serif);
|
|
92
|
+
font-feature-settings: 'ss02', 'ss05', 'tnum';
|
|
93
|
+
font-size: var(--slider-value-size);
|
|
94
|
+
font-variant-numeric: tabular-nums;
|
|
95
|
+
line-height: var(--slider-value-line-height);
|
|
96
|
+
}
|
|
97
|
+
.value-affix { color: var(--slider-value-affix); }
|
|
98
|
+
.inline-separator,
|
|
99
|
+
.inline-value { display: none; }
|
|
100
|
+
.inline-value { margin-inline-start: 0.5ch; }
|
|
101
|
+
.end-value {
|
|
102
|
+
display: block;
|
|
103
|
+
flex: 0 0 auto;
|
|
104
|
+
margin-inline-start: auto;
|
|
105
|
+
padding-inline-start: 1ch;
|
|
106
|
+
}
|
|
107
|
+
:host([value-display="inline"]) .inline-separator,
|
|
108
|
+
:host([value-display="inline"]) .inline-value { display: block; }
|
|
109
|
+
:host([value-display="inline"]) .end-value,
|
|
110
|
+
:host([value-display="thumb"]) .end-value,
|
|
111
|
+
:host([value-display="none"]) .end-value { display: none; }
|
|
112
|
+
.control {
|
|
113
|
+
position: relative;
|
|
114
|
+
block-size: var(--anta-slider-control-size);
|
|
115
|
+
border-radius: 4px;
|
|
116
|
+
cursor: grab;
|
|
117
|
+
touch-action: none;
|
|
118
|
+
user-select: none;
|
|
119
|
+
}
|
|
120
|
+
:host([track-click="jump"]) .control { cursor: pointer; }
|
|
121
|
+
.control[data-dragging] { cursor: grabbing; }
|
|
122
|
+
.control[data-dragging] .thumb { background: var(--slider-thumb-active); }
|
|
123
|
+
:host(:focus-visible) .control:not([data-pointer-focus]) {
|
|
124
|
+
outline: 1px solid var(--focus-ring);
|
|
125
|
+
outline-offset: 0;
|
|
126
|
+
}
|
|
127
|
+
.rail-area {
|
|
128
|
+
position: absolute;
|
|
129
|
+
inset-block-start: 50%;
|
|
130
|
+
inset-inline: calc(var(--anta-slider-thumb-size) / 2);
|
|
131
|
+
block-size: var(--anta-slider-track-size);
|
|
132
|
+
transform: translateY(-50%);
|
|
133
|
+
}
|
|
134
|
+
.rail,
|
|
135
|
+
.fill {
|
|
136
|
+
position: absolute;
|
|
137
|
+
inset: 0;
|
|
138
|
+
border-radius: var(--slider-track-radius);
|
|
139
|
+
transition: background-color 75ms ease-out;
|
|
140
|
+
}
|
|
141
|
+
.rail {
|
|
142
|
+
inset-inline: calc(var(--slider-track-inset) - var(--anta-slider-thumb-size) / 2);
|
|
143
|
+
background: var(--slider-track);
|
|
144
|
+
}
|
|
145
|
+
.fill {
|
|
146
|
+
inset-inline-start: calc(var(--slider-track-inset) - var(--anta-slider-thumb-size) / 2);
|
|
147
|
+
inset-inline-end: auto;
|
|
148
|
+
inline-size: calc(var(--_percent, 0%) + var(--anta-slider-thumb-size) / 2 - var(--slider-track-inset));
|
|
149
|
+
background: var(--slider-fill);
|
|
150
|
+
}
|
|
151
|
+
.thumb {
|
|
152
|
+
position: absolute;
|
|
153
|
+
inset-block-start: 50%;
|
|
154
|
+
inset-inline-start: var(--_percent, 0%);
|
|
155
|
+
box-sizing: border-box;
|
|
156
|
+
inline-size: var(--anta-slider-thumb-size);
|
|
157
|
+
block-size: var(--anta-slider-thumb-size);
|
|
158
|
+
border: var(--anta-slider-thumb-border-width) solid var(--slider-thumb-border);
|
|
159
|
+
border-radius: var(--slider-thumb-radius);
|
|
160
|
+
background: var(--slider-thumb);
|
|
161
|
+
transition: background-color 75ms ease-out, border-color 75ms ease-out;
|
|
162
|
+
transform: translate(-50%, -50%);
|
|
163
|
+
}
|
|
164
|
+
.thumb-value {
|
|
165
|
+
display: none;
|
|
166
|
+
position: absolute;
|
|
167
|
+
inset-inline-start: var(--_percent, 0%);
|
|
168
|
+
inset-block-start: 50%;
|
|
169
|
+
min-inline-size: max-content;
|
|
170
|
+
color: var(--slider-value);
|
|
171
|
+
font-family: var(--sans-serif);
|
|
172
|
+
font-feature-settings: 'ss02', 'ss05', 'tnum';
|
|
173
|
+
font-size: var(--slider-value-size);
|
|
174
|
+
font-variant-numeric: tabular-nums;
|
|
175
|
+
line-height: var(--slider-value-line-height);
|
|
176
|
+
padding-inline: 6px;
|
|
177
|
+
background: var(--bg-2);
|
|
178
|
+
border: 1px solid var(--border-3);
|
|
179
|
+
border-radius: 4px;
|
|
180
|
+
text-align: center;
|
|
181
|
+
transform: translate(-50%, calc(
|
|
182
|
+
-50% - var(--anta-slider-control-size) / 2 - 1px - var(--slider-value-line-height) / 2
|
|
183
|
+
));
|
|
184
|
+
}
|
|
185
|
+
:host([value-display="thumb"]) .thumb-value { display: block; }
|
|
186
|
+
slot[name="markers"] {
|
|
187
|
+
display: block;
|
|
188
|
+
position: relative;
|
|
189
|
+
min-block-size: var(--slider-marker-line-height);
|
|
190
|
+
}
|
|
191
|
+
slot[name="markers"]::slotted(*) {
|
|
192
|
+
position: absolute;
|
|
193
|
+
inset-inline-start: var(--slider-marker-position);
|
|
194
|
+
max-inline-size: min(12rem, 50vw);
|
|
195
|
+
color: var(--slider-marker);
|
|
196
|
+
font-family: var(--sans-serif);
|
|
197
|
+
font-feature-settings: 'ss02', 'ss05', 'tnum';
|
|
198
|
+
font-size: var(--slider-marker-size);
|
|
199
|
+
font-variant-numeric: tabular-nums;
|
|
200
|
+
line-height: var(--slider-marker-line-height);
|
|
201
|
+
text-align: center;
|
|
202
|
+
transform: translateX(-50%);
|
|
203
|
+
white-space: nowrap;
|
|
204
|
+
}
|
|
205
|
+
slot[name="markers"]::slotted([data-slider-marker-start]) { text-align: start; transform: translateX(0); }
|
|
206
|
+
slot[name="markers"]::slotted([data-slider-marker-end]) { text-align: end; transform: translateX(-100%); }
|
|
207
|
+
slot:not([name]) { display: block; }
|
|
208
|
+
:host([disabled]) .control,
|
|
209
|
+
:host(:disabled) .control { cursor: not-allowed; }
|
|
210
|
+
@media (forced-colors: active) {
|
|
211
|
+
.rail { background: Canvas; border: 1px solid CanvasText; }
|
|
212
|
+
.fill { background: Highlight; }
|
|
213
|
+
.thumb { background: Canvas; border-color: CanvasText; }
|
|
214
|
+
:host(:focus-visible) .control { outline: 2px solid Highlight; }
|
|
215
|
+
}
|
|
216
|
+
@media (prefers-reduced-motion: reduce) {
|
|
217
|
+
.rail,
|
|
218
|
+
.fill,
|
|
219
|
+
.thumb { transition: none; }
|
|
220
|
+
}
|
|
221
|
+
`;
|
|
222
|
+
this.#header = document.createElement("div");
|
|
223
|
+
this.#header.className = "header";
|
|
224
|
+
this.#header.part.add("header");
|
|
225
|
+
this.#label = document.createElement("slot");
|
|
226
|
+
this.#label.name = "label";
|
|
227
|
+
this.#label.part.add("label");
|
|
228
|
+
const separator = document.createElement("span");
|
|
229
|
+
separator.className = "inline-separator";
|
|
230
|
+
separator.textContent = ":";
|
|
231
|
+
this.#inlineValue = document.createElement("span");
|
|
232
|
+
this.#inlineValue.className = "inline-value";
|
|
233
|
+
this.#inlineValue.part.add("value");
|
|
234
|
+
this.#inlineValuePrefix = document.createElement("span");
|
|
235
|
+
this.#inlineValuePrefix.className = "value-affix";
|
|
236
|
+
this.#inlineValueSuffix = document.createElement("span");
|
|
237
|
+
this.#inlineValueSuffix.className = "value-affix";
|
|
238
|
+
this.#inlineValue.append(this.#inlineValuePrefix, this.#inlineValueSuffix);
|
|
239
|
+
this.#endValue = document.createElement("span");
|
|
240
|
+
this.#endValue.className = "end-value";
|
|
241
|
+
this.#endValue.part.add("value");
|
|
242
|
+
this.#endValuePrefix = document.createElement("span");
|
|
243
|
+
this.#endValuePrefix.className = "value-affix";
|
|
244
|
+
this.#endValueSuffix = document.createElement("span");
|
|
245
|
+
this.#endValueSuffix.className = "value-affix";
|
|
246
|
+
this.#endValue.append(this.#endValuePrefix, this.#endValueSuffix);
|
|
247
|
+
this.#header.append(this.#label, separator, this.#inlineValue, this.#endValue);
|
|
248
|
+
this.#control = document.createElement("div");
|
|
249
|
+
this.#control.className = "control";
|
|
250
|
+
this.#control.part.add("control");
|
|
251
|
+
this.#railArea = document.createElement("div");
|
|
252
|
+
this.#railArea.className = "rail-area";
|
|
253
|
+
const rail = document.createElement("div");
|
|
254
|
+
rail.className = "rail";
|
|
255
|
+
rail.part.add("track");
|
|
256
|
+
this.#fill = document.createElement("div");
|
|
257
|
+
this.#fill.className = "fill";
|
|
258
|
+
this.#fill.part.add("fill");
|
|
259
|
+
this.#thumb = document.createElement("div");
|
|
260
|
+
this.#thumb.className = "thumb";
|
|
261
|
+
this.#thumb.part.add("thumb");
|
|
262
|
+
this.#thumbValue = document.createElement("span");
|
|
263
|
+
this.#thumbValue.className = "thumb-value";
|
|
264
|
+
this.#thumbValue.part.add("thumb-value");
|
|
265
|
+
this.#thumbValuePrefix = document.createElement("span");
|
|
266
|
+
this.#thumbValuePrefix.className = "value-affix";
|
|
267
|
+
this.#thumbValueSuffix = document.createElement("span");
|
|
268
|
+
this.#thumbValueSuffix.className = "value-affix";
|
|
269
|
+
this.#thumbValue.append(this.#thumbValuePrefix, this.#thumbValueSuffix);
|
|
270
|
+
this.#railArea.append(rail, this.#fill, this.#thumb, this.#thumbValue);
|
|
271
|
+
this.#control.append(this.#railArea);
|
|
272
|
+
this.#markers = document.createElement("slot");
|
|
273
|
+
this.#markers.name = "markers";
|
|
274
|
+
this.#markers.part.add("markers");
|
|
275
|
+
this.#extras = document.createElement("slot");
|
|
276
|
+
this.#extras.part.add("extras");
|
|
277
|
+
for (const slot of [this.#label, this.#markers, this.#extras]) {
|
|
278
|
+
slot.addEventListener("slotchange", () => this.#syncSlotVisibility());
|
|
279
|
+
}
|
|
280
|
+
this.#control.addEventListener("pointerdown", (event) => this.#beginDrag(event));
|
|
281
|
+
this.#control.addEventListener("pointermove", (event) => this.#moveDrag(event));
|
|
282
|
+
this.#control.addEventListener("pointerup", (event) => this.#finishDrag(event));
|
|
283
|
+
this.#control.addEventListener("pointercancel", (event) => this.#finishDrag(event));
|
|
284
|
+
this.addEventListener("keydown", (event) => this.#handleKeydown(event));
|
|
285
|
+
this.addEventListener("blur", () => delete this.#control.dataset.pointerFocus);
|
|
286
|
+
shadow.append(style, this.#header, this.#control, this.#markers, this.#extras);
|
|
287
|
+
}
|
|
288
|
+
connectedCallback() {
|
|
289
|
+
if (!this.#seeded) {
|
|
290
|
+
this.#value = this.#initialValue();
|
|
291
|
+
this.#seeded = true;
|
|
292
|
+
}
|
|
293
|
+
this.#paint();
|
|
294
|
+
this.#syncSlotVisibility();
|
|
295
|
+
}
|
|
296
|
+
attributeChangedCallback(name) {
|
|
297
|
+
if (!this.#seeded) return;
|
|
298
|
+
if (name === "value") {
|
|
299
|
+
if (this.hasAttribute("value")) {
|
|
300
|
+
this.#value = this.#normalize(finiteNumber(this.getAttribute("value"), this.#min));
|
|
301
|
+
this.#dirty = false;
|
|
302
|
+
} else if (!this.#dirty) {
|
|
303
|
+
this.#value = this.#initialValue();
|
|
304
|
+
}
|
|
305
|
+
} else if (name === "defaultvalue" && !this.hasAttribute("value") && !this.#dirty) {
|
|
306
|
+
this.#value = this.#initialValue();
|
|
307
|
+
} else if (name === "min" || name === "max" || name === "step") {
|
|
308
|
+
this.#value = this.#normalize(this.#value);
|
|
309
|
+
}
|
|
310
|
+
this.#paint();
|
|
311
|
+
if (name === "value-display") this.#syncSlotVisibility();
|
|
312
|
+
}
|
|
313
|
+
formResetCallback() {
|
|
314
|
+
const previous = this.#value;
|
|
315
|
+
this.#value = this.#normalize(finiteNumber(this.getAttribute("defaultvalue"), this.#min));
|
|
316
|
+
this.#dirty = false;
|
|
317
|
+
this.#paint();
|
|
318
|
+
if (this.#value !== previous) this.#emitInputAndChange();
|
|
319
|
+
}
|
|
320
|
+
formStateRestoreCallback(state) {
|
|
321
|
+
if (typeof state !== "string") return;
|
|
322
|
+
this.#value = this.#normalize(finiteNumber(state, this.#min));
|
|
323
|
+
this.#dirty = true;
|
|
324
|
+
this.#paint();
|
|
325
|
+
}
|
|
326
|
+
formDisabledCallback() {
|
|
327
|
+
this.#paint();
|
|
328
|
+
}
|
|
329
|
+
get #min() {
|
|
330
|
+
return finiteNumber(this.getAttribute("min"), 0);
|
|
331
|
+
}
|
|
332
|
+
get #max() {
|
|
333
|
+
return Math.max(this.#min, finiteNumber(this.getAttribute("max"), 100));
|
|
334
|
+
}
|
|
335
|
+
get #step() {
|
|
336
|
+
const step = finiteNumber(this.getAttribute("step"), 1);
|
|
337
|
+
return step > 0 ? step : 1;
|
|
338
|
+
}
|
|
339
|
+
get #isDisabled() {
|
|
340
|
+
return this.hasAttribute("disabled") || this.matches(":disabled");
|
|
341
|
+
}
|
|
342
|
+
#initialValue() {
|
|
343
|
+
const source = this.getAttribute("value") ?? this.getAttribute("defaultvalue");
|
|
344
|
+
return this.#normalize(finiteNumber(source, this.#min));
|
|
345
|
+
}
|
|
346
|
+
#normalize(value) {
|
|
347
|
+
const min = this.#min;
|
|
348
|
+
const max = this.#max;
|
|
349
|
+
const step = this.#step;
|
|
350
|
+
const stepped = min + Math.round((Math.min(max, Math.max(min, value)) - min) / step) * step;
|
|
351
|
+
const precision = Math.min(12, Math.max(precisionOf(min), precisionOf(max), precisionOf(step)));
|
|
352
|
+
return Number(Math.min(max, Math.max(min, stepped)).toFixed(precision));
|
|
353
|
+
}
|
|
354
|
+
#percent(value = this.#value) {
|
|
355
|
+
const range = this.#max - this.#min;
|
|
356
|
+
return range > 0 ? (value - this.#min) / range * 100 : 0;
|
|
357
|
+
}
|
|
358
|
+
#paint() {
|
|
359
|
+
const percent = `${this.#percent()}%`;
|
|
360
|
+
this.#railArea.style.setProperty("--_percent", percent);
|
|
361
|
+
const value = this.#displayValue();
|
|
362
|
+
const displayedValue = String(this.#value);
|
|
363
|
+
const prefix = this.getAttribute("value-prefix") ?? "";
|
|
364
|
+
const suffix = this.getAttribute("value-suffix") ?? "";
|
|
365
|
+
for (const [element, prefixElement, suffixElement] of [
|
|
366
|
+
[this.#inlineValue, this.#inlineValuePrefix, this.#inlineValueSuffix],
|
|
367
|
+
[this.#endValue, this.#endValuePrefix, this.#endValueSuffix],
|
|
368
|
+
[this.#thumbValue, this.#thumbValuePrefix, this.#thumbValueSuffix]
|
|
369
|
+
]) {
|
|
370
|
+
element.textContent = displayedValue;
|
|
371
|
+
prefixElement.textContent = prefix;
|
|
372
|
+
suffixElement.textContent = suffix;
|
|
373
|
+
element.prepend(prefixElement);
|
|
374
|
+
element.append(suffixElement);
|
|
375
|
+
}
|
|
376
|
+
const internals = this.#internals;
|
|
377
|
+
if (!internals) return;
|
|
378
|
+
internals.ariaValueMin = String(this.#min);
|
|
379
|
+
internals.ariaValueMax = String(this.#max);
|
|
380
|
+
internals.ariaValueNow = String(this.#value);
|
|
381
|
+
internals.ariaValueText = value;
|
|
382
|
+
internals.setFormValue(this.#isDisabled ? null : String(this.#value), String(this.#value));
|
|
383
|
+
}
|
|
384
|
+
#displayValue() {
|
|
385
|
+
return `${this.getAttribute("value-prefix") ?? ""}${this.#value}${this.getAttribute("value-suffix") ?? ""}`;
|
|
386
|
+
}
|
|
387
|
+
#syncSlotVisibility() {
|
|
388
|
+
const assigned = (slot) => slot.assignedNodes({ flatten: true }).length > 0;
|
|
389
|
+
this.#header.hidden = !assigned(this.#label) && this.getAttribute("value-display") === "none";
|
|
390
|
+
this.#markers.hidden = !assigned(this.#markers);
|
|
391
|
+
this.#extras.hidden = !assigned(this.#extras);
|
|
392
|
+
}
|
|
393
|
+
#setValue(value) {
|
|
394
|
+
const next = this.#normalize(value);
|
|
395
|
+
if (next === this.#value) return false;
|
|
396
|
+
this.#value = next;
|
|
397
|
+
this.#dirty = true;
|
|
398
|
+
this.#paint();
|
|
399
|
+
this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
#emitInputAndChange() {
|
|
403
|
+
this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
|
|
404
|
+
this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
|
|
405
|
+
}
|
|
406
|
+
#valueAt(clientX) {
|
|
407
|
+
const rect = this.#railArea.getBoundingClientRect();
|
|
408
|
+
if (rect.width <= 0) return this.#value;
|
|
409
|
+
return this.#min + (clientX - rect.left) / rect.width * (this.#max - this.#min);
|
|
410
|
+
}
|
|
411
|
+
#beginDrag(event) {
|
|
412
|
+
if (this.#isDisabled || event.button !== 0) return;
|
|
413
|
+
const rect = this.#railArea.getBoundingClientRect();
|
|
414
|
+
if (rect.width <= 0) return;
|
|
415
|
+
this.#drag = { pointerId: event.pointerId, startX: event.clientX, startValue: this.#value };
|
|
416
|
+
this.#control.setPointerCapture(event.pointerId);
|
|
417
|
+
this.#control.dataset.dragging = "";
|
|
418
|
+
this.#control.dataset.pointerFocus = "";
|
|
419
|
+
this.focus({ preventScroll: true });
|
|
420
|
+
if (this.getAttribute("track-click") === "jump") this.#setValue(this.#valueAt(event.clientX));
|
|
421
|
+
event.preventDefault();
|
|
422
|
+
}
|
|
423
|
+
#moveDrag(event) {
|
|
424
|
+
const drag = this.#drag;
|
|
425
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
426
|
+
const next = this.getAttribute("track-click") === "jump" ? this.#valueAt(event.clientX) : drag.startValue + (event.clientX - drag.startX) / this.#railArea.getBoundingClientRect().width * (this.#max - this.#min);
|
|
427
|
+
this.#setValue(next);
|
|
428
|
+
event.preventDefault();
|
|
429
|
+
}
|
|
430
|
+
#finishDrag(event) {
|
|
431
|
+
const drag = this.#drag;
|
|
432
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
433
|
+
this.#drag = void 0;
|
|
434
|
+
delete this.#control.dataset.dragging;
|
|
435
|
+
if (this.#control.hasPointerCapture(event.pointerId)) this.#control.releasePointerCapture(event.pointerId);
|
|
436
|
+
if (this.#value !== drag.startValue) this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
|
|
437
|
+
}
|
|
438
|
+
#handleKeydown(event) {
|
|
439
|
+
if (event.target !== this || this.#isDisabled) return;
|
|
440
|
+
delete this.#control.dataset.pointerFocus;
|
|
441
|
+
const page = Math.max(this.#step, (this.#max - this.#min) / 10);
|
|
442
|
+
let next;
|
|
443
|
+
switch (event.key) {
|
|
444
|
+
case "ArrowRight":
|
|
445
|
+
case "ArrowUp":
|
|
446
|
+
next = this.#value + this.#step;
|
|
447
|
+
break;
|
|
448
|
+
case "ArrowLeft":
|
|
449
|
+
case "ArrowDown":
|
|
450
|
+
next = this.#value - this.#step;
|
|
451
|
+
break;
|
|
452
|
+
case "PageUp":
|
|
453
|
+
next = this.#value + page;
|
|
454
|
+
break;
|
|
455
|
+
case "PageDown":
|
|
456
|
+
next = this.#value - page;
|
|
457
|
+
break;
|
|
458
|
+
case "Home":
|
|
459
|
+
next = this.#min;
|
|
460
|
+
break;
|
|
461
|
+
case "End":
|
|
462
|
+
next = this.#max;
|
|
463
|
+
break;
|
|
464
|
+
default:
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
event.preventDefault();
|
|
468
|
+
if (this.#setValue(next)) this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
function register_a_slider() {
|
|
472
|
+
if (typeof customElements === "undefined") return;
|
|
473
|
+
if (!customElements.get("a-slider")) customElements.define("a-slider", ASliderElement);
|
|
474
|
+
}
|
|
475
|
+
register_a_slider();
|
|
476
|
+
export {
|
|
477
|
+
ASliderElement,
|
|
478
|
+
register_a_slider
|
|
479
|
+
};
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* productized "copy button" / "copying menu item". `<a-copy>` (slotted inside a
|
|
4
4
|
* button or menu row) calls these on the host's activation: it performs the
|
|
5
5
|
* clipboard write itself (rather than a UI-thread callback) and reports the
|
|
6
|
-
* outcome with a `copydone` event
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* outcome with a `copydone` event. JSX presets can render visual feedback from
|
|
7
|
+
* that event. Nothing here touches the DOM — no light-DOM mutation, no host
|
|
8
|
+
* attributes, no ElementInternals.
|
|
9
9
|
*
|
|
10
10
|
* Events are dispatched non-bubbling (`bubbles: false`): the wrapper binds on the
|
|
11
11
|
* host itself, so it catches them in the target phase, and not bubbling keeps a
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export { ASwitchElement, register_a_switch } from './a-switch';
|
|
|
23
23
|
export { AExpanderElement, register_a_expander } from './a-expander';
|
|
24
24
|
export { ATooltipElement, register_a_tooltip } from './a-tooltip';
|
|
25
25
|
export { AInputElement, register_a_input } from './a-input';
|
|
26
|
+
export { ASliderElement, register_a_slider } from './a-slider';
|
|
26
27
|
export { AInputTimeElement, register_a_input_time } from './a-input-time';
|
|
27
28
|
export { ACalendarElement, register_a_calendar } from './a-calendar';
|
|
28
29
|
export { ARadioElement, register_a_radio } from './a-radio';
|
package/dist/elements/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { ASwitchElement, register_a_switch } from "./a-switch";
|
|
|
8
8
|
import { AExpanderElement, register_a_expander } from "./a-expander";
|
|
9
9
|
import { ATooltipElement, register_a_tooltip } from "./a-tooltip";
|
|
10
10
|
import { AInputElement, register_a_input } from "./a-input";
|
|
11
|
+
import { ASliderElement, register_a_slider } from "./a-slider";
|
|
11
12
|
import { AInputTimeElement, register_a_input_time } from "./a-input-time";
|
|
12
13
|
import { ACalendarElement, register_a_calendar } from "./a-calendar";
|
|
13
14
|
import { ARadioElement, register_a_radio } from "./a-radio";
|
|
@@ -45,6 +46,7 @@ export {
|
|
|
45
46
|
AProgressElement,
|
|
46
47
|
ARadioElement,
|
|
47
48
|
ARadioGroupElement,
|
|
49
|
+
ASliderElement,
|
|
48
50
|
ASwitchElement,
|
|
49
51
|
ATabElement,
|
|
50
52
|
ATabPanelElement,
|
|
@@ -71,6 +73,7 @@ export {
|
|
|
71
73
|
register_a_progress,
|
|
72
74
|
register_a_radio,
|
|
73
75
|
register_a_radio_group,
|
|
76
|
+
register_a_slider,
|
|
74
77
|
register_a_switch,
|
|
75
78
|
register_a_tab,
|
|
76
79
|
register_a_tabpanel,
|
package/dist/general_types.d.ts
CHANGED
|
@@ -572,8 +572,58 @@ export interface AInputAttributes extends BaseAttributes {
|
|
|
572
572
|
'aria-invalid'?: 'true' | 'false' | boolean;
|
|
573
573
|
'aria-label'?: string;
|
|
574
574
|
}
|
|
575
|
+
/** Attributes for the `<a-slider>` custom element. For the typed JSX wrapper,
|
|
576
|
+
* display formatting, and marker layout use `Slider` from `@antadesign/anta`. */
|
|
577
|
+
export interface ASliderAttributes extends BaseAttributes {
|
|
578
|
+
/** Controlled numeric value. */
|
|
579
|
+
value?: number | string;
|
|
580
|
+
/** Initial uncontrolled value and form-reset baseline. */
|
|
581
|
+
defaultvalue?: number | string;
|
|
582
|
+
/** Lowest permitted value. Defaults to 0. */
|
|
583
|
+
min?: number | string;
|
|
584
|
+
/** Highest permitted value. Defaults to 100. */
|
|
585
|
+
max?: number | string;
|
|
586
|
+
/** Smallest permitted increment. Defaults to 1. */
|
|
587
|
+
step?: number | string;
|
|
588
|
+
/** Form field name — submitted through ElementInternals. */
|
|
589
|
+
name?: string;
|
|
590
|
+
/** Disables pointer and keyboard interaction. Presence-based. */
|
|
591
|
+
disabled?: boolean | '';
|
|
592
|
+
/** Colour of the filled rail. Named tones or a literal CSS colour. */
|
|
593
|
+
tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
594
|
+
/** Colour of the thumb stroke. Named tones or a literal CSS colour. */
|
|
595
|
+
'thumb-tone'?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
596
|
+
/** Size variant. small=24px, medium=28px, large=32px tall. */
|
|
597
|
+
size?: 'small' | 'medium' | 'large';
|
|
598
|
+
/** Thickness of both rail segments as a CSS length, such as `'4px'`. */
|
|
599
|
+
'track-size'?: string;
|
|
600
|
+
/** Diameter of the thumb as a CSS length, such as `'20px'`. */
|
|
601
|
+
'thumb-size'?: string;
|
|
602
|
+
/** Fill the thumb with its resolved border colour. Presence-based. */
|
|
603
|
+
'thumb-fill'?: boolean | '';
|
|
604
|
+
/** Fully round the rail and thumb, or set both to a custom radius. */
|
|
605
|
+
round?: boolean | number | string;
|
|
606
|
+
/** `jump` moves to a pressed rail position. Omit for relative dragging. */
|
|
607
|
+
'track-click'?: 'jump';
|
|
608
|
+
/** `inline`, `thumb`, or `none`; omit for a value at the label row's end. */
|
|
609
|
+
'value-display'?: 'inline' | 'thumb' | 'none';
|
|
610
|
+
/** Text inserted before the live numeric value. */
|
|
611
|
+
'value-prefix'?: string;
|
|
612
|
+
/** Text inserted after the live numeric value. */
|
|
613
|
+
'value-suffix'?: string;
|
|
614
|
+
/** Fires on each value change. */
|
|
615
|
+
oninput?: (e: any) => void;
|
|
616
|
+
/** Fires when a drag ends or a keyboard value change completes. */
|
|
617
|
+
onchange?: (e: any) => void;
|
|
618
|
+
role?: string;
|
|
619
|
+
'aria-label'?: string;
|
|
620
|
+
'aria-valuenow'?: number | string;
|
|
621
|
+
'aria-valuemin'?: number | string;
|
|
622
|
+
'aria-valuemax'?: number | string;
|
|
623
|
+
'aria-valuetext'?: string;
|
|
624
|
+
}
|
|
575
625
|
/** Attributes for the `<a-input-time>` custom element — a segmented wall-clock
|
|
576
|
-
* time field (hour / minute / AM-PM
|
|
626
|
+
* time field (hour / minute / AM-PM native text-input sections in one box). */
|
|
577
627
|
export interface AInputTimeAttributes extends BaseAttributes {
|
|
578
628
|
/** Controlled value — 24-hour `"HH:mm"`, `''` when incomplete. */
|
|
579
629
|
value?: string;
|
|
@@ -835,10 +885,13 @@ export interface ACopyAttributes extends BaseAttributes {
|
|
|
835
885
|
'copy-url'?: boolean | '';
|
|
836
886
|
/** Prefix the copied `copy` string with `// URL: <href>`. Presence-based. */
|
|
837
887
|
'copy-with-url'?: boolean | '';
|
|
838
|
-
/**
|
|
839
|
-
*
|
|
840
|
-
* it
|
|
888
|
+
/** Show a short confirmation label after a successful copy. It renders in the
|
|
889
|
+
* top layer so the host's overflow cannot clip it. Presence-based. `ButtonCopy`
|
|
890
|
+
* sets it when `iconPlacement="none"`. */
|
|
841
891
|
toast?: boolean | '';
|
|
892
|
+
/** Text in the success confirmation shown by `toast`.
|
|
893
|
+
* @defaultValue Copied */
|
|
894
|
+
'copied-label'?: string;
|
|
842
895
|
/** Fired after a copy attempt (`copydone`, `detail: { ok }`, non-bubbling so a
|
|
843
896
|
* nested copy control can't flip an ancestor's feedback). All-lowercase so it
|
|
844
897
|
* binds in React *and* Preact. */
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,8 @@ export { Expander } from './components/Expander';
|
|
|
52
52
|
export type { ExpanderProps } from './components/Expander';
|
|
53
53
|
export { Input } from './components/Input';
|
|
54
54
|
export type { InputProps, InputChangeAttrs } from './components/Input';
|
|
55
|
+
export { Slider } from './components/Slider';
|
|
56
|
+
export type { SliderProps, SliderMarker, SliderChangeAttrs } from './components/Slider';
|
|
55
57
|
export { Calendar } from './components/Calendar';
|
|
56
58
|
export type { CalendarProps, CalendarChangeAttrs } from './components/Calendar';
|
|
57
59
|
export { InputDate } from './components/InputDate';
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import { MenuSeparator } from "./components/MenuSeparator";
|
|
|
16
16
|
import { MenuGroup } from "./components/MenuGroup";
|
|
17
17
|
import { Expander } from "./components/Expander";
|
|
18
18
|
import { Input } from "./components/Input";
|
|
19
|
+
import { Slider } from "./components/Slider";
|
|
19
20
|
import { Calendar } from "./components/Calendar";
|
|
20
21
|
import { InputDate } from "./components/InputDate";
|
|
21
22
|
import { InputTime } from "./components/InputTime";
|
|
@@ -71,6 +72,7 @@ export {
|
|
|
71
72
|
RadioGroup,
|
|
72
73
|
Select,
|
|
73
74
|
SelectFaceted,
|
|
75
|
+
Slider,
|
|
74
76
|
Switch,
|
|
75
77
|
TabPanel,
|
|
76
78
|
Tabs,
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export declare function useSyncExternalStore<T>(subscribe: (onChange: () => void
|
|
|
44
44
|
export declare function jsx(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
45
45
|
export declare function jsxs(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
46
46
|
export { _Fragment as Fragment };
|
|
47
|
-
import type { AProgressAttributes, ATextAttributes, ATitleAttributes, ATagAttributes, AExpanderAttributes, AIconAttributes, AButtonAttributes, ACopyAttributes, ACheckboxAttributes, ASwitchAttributes, ATooltipAttributes, AInputAttributes, AInputTimeAttributes, ACalendarAttributes, ARadioAttributes, ARadioGroupAttributes, AMenuAttributes, AMenuItemAttributes, AMenuGroupAttributes, ATabsAttributes, ATabAttributes, ATabpanelAttributes, ADialogAttributes, ACardAttributes, ABannerAttributes, AToasterAttributes, AToastAttributes, BaseAttributes } from './general_types';
|
|
47
|
+
import type { AProgressAttributes, ATextAttributes, ATitleAttributes, ATagAttributes, AExpanderAttributes, AIconAttributes, AButtonAttributes, ACopyAttributes, ACheckboxAttributes, ASwitchAttributes, ATooltipAttributes, AInputAttributes, ASliderAttributes, AInputTimeAttributes, ACalendarAttributes, ARadioAttributes, ARadioGroupAttributes, AMenuAttributes, AMenuItemAttributes, AMenuGroupAttributes, ATabsAttributes, ATabAttributes, ATabpanelAttributes, ADialogAttributes, ACardAttributes, ABannerAttributes, AToasterAttributes, AToastAttributes, BaseAttributes } from './general_types';
|
|
48
48
|
export declare namespace JSX {
|
|
49
49
|
interface IntrinsicElements extends React.JSX.IntrinsicElements, AntaIntrinsicElements {
|
|
50
50
|
}
|
|
@@ -77,6 +77,7 @@ export interface AntaIntrinsicElements {
|
|
|
77
77
|
'a-switch-hint': BaseAttributes;
|
|
78
78
|
'a-tooltip': ATooltipAttributes;
|
|
79
79
|
'a-input': AInputAttributes;
|
|
80
|
+
'a-slider': ASliderAttributes;
|
|
80
81
|
'a-input-time': AInputTimeAttributes;
|
|
81
82
|
'a-calendar': ACalendarAttributes;
|
|
82
83
|
'a-radio': ARadioAttributes;
|