@antadesign/anta 0.3.16 → 0.3.18
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 +11 -10
- 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/Loader.d.ts +39 -0
- package/dist/components/Loader.js +33 -0
- package/dist/components/Progress.d.ts +17 -8
- package/dist/components/Progress.js +12 -9
- 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-button.css +1 -1
- package/dist/elements/a-copy.d.ts +1 -1
- package/dist/elements/a-copy.js +103 -109
- package/dist/elements/a-icon.d.ts +1 -0
- package/dist/elements/a-icon.js +1 -0
- 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-loader.css +1 -0
- package/dist/elements/a-loader.d.ts +12 -0
- package/dist/elements/a-loader.js +15 -0
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-progress.js +32 -2
- 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 +2 -0
- package/dist/elements/index.js +6 -0
- package/dist/general_types.d.ts +82 -6
- package/dist/index.d.ts +8 -1
- package/dist/index.js +4 -0
- package/dist/jsx-runtime.d.ts +3 -1
- package/dist/reset.css +1 -1
- package/dist/theme-anta.css +1 -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
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* `customElements` (SSR), but there's no reason to load it server-side.
|
|
15
15
|
*/
|
|
16
16
|
export { AProgressElement, register_a_progress } from './a-progress';
|
|
17
|
+
export { ALoaderElement, register_a_loader } from './a-loader';
|
|
17
18
|
export { ATextElement, register_a_text } from './a-text';
|
|
18
19
|
export { AIconElement, register_a_icon } from './a-icon';
|
|
19
20
|
export { AButtonElement, register_a_button } from './a-button';
|
|
@@ -23,6 +24,7 @@ export { ASwitchElement, register_a_switch } from './a-switch';
|
|
|
23
24
|
export { AExpanderElement, register_a_expander } from './a-expander';
|
|
24
25
|
export { ATooltipElement, register_a_tooltip } from './a-tooltip';
|
|
25
26
|
export { AInputElement, register_a_input } from './a-input';
|
|
27
|
+
export { ASliderElement, register_a_slider } from './a-slider';
|
|
26
28
|
export { AInputTimeElement, register_a_input_time } from './a-input-time';
|
|
27
29
|
export { ACalendarElement, register_a_calendar } from './a-calendar';
|
|
28
30
|
export { ARadioElement, register_a_radio } from './a-radio';
|
package/dist/elements/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AProgressElement, register_a_progress } from "./a-progress";
|
|
2
|
+
import { ALoaderElement, register_a_loader } from "./a-loader";
|
|
2
3
|
import { ATextElement, register_a_text } from "./a-text";
|
|
3
4
|
import { AIconElement, register_a_icon } from "./a-icon";
|
|
4
5
|
import { AButtonElement, register_a_button } from "./a-button";
|
|
@@ -8,6 +9,7 @@ import { ASwitchElement, register_a_switch } from "./a-switch";
|
|
|
8
9
|
import { AExpanderElement, register_a_expander } from "./a-expander";
|
|
9
10
|
import { ATooltipElement, register_a_tooltip } from "./a-tooltip";
|
|
10
11
|
import { AInputElement, register_a_input } from "./a-input";
|
|
12
|
+
import { ASliderElement, register_a_slider } from "./a-slider";
|
|
11
13
|
import { AInputTimeElement, register_a_input_time } from "./a-input-time";
|
|
12
14
|
import { ACalendarElement, register_a_calendar } from "./a-calendar";
|
|
13
15
|
import { ARadioElement, register_a_radio } from "./a-radio";
|
|
@@ -38,6 +40,7 @@ export {
|
|
|
38
40
|
AIconElement,
|
|
39
41
|
AInputElement,
|
|
40
42
|
AInputTimeElement,
|
|
43
|
+
ALoaderElement,
|
|
41
44
|
AMenuElement,
|
|
42
45
|
AMenuGroupElement,
|
|
43
46
|
AMenuItemElement,
|
|
@@ -45,6 +48,7 @@ export {
|
|
|
45
48
|
AProgressElement,
|
|
46
49
|
ARadioElement,
|
|
47
50
|
ARadioGroupElement,
|
|
51
|
+
ASliderElement,
|
|
48
52
|
ASwitchElement,
|
|
49
53
|
ATabElement,
|
|
50
54
|
ATabPanelElement,
|
|
@@ -64,6 +68,7 @@ export {
|
|
|
64
68
|
register_a_icon,
|
|
65
69
|
register_a_input,
|
|
66
70
|
register_a_input_time,
|
|
71
|
+
register_a_loader,
|
|
67
72
|
register_a_menu,
|
|
68
73
|
register_a_menu_group,
|
|
69
74
|
register_a_menu_item,
|
|
@@ -71,6 +76,7 @@ export {
|
|
|
71
76
|
register_a_progress,
|
|
72
77
|
register_a_radio,
|
|
73
78
|
register_a_radio_group,
|
|
79
|
+
register_a_slider,
|
|
74
80
|
register_a_switch,
|
|
75
81
|
register_a_tab,
|
|
76
82
|
register_a_tabpanel,
|
package/dist/general_types.d.ts
CHANGED
|
@@ -147,13 +147,15 @@ export interface BaseAttributes extends DOMEventHandlers {
|
|
|
147
147
|
* typed props and computed labels, use `Progress` from `@antadesign/anta`.
|
|
148
148
|
*/
|
|
149
149
|
export interface AProgressAttributes extends BaseAttributes {
|
|
150
|
-
/** Current progress value. */
|
|
151
|
-
value?: number | string;
|
|
150
|
+
/** Current progress value. Omit this attribute for indeterminate progress. */
|
|
151
|
+
value?: number | string | false;
|
|
152
152
|
/** Maximum value. Defaults to 100. */
|
|
153
153
|
max?: number | string;
|
|
154
154
|
/** Colour variant, or any literal CSS colour for a custom tone (derived in
|
|
155
155
|
* oklch). Named tones track light/dark automatically. */
|
|
156
156
|
tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
157
|
+
/** Size variant. `medium` is the default. */
|
|
158
|
+
size?: 'small' | 'medium' | 'large';
|
|
157
159
|
/** Fully-round track (`border-radius: 999px`), or a custom radius via a length
|
|
158
160
|
* value (`round="6px"`). Presence-based for the boolean form. */
|
|
159
161
|
round?: boolean | number | string;
|
|
@@ -168,6 +170,27 @@ export interface AProgressAttributes extends BaseAttributes {
|
|
|
168
170
|
/** ARIA accessible name. */
|
|
169
171
|
'aria-label'?: string;
|
|
170
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Attributes for the `<a-loader>` custom element. For the JSX wrapper with
|
|
175
|
+
* cross-browser sizing and accessible progress semantics, use `Loader` from
|
|
176
|
+
* `@antadesign/anta`.
|
|
177
|
+
*/
|
|
178
|
+
export interface ALoaderAttributes extends BaseAttributes {
|
|
179
|
+
/** Presence selects the static, determinate gradient. Set `--loader-value`
|
|
180
|
+
* in `style` to its percentage. Omit this attribute for the rotating
|
|
181
|
+
* indeterminate gradient. */
|
|
182
|
+
value?: number | string | false;
|
|
183
|
+
/** ARIA accessible name. */
|
|
184
|
+
'aria-label'?: string;
|
|
185
|
+
/** Hides a decorative loader from screen readers. */
|
|
186
|
+
'aria-hidden'?: 'true' | 'false' | boolean;
|
|
187
|
+
/** ARIA value-now for determinate progress. */
|
|
188
|
+
'aria-valuenow'?: number | string;
|
|
189
|
+
/** ARIA value-min. */
|
|
190
|
+
'aria-valuemin'?: number | string;
|
|
191
|
+
/** ARIA value-max. */
|
|
192
|
+
'aria-valuemax'?: number | string;
|
|
193
|
+
}
|
|
171
194
|
/**
|
|
172
195
|
* Attributes for the `<a-text>` custom element.
|
|
173
196
|
*
|
|
@@ -572,8 +595,58 @@ export interface AInputAttributes extends BaseAttributes {
|
|
|
572
595
|
'aria-invalid'?: 'true' | 'false' | boolean;
|
|
573
596
|
'aria-label'?: string;
|
|
574
597
|
}
|
|
598
|
+
/** Attributes for the `<a-slider>` custom element. For the typed JSX wrapper,
|
|
599
|
+
* display formatting, and marker layout use `Slider` from `@antadesign/anta`. */
|
|
600
|
+
export interface ASliderAttributes extends BaseAttributes {
|
|
601
|
+
/** Controlled numeric value. */
|
|
602
|
+
value?: number | string;
|
|
603
|
+
/** Initial uncontrolled value and form-reset baseline. */
|
|
604
|
+
defaultvalue?: number | string;
|
|
605
|
+
/** Lowest permitted value. Defaults to 0. */
|
|
606
|
+
min?: number | string;
|
|
607
|
+
/** Highest permitted value. Defaults to 100. */
|
|
608
|
+
max?: number | string;
|
|
609
|
+
/** Smallest permitted increment. Defaults to 1. */
|
|
610
|
+
step?: number | string;
|
|
611
|
+
/** Form field name — submitted through ElementInternals. */
|
|
612
|
+
name?: string;
|
|
613
|
+
/** Disables pointer and keyboard interaction. Presence-based. */
|
|
614
|
+
disabled?: boolean | '';
|
|
615
|
+
/** Colour of the filled rail. Named tones or a literal CSS colour. */
|
|
616
|
+
tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
617
|
+
/** Colour of the thumb stroke. Named tones or a literal CSS colour. */
|
|
618
|
+
'thumb-tone'?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
|
|
619
|
+
/** Size variant. small=24px, medium=28px, large=32px tall. */
|
|
620
|
+
size?: 'small' | 'medium' | 'large';
|
|
621
|
+
/** Thickness of both rail segments as a CSS length, such as `'4px'`. */
|
|
622
|
+
'track-size'?: string;
|
|
623
|
+
/** Diameter of the thumb as a CSS length, such as `'20px'`. */
|
|
624
|
+
'thumb-size'?: string;
|
|
625
|
+
/** Fill the thumb with its resolved border colour. Presence-based. */
|
|
626
|
+
'thumb-fill'?: boolean | '';
|
|
627
|
+
/** Fully round the rail and thumb, or set both to a custom radius. */
|
|
628
|
+
round?: boolean | number | string;
|
|
629
|
+
/** `jump` moves to a pressed rail position. Omit for relative dragging. */
|
|
630
|
+
'track-click'?: 'jump';
|
|
631
|
+
/** `inline`, `thumb`, or `none`; omit for a value at the label row's end. */
|
|
632
|
+
'value-display'?: 'inline' | 'thumb' | 'none';
|
|
633
|
+
/** Text inserted before the live numeric value. */
|
|
634
|
+
'value-prefix'?: string;
|
|
635
|
+
/** Text inserted after the live numeric value. */
|
|
636
|
+
'value-suffix'?: string;
|
|
637
|
+
/** Fires on each value change. */
|
|
638
|
+
oninput?: (e: any) => void;
|
|
639
|
+
/** Fires when a drag ends or a keyboard value change completes. */
|
|
640
|
+
onchange?: (e: any) => void;
|
|
641
|
+
role?: string;
|
|
642
|
+
'aria-label'?: string;
|
|
643
|
+
'aria-valuenow'?: number | string;
|
|
644
|
+
'aria-valuemin'?: number | string;
|
|
645
|
+
'aria-valuemax'?: number | string;
|
|
646
|
+
'aria-valuetext'?: string;
|
|
647
|
+
}
|
|
575
648
|
/** Attributes for the `<a-input-time>` custom element — a segmented wall-clock
|
|
576
|
-
* time field (hour / minute / AM-PM
|
|
649
|
+
* time field (hour / minute / AM-PM native text-input sections in one box). */
|
|
577
650
|
export interface AInputTimeAttributes extends BaseAttributes {
|
|
578
651
|
/** Controlled value — 24-hour `"HH:mm"`, `''` when incomplete. */
|
|
579
652
|
value?: string;
|
|
@@ -835,10 +908,13 @@ export interface ACopyAttributes extends BaseAttributes {
|
|
|
835
908
|
'copy-url'?: boolean | '';
|
|
836
909
|
/** Prefix the copied `copy` string with `// URL: <href>`. Presence-based. */
|
|
837
910
|
'copy-with-url'?: boolean | '';
|
|
838
|
-
/**
|
|
839
|
-
*
|
|
840
|
-
* it
|
|
911
|
+
/** Show a short confirmation label after a successful copy. It renders in the
|
|
912
|
+
* top layer so the host's overflow cannot clip it. Presence-based. `ButtonCopy`
|
|
913
|
+
* sets it when `iconPlacement="none"`. */
|
|
841
914
|
toast?: boolean | '';
|
|
915
|
+
/** Text in the success confirmation shown by `toast`.
|
|
916
|
+
* @defaultValue Copied */
|
|
917
|
+
'copied-label'?: string;
|
|
842
918
|
/** Fired after a copy attempt (`copydone`, `detail: { ok }`, non-bubbling so a
|
|
843
919
|
* nested copy control can't flip an ancestor's feedback). All-lowercase so it
|
|
844
920
|
* binds in React *and* Preact. */
|