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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/README.md +8 -1
  4. data/dist/cable/index.js +363 -436
  5. data/dist/controllers/accordion_controller.js +166 -55
  6. data/dist/controllers/alert_dialog_controller.js +862 -221
  7. data/dist/controllers/announcer_controller.js +135 -198
  8. data/dist/controllers/aspect_ratio_controller.js +0 -10
  9. data/dist/controllers/auto_submit_controller.js +271 -127
  10. data/dist/controllers/avatar_controller.js +171 -105
  11. data/dist/controllers/breadcrumb_controller.js +0 -130
  12. data/dist/controllers/bulk_select_controller.js +262 -52
  13. data/dist/controllers/calendar_controller.js +175 -209
  14. data/dist/controllers/carousel_controller.js +461 -399
  15. data/dist/controllers/character_counter_controller.js +246 -156
  16. data/dist/controllers/checkbox_controller.js +32 -74
  17. data/dist/controllers/clipboard_controller.js +168 -147
  18. data/dist/controllers/collapsible_controller.js +301 -120
  19. data/dist/controllers/color_picker_controller.js +149 -139
  20. data/dist/controllers/combobox_controller.js +360 -133
  21. data/dist/controllers/command_palette_controller.js +970 -358
  22. data/dist/controllers/conditional_fields_controller.js +166 -124
  23. data/dist/controllers/confirm_controller.js +939 -248
  24. data/dist/controllers/context_menu_controller.js +256 -128
  25. data/dist/controllers/count_up_controller.js +73 -21
  26. data/dist/controllers/countdown_controller.js +183 -148
  27. data/dist/controllers/currency_input_controller.js +134 -158
  28. data/dist/controllers/data_grid_controller.js +114 -186
  29. data/dist/controllers/date_range_picker_controller.js +288 -206
  30. data/dist/controllers/dialog_controller.js +858 -223
  31. data/dist/controllers/direct_upload_controller.js +73 -153
  32. data/dist/controllers/dirty_form_controller.js +14 -48
  33. data/dist/controllers/dismissible_controller.js +175 -21
  34. data/dist/controllers/drawer_controller.js +933 -341
  35. data/dist/controllers/dropdown_controller.js +312 -82
  36. data/dist/controllers/editable_controller.js +158 -68
  37. data/dist/controllers/empty_state_controller.js +67 -53
  38. data/dist/controllers/file_dropzone_controller.js +311 -207
  39. data/dist/controllers/filter_controller.js +67 -39
  40. data/dist/controllers/flash_controller.js +172 -314
  41. data/dist/controllers/focus_controller.js +654 -240
  42. data/dist/controllers/form_field_controller.js +147 -132
  43. data/dist/controllers/form_validation_controller.js +13 -86
  44. data/dist/controllers/frame_loading_controller.js +264 -213
  45. data/dist/controllers/highlight_controller.js +107 -75
  46. data/dist/controllers/hover_card_controller.js +309 -118
  47. data/dist/controllers/idle_controller.js +267 -101
  48. data/dist/controllers/input_mask_controller.js +71 -72
  49. data/dist/controllers/intersection_controller.js +147 -106
  50. data/dist/controllers/lazy_frame_controller.js +9 -65
  51. data/dist/controllers/listbox_controller.js +306 -204
  52. data/dist/controllers/local_time_controller.js +54 -64
  53. data/dist/controllers/masonry_controller.js +70 -93
  54. data/dist/controllers/menu_controller.js +214 -156
  55. data/dist/controllers/menubar_controller.js +170 -329
  56. data/dist/controllers/meter_controller.js +151 -67
  57. data/dist/controllers/multi_select_controller.js +593 -358
  58. data/dist/controllers/navigation_menu_controller.js +124 -232
  59. data/dist/controllers/nested_form_controller.js +352 -182
  60. data/dist/controllers/network_status_controller.js +242 -54
  61. data/dist/controllers/number_input_controller.js +320 -263
  62. data/dist/controllers/optimistic_controller.js +16 -76
  63. data/dist/controllers/otp_controller.js +198 -193
  64. data/dist/controllers/overflow_indicator_controller.js +116 -113
  65. data/dist/controllers/overflow_menu_controller.js +343 -283
  66. data/dist/controllers/pagination_controller.js +295 -119
  67. data/dist/controllers/password_reveal_controller.js +389 -121
  68. data/dist/controllers/password_strength_controller.js +99 -153
  69. data/dist/controllers/persist_controller.js +237 -103
  70. data/dist/controllers/pointer_drag_controller.js +185 -165
  71. data/dist/controllers/popover_controller.js +236 -97
  72. data/dist/controllers/portal_controller.js +209 -76
  73. data/dist/controllers/preview_guard_controller.js +232 -116
  74. data/dist/controllers/progress_controller.js +125 -56
  75. data/dist/controllers/radio_group_controller.js +117 -137
  76. data/dist/controllers/range_slider_controller.js +192 -105
  77. data/dist/controllers/rating_controller.js +418 -207
  78. data/dist/controllers/read_more_controller.js +134 -63
  79. data/dist/controllers/reading_progress_controller.js +147 -135
  80. data/dist/controllers/relative_time_controller.js +145 -110
  81. data/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +97 -38
  82. data/dist/controllers/resizable_controller.js +255 -139
  83. data/dist/controllers/roving_controller.js +39 -84
  84. data/dist/controllers/scroll_area_controller.js +428 -225
  85. data/dist/controllers/scroll_restore_controller.js +0 -53
  86. data/dist/controllers/scroll_visibility_controller.js +395 -145
  87. data/dist/controllers/scrollspy_controller.js +181 -242
  88. data/dist/controllers/separator_controller.js +267 -140
  89. data/dist/controllers/sidebar_controller.js +1023 -386
  90. data/dist/controllers/skeleton_controller.js +248 -97
  91. data/dist/controllers/slider_controller.js +159 -79
  92. data/dist/controllers/smart_sticky_header_controller.js +162 -63
  93. data/dist/controllers/sortable_controller.js +0 -112
  94. data/dist/controllers/spinner_controller.js +277 -169
  95. data/dist/controllers/step_indicator_controller.js +99 -46
  96. data/dist/controllers/stepper_controller.js +114 -73
  97. data/dist/controllers/stick_to_bottom_controller.js +262 -138
  98. data/dist/controllers/sticky_observer_controller.js +214 -49
  99. data/dist/controllers/submit_once_controller.js +294 -205
  100. data/dist/controllers/switch_controller.js +33 -60
  101. data/dist/controllers/tabs_controller.js +35 -29
  102. data/dist/controllers/tags_input_controller.js +136 -145
  103. data/dist/controllers/textarea_autosize_controller.js +71 -58
  104. data/dist/controllers/theme_controller.js +130 -112
  105. data/dist/controllers/time_picker_controller.js +146 -80
  106. data/dist/controllers/toast_controller.js +186 -297
  107. data/dist/controllers/toggle_group_controller.js +95 -136
  108. data/dist/controllers/toolbar_controller.js +68 -98
  109. data/dist/controllers/tooltip_controller.js +158 -124
  110. data/dist/controllers/transition_controller.js +123 -119
  111. data/dist/controllers/tree_view_controller.js +150 -345
  112. data/dist/index.js +6370 -9346
  113. data/dist/positioning/index.js +148 -47
  114. data/lib/stimeo/ui/version.rb +1 -1
  115. 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
- // src/utils/microtask_coalescer.ts
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
- // src/utils/owned_pointer_session.ts
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
- /** Collapses a morph that swaps several render Values into one repaint. */
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.activate();
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.cancel();
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
- /** Drops the stale focus owner while allowing a live track gesture to continue. */
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.valueValue;
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.minValue;
400
+ next = this.#safeMin;
333
401
  break;
334
402
  case "End":
335
- next = this.maxValue;
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.minValue + fraction * (this.maxValue - this.minValue);
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.minValue),
429
- "aria-valuemax": String(this.maxValue),
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.minValue, this.maxValue);
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.valueValue, this.#steppedRange);
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.minValue, max: this.maxValue, step: this.stepValue };
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