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,78 +1,110 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
static
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
/** Subscribes to `turbo:before-cache`; call from `connect()`. Idempotent. */
|
|
19
|
-
activate() {
|
|
20
|
-
const first = _BeforeCacheReset.#subscribers.size === 0;
|
|
21
|
-
_BeforeCacheReset.#subscribers.add(this);
|
|
22
|
-
if (first) {
|
|
23
|
-
document.addEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
|
|
3
|
+
var DetachGate = class _DetachGate {
|
|
4
|
+
#pending = false;
|
|
5
|
+
get pending() {
|
|
6
|
+
return this.#pending;
|
|
7
|
+
}
|
|
8
|
+
static isDetached(host) {
|
|
9
|
+
return !host.element.isConnected || !_DetachGate.#listed(host);
|
|
10
|
+
}
|
|
11
|
+
disconnected(host, teardown) {
|
|
12
|
+
const carried = _DetachGate.#carried(host);
|
|
13
|
+
if (!carried && _DetachGate.isDetached(host)) {
|
|
14
|
+
this.#pending = false;
|
|
15
|
+
teardown();
|
|
16
|
+
return;
|
|
24
17
|
}
|
|
18
|
+
this.#pending = true;
|
|
19
|
+
const probe = () => {
|
|
20
|
+
if (!this.#pending) return;
|
|
21
|
+
this.#pending = false;
|
|
22
|
+
teardown();
|
|
23
|
+
};
|
|
24
|
+
if (carried) setTimeout(probe, 0);
|
|
25
|
+
else queueMicrotask(probe);
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
static #carried(host) {
|
|
28
|
+
const element = host.element;
|
|
29
|
+
return !element.isConnected && element.closest("[data-turbo-permanent]") !== null && _DetachGate.#listed(host);
|
|
30
|
+
}
|
|
31
|
+
static #listed(host) {
|
|
32
|
+
const tokens = (host.element.getAttribute("data-controller") ?? "").split(/\s+/);
|
|
33
|
+
return tokens.includes(host.identifier);
|
|
34
|
+
}
|
|
35
|
+
cancel() {
|
|
36
|
+
this.#pending = false;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
41
|
+
|
|
42
|
+
var NUMBER_BOUNDS = {
|
|
43
|
+
timer: { finite: true, min: 0, max: MAX_TIMER_DELAY_MS }};
|
|
44
|
+
function matchesNumberBounds(value, bounds) {
|
|
45
|
+
if (!Number.isFinite(value)) {
|
|
46
|
+
const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
|
|
47
|
+
if (direction === null) return false;
|
|
48
|
+
if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
|
|
49
|
+
}
|
|
50
|
+
if (bounds.min !== void 0 && value < bounds.min) return false;
|
|
51
|
+
if (bounds.max !== void 0 && value > bounds.max) return false;
|
|
52
|
+
if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
|
|
53
|
+
if (bounds.integer && !Number.isInteger(value)) return false;
|
|
54
|
+
if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readNumber(raw, fallback, bounds) {
|
|
59
|
+
return matchesNumberBounds(raw, bounds) ? raw : fallback;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
var NumberValueReader = class {
|
|
63
|
+
#lastRejected = /* @__PURE__ */ new Map();
|
|
64
|
+
read(owner, name, raw, fallback, bounds) {
|
|
65
|
+
const resolved = readNumber(raw, fallback, bounds);
|
|
66
|
+
if (matchesNumberBounds(raw, bounds)) {
|
|
67
|
+
this.#lastRejected.delete(name);
|
|
68
|
+
return resolved;
|
|
69
|
+
}
|
|
70
|
+
const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
|
|
71
|
+
const literal = owner.element.getAttribute(attribute);
|
|
72
|
+
if (literal === null) {
|
|
73
|
+
this.#lastRejected.delete(name);
|
|
74
|
+
return resolved;
|
|
75
|
+
}
|
|
76
|
+
if (this.#lastRejected.get(name) !== literal) {
|
|
77
|
+
this.#lastRejected.set(name, literal);
|
|
78
|
+
console.warn(
|
|
79
|
+
`Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
return resolved;
|
|
31
83
|
}
|
|
32
84
|
};
|
|
33
85
|
|
|
34
|
-
// src/utils/reduced_motion.ts
|
|
35
86
|
function prefersReducedMotion() {
|
|
36
87
|
return typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
37
88
|
}
|
|
38
89
|
|
|
39
|
-
// src/utils/safe_timeout.ts
|
|
40
90
|
var TimerRegistry = class {
|
|
41
|
-
/** Live timer ids that have not yet been cleared (or, for timeouts, fired). */
|
|
42
91
|
ids = /* @__PURE__ */ new Set();
|
|
43
|
-
/**
|
|
44
|
-
* Cancels a single tracked timer.
|
|
45
|
-
*
|
|
46
|
-
* No-ops if the id is unknown (already cleared, fired, or never owned by this
|
|
47
|
-
* registry), so callers can clear defensively without guarding.
|
|
48
|
-
*/
|
|
49
92
|
clear(id) {
|
|
50
93
|
if (this.ids.delete(id)) {
|
|
51
94
|
this.cancel(id);
|
|
52
95
|
}
|
|
53
96
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Cancels every tracked timer. Call this from a controller's `disconnect()`
|
|
56
|
-
* to guarantee no timer outlives the element.
|
|
57
|
-
*/
|
|
58
97
|
clearAll() {
|
|
59
98
|
for (const id of this.ids) {
|
|
60
99
|
this.cancel(id);
|
|
61
100
|
}
|
|
62
101
|
this.ids.clear();
|
|
63
102
|
}
|
|
64
|
-
/** Number of timers currently tracked (pending). */
|
|
65
103
|
get size() {
|
|
66
104
|
return this.ids.size;
|
|
67
105
|
}
|
|
68
106
|
};
|
|
69
107
|
var SafeTimeout = class extends TimerRegistry {
|
|
70
|
-
/**
|
|
71
|
-
* Schedules `callback` after `delay` ms and returns the timer id.
|
|
72
|
-
*
|
|
73
|
-
* The id is removed from the registry automatically when the timeout fires,
|
|
74
|
-
* so {@link TimerRegistry.size | size} reflects only still-pending timers.
|
|
75
|
-
*/
|
|
76
108
|
set(callback, delay) {
|
|
77
109
|
const id = this.schedule(() => {
|
|
78
110
|
this.ids.delete(id);
|
|
@@ -89,7 +121,6 @@ var SafeTimeout = class extends TimerRegistry {
|
|
|
89
121
|
}
|
|
90
122
|
};
|
|
91
123
|
|
|
92
|
-
// src/utils/transition_completion.ts
|
|
93
124
|
function timeMs(value) {
|
|
94
125
|
const trimmed = value.trim();
|
|
95
126
|
const amount = Number.parseFloat(trimmed);
|
|
@@ -125,13 +156,6 @@ var TransitionCompletion = class {
|
|
|
125
156
|
#complete = null;
|
|
126
157
|
#pendingProperties = null;
|
|
127
158
|
#deadline = 0;
|
|
128
|
-
/**
|
|
129
|
-
* Replaces any prior wait and invokes `complete` synchronously for a 0ms
|
|
130
|
-
* transition (including when `getComputedStyle` is unavailable).
|
|
131
|
-
*
|
|
132
|
-
* With a positive `options.timeoutMs` the synchronous fast-path is skipped and
|
|
133
|
-
* the override replaces the auto-computed fallback (see {@link TransitionWaitOptions}).
|
|
134
|
-
*/
|
|
135
159
|
wait(element, complete, options = {}) {
|
|
136
160
|
this.cancel();
|
|
137
161
|
const requested = options.timeoutMs ?? 0;
|
|
@@ -151,18 +175,10 @@ var TransitionCompletion = class {
|
|
|
151
175
|
element.addEventListener("transitioncancel", this.#onTerminal);
|
|
152
176
|
this.#timers.set(() => this.#finish(), override > 0 ? override : maximum + 50);
|
|
153
177
|
}
|
|
154
|
-
/** Cancels the pending wait without invoking its completion callback. */
|
|
155
178
|
cancel() {
|
|
156
179
|
this.#complete = null;
|
|
157
180
|
this.#teardown();
|
|
158
181
|
}
|
|
159
|
-
/**
|
|
160
|
-
* Handles terminal events from the observed element only.
|
|
161
|
-
*
|
|
162
|
-
* For explicit property lists, every declared positive-time property must
|
|
163
|
-
* settle. For `all`, no reliable property set exists, so an event can finish
|
|
164
|
-
* only after the computed maximum time; the safety timeout owns the usual path.
|
|
165
|
-
*/
|
|
166
182
|
#onTerminal = (event) => {
|
|
167
183
|
if (event.target !== this.#element) return;
|
|
168
184
|
const transitionEvent = event;
|
|
@@ -182,10 +198,6 @@ var TransitionCompletion = class {
|
|
|
182
198
|
}
|
|
183
199
|
if (Date.now() >= this.#deadline) this.#finish();
|
|
184
200
|
};
|
|
185
|
-
/**
|
|
186
|
-
* Returns active CSS transition properties expanded to the names reported by
|
|
187
|
-
* terminal events. CSS animations and pseudo-element effects are excluded.
|
|
188
|
-
*/
|
|
189
201
|
#activeTransitionProperties(element) {
|
|
190
202
|
if (!element || typeof element.getAnimations !== "function") return /* @__PURE__ */ new Set();
|
|
191
203
|
try {
|
|
@@ -203,7 +215,6 @@ var TransitionCompletion = class {
|
|
|
203
215
|
return /* @__PURE__ */ new Set();
|
|
204
216
|
}
|
|
205
217
|
}
|
|
206
|
-
/** Returns explicit positive-time properties, or `null` for the ambiguous `all`. */
|
|
207
218
|
#explicitPendingProperties(timings) {
|
|
208
219
|
if (timings.some(({ property }) => property === "all")) return null;
|
|
209
220
|
const pending = new Set(
|
|
@@ -211,7 +222,6 @@ var TransitionCompletion = class {
|
|
|
211
222
|
);
|
|
212
223
|
return pending.size > 0 ? pending : null;
|
|
213
224
|
}
|
|
214
|
-
/** Completes exactly once, releasing listeners and the fallback before the callback. */
|
|
215
225
|
#finish() {
|
|
216
226
|
const complete = this.#complete;
|
|
217
227
|
if (!complete) return;
|
|
@@ -219,7 +229,6 @@ var TransitionCompletion = class {
|
|
|
219
229
|
this.#teardown();
|
|
220
230
|
complete();
|
|
221
231
|
}
|
|
222
|
-
/** Releases the exact element listeners and timer owned by the current wait. */
|
|
223
232
|
#teardown() {
|
|
224
233
|
this.#timers.clearAll();
|
|
225
234
|
this.#element?.removeEventListener("transitionend", this.#onTerminal);
|
|
@@ -230,9 +239,10 @@ var TransitionCompletion = class {
|
|
|
230
239
|
}
|
|
231
240
|
};
|
|
232
241
|
|
|
233
|
-
// src/controllers/transition_controller.ts
|
|
234
242
|
var tokensOf = (value) => value.split(/\s+/).filter(Boolean);
|
|
235
|
-
var
|
|
243
|
+
var STAGED_RECORD = "staged";
|
|
244
|
+
var TransitionController = class _TransitionController extends Controller {
|
|
245
|
+
#numbers = new NumberValueReader();
|
|
236
246
|
static values = {
|
|
237
247
|
enter: { type: String, default: "" },
|
|
238
248
|
enterFrom: { type: String, default: "" },
|
|
@@ -242,45 +252,56 @@ var TransitionController = class extends Controller {
|
|
|
242
252
|
leaveTo: { type: String, default: "" },
|
|
243
253
|
timeout: { type: Number, default: 0 }
|
|
244
254
|
};
|
|
255
|
+
static valueConstraints = {
|
|
256
|
+
timeout: NUMBER_BOUNDS.timer
|
|
257
|
+
};
|
|
245
258
|
static actions = ["enter", "leave", "toggle"];
|
|
246
259
|
static events = ["entered", "left"];
|
|
247
|
-
/** Owns the cancellable completion wait (terminal events + bounded fallback). */
|
|
248
260
|
#transition = new TransitionCompletion();
|
|
249
|
-
/** Rewinds a half-applied stage before Turbo copies the page into its snapshot. */
|
|
250
|
-
#beforeCache = new BeforeCacheReset(() => this.#rewindForCache());
|
|
251
261
|
#rafId = null;
|
|
252
|
-
/**
|
|
253
|
-
* Stage classes this controller put on the element. Removing by declaration
|
|
254
|
-
* instead would take a token the consumer also authored, and would strand the
|
|
255
|
-
* token that was applied when a Value changes mid-transition.
|
|
256
|
-
*/
|
|
257
262
|
#staged = /* @__PURE__ */ new Set();
|
|
263
|
+
#gate = new DetachGate();
|
|
258
264
|
connect() {
|
|
259
|
-
this.#
|
|
265
|
+
const moved = this.#gate.pending;
|
|
266
|
+
this.#gate.cancel();
|
|
267
|
+
if (moved) return;
|
|
268
|
+
if (this.#staged.size === 0) this.#stripRecorded();
|
|
260
269
|
this.#settleState();
|
|
261
270
|
}
|
|
262
271
|
disconnect() {
|
|
263
|
-
this.#
|
|
264
|
-
|
|
272
|
+
this.#gate.disconnected(this, () => this.#cancel());
|
|
273
|
+
}
|
|
274
|
+
get #stagedRecord() {
|
|
275
|
+
return `data-${this.identifier}-${STAGED_RECORD}`;
|
|
276
|
+
}
|
|
277
|
+
#stripRecorded() {
|
|
278
|
+
const raw = this.element.getAttribute(this.#stagedRecord) ?? "null";
|
|
279
|
+
this.element.removeAttribute(this.#stagedRecord);
|
|
280
|
+
let recorded = null;
|
|
281
|
+
try {
|
|
282
|
+
recorded = JSON.parse(raw);
|
|
283
|
+
} catch {
|
|
284
|
+
}
|
|
285
|
+
if (!Array.isArray(recorded)) return;
|
|
286
|
+
for (const token of recorded) {
|
|
287
|
+
if (typeof token === "string" && token !== "") this.element.classList.remove(token);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
#record() {
|
|
291
|
+
if (this.#staged.size === 0) this.element.removeAttribute(this.#stagedRecord);
|
|
292
|
+
else this.element.setAttribute(this.#stagedRecord, JSON.stringify([...this.#staged]));
|
|
265
293
|
}
|
|
266
|
-
/** Shows the element with the enter transition. */
|
|
267
294
|
enter() {
|
|
268
295
|
this.#run("enter");
|
|
269
296
|
}
|
|
270
|
-
/** Hides the element with the leave transition. */
|
|
271
297
|
leave() {
|
|
272
298
|
this.#run("leave");
|
|
273
299
|
}
|
|
274
|
-
/** Reverses the current direction (enter when hidden/leaving, else leave). */
|
|
275
300
|
toggle() {
|
|
276
301
|
const state = this.element.getAttribute("data-transition-state");
|
|
277
302
|
if (state === "entered" || state === "entering") this.leave();
|
|
278
303
|
else this.enter();
|
|
279
304
|
}
|
|
280
|
-
/**
|
|
281
|
-
* @stimeoRuntimeOnly The class lists and `timeout` shape this one transition; `#finish` strips
|
|
282
|
-
* the classes, so none of them stays at rest.
|
|
283
|
-
*/
|
|
284
305
|
#run(kind) {
|
|
285
306
|
this.#cancel();
|
|
286
307
|
const isEnter = kind === "enter";
|
|
@@ -293,18 +314,16 @@ var TransitionController = class extends Controller {
|
|
|
293
314
|
const base = isEnter ? this.enterValue : this.leaveValue;
|
|
294
315
|
const from = isEnter ? this.enterFromValue : this.leaveFromValue;
|
|
295
316
|
const to = isEnter ? this.enterToValue : this.leaveToValue;
|
|
317
|
+
const timeoutMs = this.#safeTimeout;
|
|
296
318
|
this.#add(base, from);
|
|
297
319
|
void this.element.offsetWidth;
|
|
298
320
|
this.#rafId = this.#raf(() => {
|
|
299
321
|
this.#rafId = null;
|
|
300
322
|
this.#remove(from);
|
|
301
323
|
this.#add(to);
|
|
302
|
-
this.#transition.wait(this.element, () => this.#finish(kind), {
|
|
303
|
-
timeoutMs: this.timeoutValue
|
|
304
|
-
});
|
|
324
|
+
this.#transition.wait(this.element, () => this.#finish(kind), { timeoutMs });
|
|
305
325
|
});
|
|
306
326
|
}
|
|
307
|
-
/** Settles the element into the completed state, clearing the stage classes. */
|
|
308
327
|
#finish(kind) {
|
|
309
328
|
this.#strip();
|
|
310
329
|
if (kind === "enter") {
|
|
@@ -316,22 +335,9 @@ var TransitionController = class extends Controller {
|
|
|
316
335
|
this.dispatch("left", { detail: {} });
|
|
317
336
|
}
|
|
318
337
|
}
|
|
319
|
-
/** Writes the state hook the element's visibility implies. */
|
|
320
338
|
#settleState() {
|
|
321
339
|
this.element.setAttribute("data-transition-state", this.element.hidden ? "left" : "entered");
|
|
322
340
|
}
|
|
323
|
-
/**
|
|
324
|
-
* Returns the element to a settled state before Turbo copies the page.
|
|
325
|
-
*
|
|
326
|
-
* The snapshot is taken while the controller is still connected, so stripping on
|
|
327
|
-
* the next `connect()` would only repair the page after it has been painted from
|
|
328
|
-
* the cache. The pass is silent: `connect()` derives the state again on restore.
|
|
329
|
-
*/
|
|
330
|
-
#rewindForCache() {
|
|
331
|
-
this.#cancel();
|
|
332
|
-
this.#settleState();
|
|
333
|
-
}
|
|
334
|
-
/** Cancels any in-flight transition (interruption / teardown). */
|
|
335
341
|
#cancel() {
|
|
336
342
|
if (this.#rafId !== null) {
|
|
337
343
|
this.#cancelRaf(this.#rafId);
|
|
@@ -340,34 +346,24 @@ var TransitionController = class extends Controller {
|
|
|
340
346
|
this.#transition.cancel();
|
|
341
347
|
this.#strip();
|
|
342
348
|
}
|
|
343
|
-
/**
|
|
344
|
-
* Applies the stage tokens this controller does not already find on the
|
|
345
|
-
* element, and claims exactly those.
|
|
346
|
-
*
|
|
347
|
-
* A token already on the element is left unclaimed: it is either the consumer's
|
|
348
|
-
* standing class or one an earlier stage of this transition already claimed, and
|
|
349
|
-
* in neither case may this call take ownership of it. That is what keeps a
|
|
350
|
-
* standing class the consumer also named as a stage Value; the cost is that such
|
|
351
|
-
* a token cannot be staged, so the property it drives resolves from their CSS.
|
|
352
|
-
*/
|
|
353
349
|
#add(...lists) {
|
|
354
350
|
for (const token of lists.flatMap(tokensOf)) {
|
|
355
351
|
if (this.element.classList.contains(token)) continue;
|
|
356
352
|
this.element.classList.add(token);
|
|
357
353
|
this.#staged.add(token);
|
|
358
354
|
}
|
|
355
|
+
this.#record();
|
|
359
356
|
}
|
|
360
|
-
/** Drops the named tokens that are this controller's to drop. */
|
|
361
357
|
#remove(...lists) {
|
|
362
358
|
for (const token of lists.flatMap(tokensOf)) {
|
|
363
359
|
if (!this.#staged.delete(token)) continue;
|
|
364
360
|
this.element.classList.remove(token);
|
|
365
361
|
}
|
|
366
362
|
}
|
|
367
|
-
/** Removes every stage class this controller applied, so none lingers. */
|
|
368
363
|
#strip() {
|
|
369
364
|
this.element.classList.remove(...this.#staged);
|
|
370
365
|
this.#staged.clear();
|
|
366
|
+
this.#record();
|
|
371
367
|
}
|
|
372
368
|
#raf(callback) {
|
|
373
369
|
if (typeof window.requestAnimationFrame === "function") {
|
|
@@ -379,8 +375,16 @@ var TransitionController = class extends Controller {
|
|
|
379
375
|
if (typeof window.cancelAnimationFrame === "function") window.cancelAnimationFrame(id);
|
|
380
376
|
else window.clearTimeout(id);
|
|
381
377
|
}
|
|
378
|
+
get #safeTimeout() {
|
|
379
|
+
return this.#numbers.read(
|
|
380
|
+
this,
|
|
381
|
+
"timeout",
|
|
382
|
+
this.timeoutValue,
|
|
383
|
+
_TransitionController.values.timeout.default,
|
|
384
|
+
_TransitionController.valueConstraints.timeout
|
|
385
|
+
);
|
|
386
|
+
}
|
|
382
387
|
};
|
|
383
388
|
|
|
384
389
|
export { TransitionController };
|
|
385
|
-
//# sourceMappingURL=transition_controller.js.map
|
|
386
390
|
//# sourceMappingURL=transition_controller.js.map
|