stimeo-ui 0.16.0 → 0.17.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +8 -1
- data/dist/cable/index.js +363 -436
- data/dist/controllers/accordion_controller.js +166 -55
- data/dist/controllers/alert_dialog_controller.js +862 -221
- data/dist/controllers/announcer_controller.js +135 -198
- data/dist/controllers/aspect_ratio_controller.js +0 -10
- data/dist/controllers/auto_submit_controller.js +271 -127
- data/dist/controllers/avatar_controller.js +171 -105
- data/dist/controllers/breadcrumb_controller.js +0 -130
- data/dist/controllers/bulk_select_controller.js +262 -52
- data/dist/controllers/calendar_controller.js +175 -209
- data/dist/controllers/carousel_controller.js +461 -399
- data/dist/controllers/character_counter_controller.js +246 -156
- data/dist/controllers/checkbox_controller.js +32 -74
- data/dist/controllers/clipboard_controller.js +168 -147
- data/dist/controllers/collapsible_controller.js +301 -120
- data/dist/controllers/color_picker_controller.js +149 -139
- data/dist/controllers/combobox_controller.js +360 -133
- data/dist/controllers/command_palette_controller.js +970 -358
- data/dist/controllers/conditional_fields_controller.js +166 -124
- data/dist/controllers/confirm_controller.js +939 -248
- data/dist/controllers/context_menu_controller.js +256 -128
- data/dist/controllers/count_up_controller.js +73 -21
- data/dist/controllers/countdown_controller.js +183 -148
- data/dist/controllers/currency_input_controller.js +134 -158
- data/dist/controllers/data_grid_controller.js +114 -186
- data/dist/controllers/date_range_picker_controller.js +288 -206
- data/dist/controllers/dialog_controller.js +858 -223
- data/dist/controllers/direct_upload_controller.js +73 -153
- data/dist/controllers/dirty_form_controller.js +14 -48
- data/dist/controllers/dismissible_controller.js +175 -21
- data/dist/controllers/drawer_controller.js +933 -341
- data/dist/controllers/dropdown_controller.js +312 -82
- data/dist/controllers/editable_controller.js +158 -68
- data/dist/controllers/empty_state_controller.js +67 -53
- data/dist/controllers/file_dropzone_controller.js +311 -207
- data/dist/controllers/filter_controller.js +67 -39
- data/dist/controllers/flash_controller.js +172 -314
- data/dist/controllers/focus_controller.js +654 -240
- data/dist/controllers/form_field_controller.js +147 -132
- data/dist/controllers/form_validation_controller.js +13 -86
- data/dist/controllers/frame_loading_controller.js +264 -213
- data/dist/controllers/highlight_controller.js +107 -75
- data/dist/controllers/hover_card_controller.js +309 -118
- data/dist/controllers/idle_controller.js +267 -101
- data/dist/controllers/input_mask_controller.js +71 -72
- data/dist/controllers/intersection_controller.js +147 -106
- data/dist/controllers/lazy_frame_controller.js +9 -65
- data/dist/controllers/listbox_controller.js +306 -204
- data/dist/controllers/local_time_controller.js +54 -64
- data/dist/controllers/masonry_controller.js +70 -93
- data/dist/controllers/menu_controller.js +214 -156
- data/dist/controllers/menubar_controller.js +170 -329
- data/dist/controllers/meter_controller.js +151 -67
- data/dist/controllers/multi_select_controller.js +593 -358
- data/dist/controllers/navigation_menu_controller.js +124 -232
- data/dist/controllers/nested_form_controller.js +352 -182
- data/dist/controllers/network_status_controller.js +242 -54
- data/dist/controllers/number_input_controller.js +320 -263
- data/dist/controllers/optimistic_controller.js +16 -76
- data/dist/controllers/otp_controller.js +198 -193
- data/dist/controllers/overflow_indicator_controller.js +116 -113
- data/dist/controllers/overflow_menu_controller.js +343 -283
- data/dist/controllers/pagination_controller.js +295 -119
- data/dist/controllers/password_reveal_controller.js +389 -121
- data/dist/controllers/password_strength_controller.js +99 -153
- data/dist/controllers/persist_controller.js +237 -103
- data/dist/controllers/pointer_drag_controller.js +185 -165
- data/dist/controllers/popover_controller.js +236 -97
- data/dist/controllers/portal_controller.js +209 -76
- data/dist/controllers/preview_guard_controller.js +232 -116
- data/dist/controllers/progress_controller.js +125 -56
- data/dist/controllers/radio_group_controller.js +117 -137
- data/dist/controllers/range_slider_controller.js +192 -105
- data/dist/controllers/rating_controller.js +418 -207
- data/dist/controllers/read_more_controller.js +134 -63
- data/dist/controllers/reading_progress_controller.js +147 -135
- data/dist/controllers/relative_time_controller.js +145 -110
- data/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +97 -38
- data/dist/controllers/resizable_controller.js +255 -139
- data/dist/controllers/roving_controller.js +39 -84
- data/dist/controllers/scroll_area_controller.js +428 -225
- data/dist/controllers/scroll_restore_controller.js +0 -53
- data/dist/controllers/scroll_visibility_controller.js +395 -145
- data/dist/controllers/scrollspy_controller.js +181 -242
- data/dist/controllers/separator_controller.js +267 -140
- data/dist/controllers/sidebar_controller.js +1023 -386
- data/dist/controllers/skeleton_controller.js +248 -97
- data/dist/controllers/slider_controller.js +159 -79
- data/dist/controllers/smart_sticky_header_controller.js +162 -63
- data/dist/controllers/sortable_controller.js +0 -112
- data/dist/controllers/spinner_controller.js +277 -169
- data/dist/controllers/step_indicator_controller.js +99 -46
- data/dist/controllers/stepper_controller.js +114 -73
- data/dist/controllers/stick_to_bottom_controller.js +262 -138
- data/dist/controllers/sticky_observer_controller.js +214 -49
- data/dist/controllers/submit_once_controller.js +294 -205
- data/dist/controllers/switch_controller.js +33 -60
- data/dist/controllers/tabs_controller.js +35 -29
- data/dist/controllers/tags_input_controller.js +136 -145
- data/dist/controllers/textarea_autosize_controller.js +71 -58
- data/dist/controllers/theme_controller.js +130 -112
- data/dist/controllers/time_picker_controller.js +146 -80
- data/dist/controllers/toast_controller.js +186 -297
- data/dist/controllers/toggle_group_controller.js +95 -136
- data/dist/controllers/toolbar_controller.js +68 -98
- data/dist/controllers/tooltip_controller.js +158 -124
- data/dist/controllers/transition_controller.js +123 -119
- data/dist/controllers/tree_view_controller.js +150 -345
- data/dist/index.js +6370 -9346
- data/dist/positioning/index.js +148 -47
- data/lib/stimeo/ui/version.rb +1 -1
- metadata +3 -3
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
// src/controllers/slider_controller.ts
|
|
4
|
-
|
|
5
|
-
// src/utils/logical_scroll.ts
|
|
6
3
|
function isRtl(element) {
|
|
7
4
|
return window.getComputedStyle(element).direction === "rtl";
|
|
8
5
|
}
|
|
9
6
|
|
|
10
|
-
// src/utils/arrow_step.ts
|
|
11
7
|
function logicalArrowKey(key, element) {
|
|
12
8
|
if (key !== "ArrowRight" && key !== "ArrowLeft") return key;
|
|
13
9
|
if (!isRtl(element)) return key;
|
|
@@ -18,7 +14,6 @@ function isReservedArrowChord(event, allow = []) {
|
|
|
18
14
|
return event.altKey && !allow.includes("alt") || event.ctrlKey && !allow.includes("ctrl") || event.metaKey && !allow.includes("meta") || event.shiftKey && !allow.includes("shift");
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
// src/utils/field_mirror.ts
|
|
22
17
|
function writeField(field, value) {
|
|
23
18
|
if (field.value === value) return false;
|
|
24
19
|
field.value = value;
|
|
@@ -28,27 +23,33 @@ function commitField(target) {
|
|
|
28
23
|
target.dispatchEvent(new Event("change", { bubbles: true }));
|
|
29
24
|
}
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
var ListenerSet = class {
|
|
27
|
+
#abort = new AbortController();
|
|
28
|
+
add(target, type, handler, options) {
|
|
29
|
+
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
30
|
+
}
|
|
31
|
+
dispose() {
|
|
32
|
+
this.#abort.abort();
|
|
33
|
+
this.#abort = new AbortController();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
32
37
|
var MicrotaskCoalescer = class {
|
|
33
38
|
#run;
|
|
34
39
|
#queued = false;
|
|
35
40
|
#active = false;
|
|
36
41
|
#generation = 0;
|
|
37
|
-
/** @param run - the single reconciliation pass, invoked at most once per batch. */
|
|
38
42
|
constructor(run) {
|
|
39
43
|
this.#run = run;
|
|
40
44
|
}
|
|
41
|
-
/** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
|
|
42
45
|
activate() {
|
|
43
46
|
this.#active = true;
|
|
44
47
|
}
|
|
45
|
-
/** Closes the window and drops any pending pass; call from `disconnect()`. */
|
|
46
48
|
cancel() {
|
|
47
49
|
this.#active = false;
|
|
48
50
|
this.#queued = false;
|
|
49
51
|
this.#generation += 1;
|
|
50
52
|
}
|
|
51
|
-
/** Requests one pass after the batch settles. Idempotent; inert outside the window. */
|
|
52
53
|
schedule() {
|
|
53
54
|
if (!this.#active || this.#queued) return;
|
|
54
55
|
this.#queued = true;
|
|
@@ -61,7 +62,87 @@ var MicrotaskCoalescer = class {
|
|
|
61
62
|
}
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
var MorphRenderWatcher = class {
|
|
66
|
+
#listeners = new ListenerSet();
|
|
67
|
+
#pass;
|
|
68
|
+
#element = null;
|
|
69
|
+
#onMorph = () => this.#pass.schedule();
|
|
70
|
+
constructor(run) {
|
|
71
|
+
this.#pass = new MicrotaskCoalescer(run);
|
|
72
|
+
}
|
|
73
|
+
observe(element) {
|
|
74
|
+
if (this.#element === element) return;
|
|
75
|
+
this.disconnect();
|
|
76
|
+
this.#element = element;
|
|
77
|
+
this.#pass.activate();
|
|
78
|
+
this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
|
|
79
|
+
}
|
|
80
|
+
schedule() {
|
|
81
|
+
this.#pass.schedule();
|
|
82
|
+
}
|
|
83
|
+
disconnect() {
|
|
84
|
+
this.#listeners.dispose();
|
|
85
|
+
this.#pass.cancel();
|
|
86
|
+
this.#element = null;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
var MoveCounter = class {
|
|
91
|
+
#sequence = 0;
|
|
92
|
+
record() {
|
|
93
|
+
this.#sequence += 1;
|
|
94
|
+
return this.#sequence;
|
|
95
|
+
}
|
|
96
|
+
isLatest(token) {
|
|
97
|
+
return token === this.#sequence;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
var NUMBER_BOUNDS = {
|
|
102
|
+
finite: { finite: true },
|
|
103
|
+
positive: { finite: true, exclusiveMin: 0 }};
|
|
104
|
+
function matchesNumberBounds(value, bounds) {
|
|
105
|
+
if (!Number.isFinite(value)) {
|
|
106
|
+
const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
|
|
107
|
+
if (direction === null) return false;
|
|
108
|
+
if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
|
|
109
|
+
}
|
|
110
|
+
if (bounds.min !== void 0 && value < bounds.min) return false;
|
|
111
|
+
if (bounds.max !== void 0 && value > bounds.max) return false;
|
|
112
|
+
if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
|
|
113
|
+
if (bounds.integer && !Number.isInteger(value)) return false;
|
|
114
|
+
if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function readNumber(raw, fallback, bounds) {
|
|
119
|
+
return matchesNumberBounds(raw, bounds) ? raw : fallback;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
var NumberValueReader = class {
|
|
123
|
+
#lastRejected = /* @__PURE__ */ new Map();
|
|
124
|
+
read(owner, name, raw, fallback, bounds) {
|
|
125
|
+
const resolved = readNumber(raw, fallback, bounds);
|
|
126
|
+
if (matchesNumberBounds(raw, bounds)) {
|
|
127
|
+
this.#lastRejected.delete(name);
|
|
128
|
+
return resolved;
|
|
129
|
+
}
|
|
130
|
+
const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
|
|
131
|
+
const literal = owner.element.getAttribute(attribute);
|
|
132
|
+
if (literal === null) {
|
|
133
|
+
this.#lastRejected.delete(name);
|
|
134
|
+
return resolved;
|
|
135
|
+
}
|
|
136
|
+
if (this.#lastRejected.get(name) !== literal) {
|
|
137
|
+
this.#lastRejected.set(name, literal);
|
|
138
|
+
console.warn(
|
|
139
|
+
`Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
return resolved;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
65
146
|
var OwnedPointerSession = class {
|
|
66
147
|
#pointerId;
|
|
67
148
|
#owner;
|
|
@@ -81,7 +162,6 @@ var OwnedPointerSession = class {
|
|
|
81
162
|
} catch {
|
|
82
163
|
}
|
|
83
164
|
}
|
|
84
|
-
/** Releases capture and listeners, then reports the end exactly once. */
|
|
85
165
|
end() {
|
|
86
166
|
this.#finish("teardown");
|
|
87
167
|
}
|
|
@@ -106,7 +186,6 @@ var OwnedPointerSession = class {
|
|
|
106
186
|
};
|
|
107
187
|
};
|
|
108
188
|
|
|
109
|
-
// src/utils/range.ts
|
|
110
189
|
function rangeFraction(value, min, max) {
|
|
111
190
|
const span = max - min;
|
|
112
191
|
if (!(span > 0)) return 0;
|
|
@@ -122,7 +201,6 @@ function rangeFraction(value, min, max) {
|
|
|
122
201
|
return Math.min(1, Math.max(0, fraction));
|
|
123
202
|
}
|
|
124
203
|
|
|
125
|
-
// src/utils/stepped_value.ts
|
|
126
204
|
function effectiveStep(step) {
|
|
127
205
|
return Number.isFinite(step) && step > 0 ? step : 1;
|
|
128
206
|
}
|
|
@@ -228,9 +306,11 @@ function finiteFallback(min, max) {
|
|
|
228
306
|
return 0;
|
|
229
307
|
}
|
|
230
308
|
|
|
231
|
-
// src/controllers/slider_controller.ts
|
|
232
309
|
var FRACTION_PROPERTY = "--stimeo--slider-fraction";
|
|
233
|
-
var SliderController = class extends Controller {
|
|
310
|
+
var SliderController = class _SliderController extends Controller {
|
|
311
|
+
#numbers = new NumberValueReader();
|
|
312
|
+
#moves = new MoveCounter();
|
|
313
|
+
#move = 0;
|
|
234
314
|
static targets = ["track", "thumb", "field"];
|
|
235
315
|
static values = {
|
|
236
316
|
min: { type: Number, default: 0 },
|
|
@@ -239,79 +319,67 @@ var SliderController = class extends Controller {
|
|
|
239
319
|
value: { type: Number, default: 0 },
|
|
240
320
|
logicalTrack: { type: Boolean, default: false }
|
|
241
321
|
};
|
|
322
|
+
static valueConstraints = {
|
|
323
|
+
min: NUMBER_BOUNDS.finite,
|
|
324
|
+
max: NUMBER_BOUNDS.finite,
|
|
325
|
+
step: NUMBER_BOUNDS.positive,
|
|
326
|
+
value: NUMBER_BOUNDS.finite
|
|
327
|
+
};
|
|
242
328
|
static actions = ["onKeydown", "onPointerDown"];
|
|
243
329
|
static events = ["change", "reconcile"];
|
|
244
|
-
/** One initiating pointer owns each live drag and its stable target snapshot. */
|
|
245
330
|
#drag = null;
|
|
246
|
-
/**
|
|
247
|
-
* The value last published: taken on connect, then moved by each user commit
|
|
248
|
-
* and by each repaint that reports a page-driven move.
|
|
249
|
-
*/
|
|
250
331
|
#settled = 0;
|
|
251
|
-
|
|
252
|
-
#repaint = new MicrotaskCoalescer(() => this.#render());
|
|
253
|
-
/** Whether the consumer declared a mirroring track and the direction mirrors it. */
|
|
332
|
+
#repaint = new MorphRenderWatcher(() => this.#render());
|
|
254
333
|
get #mirrored() {
|
|
255
334
|
return this.logicalTrackValue && isRtl(this.element);
|
|
256
335
|
}
|
|
257
|
-
/**
|
|
258
|
-
* Renders the normalized value as the starting position without writing it
|
|
259
|
-
* back, and takes it as the baseline, so connecting reports nothing.
|
|
260
|
-
*/
|
|
261
336
|
connect() {
|
|
262
|
-
this.#repaint.
|
|
337
|
+
this.#repaint.observe(this.element);
|
|
263
338
|
this.#settled = this.#currentValue();
|
|
264
339
|
this.#render();
|
|
265
340
|
}
|
|
266
|
-
/** Cancels any active pointer drag so document listeners never leak. */
|
|
267
341
|
disconnect() {
|
|
268
|
-
this.#repaint.
|
|
342
|
+
this.#repaint.disconnect();
|
|
269
343
|
this.#endDrag();
|
|
270
344
|
}
|
|
271
|
-
/** Repaints a minimum changed by application code or a Turbo morph. */
|
|
272
345
|
minValueChanged() {
|
|
273
346
|
this.#repaint.schedule();
|
|
274
347
|
}
|
|
275
|
-
/** Repaints a maximum changed by application code or a Turbo morph. */
|
|
276
348
|
maxValueChanged() {
|
|
277
349
|
this.#repaint.schedule();
|
|
278
350
|
}
|
|
279
|
-
/** Repaints a step changed by application code or a Turbo morph. */
|
|
280
351
|
stepValueChanged() {
|
|
281
352
|
this.#repaint.schedule();
|
|
282
353
|
}
|
|
283
|
-
/** Repaints a value changed by application code or a Turbo morph. */
|
|
284
354
|
valueValueChanged() {
|
|
285
355
|
this.#repaint.schedule();
|
|
286
356
|
}
|
|
287
|
-
/** Hydrates a thumb inserted or replaced at runtime with the current ARIA state. */
|
|
288
357
|
thumbTargetConnected(thumb) {
|
|
289
358
|
const value = this.#currentValue();
|
|
290
359
|
this.#renderThumb(thumb, value);
|
|
291
|
-
this.#renderFraction(value);
|
|
292
360
|
if (this.#drag && this.#drag.thumb === null) {
|
|
293
361
|
this.#drag.thumb = thumb;
|
|
294
362
|
thumb.focus();
|
|
295
363
|
}
|
|
296
364
|
this.#repaint.schedule();
|
|
297
365
|
}
|
|
298
|
-
/** Fills a form field inserted or replaced at runtime on the next repaint. */
|
|
299
366
|
fieldTargetConnected() {
|
|
300
367
|
this.#repaint.schedule();
|
|
301
368
|
}
|
|
302
|
-
|
|
369
|
+
fieldTargetDisconnected() {
|
|
370
|
+
this.#repaint.schedule();
|
|
371
|
+
}
|
|
303
372
|
thumbTargetDisconnected(thumb) {
|
|
304
373
|
if (this.#drag?.thumb === thumb) this.#drag.thumb = null;
|
|
374
|
+
this.#repaint.schedule();
|
|
305
375
|
}
|
|
306
|
-
/** Ends a gesture whose geometry target disappeared or ceased being a target. */
|
|
307
376
|
trackTargetDisconnected(track) {
|
|
308
377
|
if (this.#drag?.track === track) this.#endDrag();
|
|
309
378
|
}
|
|
310
|
-
/** Handles keyboard stepping per the APG slider model. */
|
|
311
379
|
onKeydown(event) {
|
|
312
380
|
if (isReservedArrowChord(event)) return;
|
|
313
381
|
let next = null;
|
|
314
|
-
const declared = this
|
|
382
|
+
const declared = this.#safeValue;
|
|
315
383
|
const range = this.#steppedRange;
|
|
316
384
|
switch (this.#mirrored ? logicalArrowKey(event.key, this.element) : event.key) {
|
|
317
385
|
case "ArrowRight":
|
|
@@ -329,10 +397,10 @@ var SliderController = class extends Controller {
|
|
|
329
397
|
next = stepSteppedValue(declared, -10, range);
|
|
330
398
|
break;
|
|
331
399
|
case "Home":
|
|
332
|
-
next = this
|
|
400
|
+
next = this.#safeMin;
|
|
333
401
|
break;
|
|
334
402
|
case "End":
|
|
335
|
-
next = this
|
|
403
|
+
next = this.#safeMax;
|
|
336
404
|
break;
|
|
337
405
|
default:
|
|
338
406
|
return;
|
|
@@ -340,7 +408,6 @@ var SliderController = class extends Controller {
|
|
|
340
408
|
event.preventDefault();
|
|
341
409
|
this.#commit(next);
|
|
342
410
|
}
|
|
343
|
-
/** Begins a pointer drag: sets the value and tracks subsequent movement. */
|
|
344
411
|
onPointerDown(event) {
|
|
345
412
|
if (event.button !== 0 || this.#drag || !this.hasTrackTarget || !this.hasThumbTarget) return;
|
|
346
413
|
const track = this.trackTarget;
|
|
@@ -367,96 +434,109 @@ var SliderController = class extends Controller {
|
|
|
367
434
|
});
|
|
368
435
|
this.#drag = drag;
|
|
369
436
|
}
|
|
370
|
-
/** Maps a pointer X coordinate to a raw value using a stable track snapshot. */
|
|
371
437
|
#valueFromClientX(clientX, mirrored, track) {
|
|
372
438
|
const rect = track.getBoundingClientRect();
|
|
373
439
|
if (rect.width === 0) return null;
|
|
374
440
|
const offset = (clientX - rect.left) / rect.width;
|
|
375
441
|
const fraction = mirrored ? 1 - offset : offset;
|
|
376
|
-
return this
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Stores the normalized value the user moved to, renders it synchronously for
|
|
380
|
-
* responsive input, and reports it as `change` when it differs from the value
|
|
381
|
-
* last published. The comparison is with the value last published, not with
|
|
382
|
-
* the value the move started from, so a page write no repaint has published
|
|
383
|
-
* yet is reported once, as this change, and a move that ends where the value
|
|
384
|
-
* was last published reports nothing. The baseline moves before either report
|
|
385
|
-
* goes out, so the repaint the Value write schedules — and any move a
|
|
386
|
-
* subscriber makes while the report is dispatched — is measured from this
|
|
387
|
-
* value.
|
|
388
|
-
*/
|
|
442
|
+
return this.#safeMin + fraction * (this.#safeMax - this.#safeMin);
|
|
443
|
+
}
|
|
389
444
|
#commit(raw) {
|
|
390
445
|
const value = snapSteppedValue(raw, this.#steppedRange);
|
|
391
446
|
const reported = this.#settled;
|
|
392
447
|
this.#settled = value;
|
|
448
|
+
if (value !== reported) this.#move = this.#moves.record();
|
|
449
|
+
const move = this.#move;
|
|
393
450
|
if (!Object.is(this.valueValue, value)) this.valueValue = value;
|
|
394
451
|
this.#renderValue(value);
|
|
395
452
|
this.#mirrorField(value, true);
|
|
453
|
+
if (!this.#moves.isLatest(move)) return;
|
|
396
454
|
if (value !== reported) this.dispatch("change", { detail: { value } });
|
|
397
455
|
}
|
|
398
|
-
/** Mirrors `value` into the optional form field, reporting only a user's move. */
|
|
399
456
|
#mirrorField(value, notify) {
|
|
400
457
|
if (!this.hasFieldTarget) return;
|
|
401
458
|
if (writeField(this.fieldTarget, String(value)) && notify) commitField(this.fieldTarget);
|
|
402
459
|
}
|
|
403
|
-
/**
|
|
404
|
-
* Reflects the normalized current Value without writing it back. A published
|
|
405
|
-
* value that moved from the last one is reported once as `reconcile`; the
|
|
406
|
-
* field follows without a native `change`.
|
|
407
|
-
*
|
|
408
|
-
* @stimeoRenderRoot
|
|
409
|
-
*/
|
|
410
460
|
#render() {
|
|
411
461
|
const value = this.#currentValue();
|
|
412
462
|
this.#renderValue(value);
|
|
413
463
|
this.#mirrorField(value, false);
|
|
414
464
|
if (value === this.#settled) return;
|
|
415
465
|
this.#settled = value;
|
|
466
|
+
this.#move = this.#moves.record();
|
|
416
467
|
this.dispatch("reconcile", { detail: { value } });
|
|
417
468
|
}
|
|
418
|
-
/** Reflects one normalized value on the current target and CSS output. */
|
|
419
469
|
#renderValue(value) {
|
|
420
470
|
if (this.hasThumbTarget) {
|
|
421
471
|
this.#renderThumb(this.thumbTarget, value);
|
|
422
472
|
}
|
|
423
473
|
this.#renderFraction(value);
|
|
424
474
|
}
|
|
425
|
-
/** Writes only ARIA values that differ, including on a replacement target. */
|
|
426
475
|
#renderThumb(thumb, value) {
|
|
427
476
|
const attributes = {
|
|
428
|
-
"aria-valuemin": String(this
|
|
429
|
-
"aria-valuemax": String(this
|
|
477
|
+
"aria-valuemin": String(this.#safeMin),
|
|
478
|
+
"aria-valuemax": String(this.#safeMax),
|
|
430
479
|
"aria-valuenow": String(value)
|
|
431
480
|
};
|
|
432
481
|
for (const [name, next] of Object.entries(attributes)) {
|
|
433
482
|
if (thumb.getAttribute(name) !== next) thumb.setAttribute(name, next);
|
|
434
483
|
}
|
|
435
484
|
}
|
|
436
|
-
/** Writes the behavior-only positioning hook only when its value changed. */
|
|
437
485
|
#renderFraction(value) {
|
|
438
|
-
const fraction = rangeFraction(value, this
|
|
486
|
+
const fraction = rangeFraction(value, this.#safeMin, this.#safeMax);
|
|
439
487
|
const next = String(fraction);
|
|
440
488
|
if (this.element.style.getPropertyValue(FRACTION_PROPERTY) !== next) {
|
|
441
489
|
this.element.style.setProperty(FRACTION_PROPERTY, next);
|
|
442
490
|
}
|
|
443
491
|
}
|
|
444
|
-
/** Current normalized value derived from the live declarative inputs. */
|
|
445
492
|
#currentValue() {
|
|
446
|
-
return snapSteppedValue(this
|
|
493
|
+
return snapSteppedValue(this.#safeValue, this.#steppedRange);
|
|
447
494
|
}
|
|
448
|
-
/** Shared range configuration; finite endpoints remain allowed off the grid. */
|
|
449
495
|
get #steppedRange() {
|
|
450
|
-
return { min: this
|
|
496
|
+
return { min: this.#safeMin, max: this.#safeMax, step: this.#safeStep };
|
|
451
497
|
}
|
|
452
|
-
/** Ends the current pointer session without dispatching another change. */
|
|
453
498
|
#endDrag() {
|
|
454
499
|
const drag = this.#drag;
|
|
455
500
|
this.#drag = null;
|
|
456
501
|
drag?.pointer?.end();
|
|
457
502
|
}
|
|
503
|
+
get #safeMin() {
|
|
504
|
+
return this.#numbers.read(
|
|
505
|
+
this,
|
|
506
|
+
"min",
|
|
507
|
+
this.minValue,
|
|
508
|
+
_SliderController.values.min.default,
|
|
509
|
+
_SliderController.valueConstraints.min
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
get #safeMax() {
|
|
513
|
+
return this.#numbers.read(
|
|
514
|
+
this,
|
|
515
|
+
"max",
|
|
516
|
+
this.maxValue,
|
|
517
|
+
_SliderController.values.max.default,
|
|
518
|
+
_SliderController.valueConstraints.max
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
get #safeStep() {
|
|
522
|
+
return this.#numbers.read(
|
|
523
|
+
this,
|
|
524
|
+
"step",
|
|
525
|
+
this.stepValue,
|
|
526
|
+
_SliderController.values.step.default,
|
|
527
|
+
_SliderController.valueConstraints.step
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
get #safeValue() {
|
|
531
|
+
return this.#numbers.read(
|
|
532
|
+
this,
|
|
533
|
+
"value",
|
|
534
|
+
this.valueValue,
|
|
535
|
+
this.#safeMin,
|
|
536
|
+
_SliderController.valueConstraints.value
|
|
537
|
+
);
|
|
538
|
+
}
|
|
458
539
|
};
|
|
459
540
|
|
|
460
541
|
export { SliderController };
|
|
461
|
-
//# sourceMappingURL=slider_controller.js.map
|
|
462
542
|
//# sourceMappingURL=slider_controller.js.map
|