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,121 +1,264 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
var ListenerSet = class {
|
|
4
|
+
#abort = new AbortController();
|
|
5
|
+
add(target, type, handler, options) {
|
|
6
|
+
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
7
|
+
}
|
|
8
|
+
dispose() {
|
|
9
|
+
this.#abort.abort();
|
|
10
|
+
this.#abort = new AbortController();
|
|
11
|
+
}
|
|
12
|
+
};
|
|
4
13
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
};
|
|
13
|
-
#rewind;
|
|
14
|
-
/** @param rewind - the pass that returns this controller's state to its initial form. */
|
|
15
|
-
constructor(rewind) {
|
|
16
|
-
this.#rewind = rewind;
|
|
14
|
+
var MicrotaskCoalescer = class {
|
|
15
|
+
#run;
|
|
16
|
+
#queued = false;
|
|
17
|
+
#active = false;
|
|
18
|
+
#generation = 0;
|
|
19
|
+
constructor(run) {
|
|
20
|
+
this.#run = run;
|
|
17
21
|
}
|
|
18
|
-
/** Subscribes to `turbo:before-cache`; call from `connect()`. Idempotent. */
|
|
19
22
|
activate() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
this.#active = true;
|
|
24
|
+
}
|
|
25
|
+
cancel() {
|
|
26
|
+
this.#active = false;
|
|
27
|
+
this.#queued = false;
|
|
28
|
+
this.#generation += 1;
|
|
25
29
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
schedule() {
|
|
31
|
+
if (!this.#active || this.#queued) return;
|
|
32
|
+
this.#queued = true;
|
|
33
|
+
const generation = this.#generation;
|
|
34
|
+
queueMicrotask(() => {
|
|
35
|
+
if (generation !== this.#generation || !this.#queued || !this.#active) return;
|
|
36
|
+
this.#queued = false;
|
|
37
|
+
this.#run();
|
|
38
|
+
});
|
|
31
39
|
}
|
|
32
40
|
};
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
var MorphRenderWatcher = class {
|
|
43
|
+
#listeners = new ListenerSet();
|
|
44
|
+
#pass;
|
|
45
|
+
#element = null;
|
|
46
|
+
#onMorph = () => this.#pass.schedule();
|
|
47
|
+
constructor(run) {
|
|
48
|
+
this.#pass = new MicrotaskCoalescer(run);
|
|
49
|
+
}
|
|
50
|
+
observe(element) {
|
|
51
|
+
if (this.#element === element) return;
|
|
52
|
+
this.disconnect();
|
|
53
|
+
this.#element = element;
|
|
54
|
+
this.#pass.activate();
|
|
55
|
+
this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
|
|
56
|
+
}
|
|
57
|
+
schedule() {
|
|
58
|
+
this.#pass.schedule();
|
|
59
|
+
}
|
|
60
|
+
disconnect() {
|
|
61
|
+
this.#listeners.dispose();
|
|
62
|
+
this.#pass.cancel();
|
|
63
|
+
this.#element = null;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function sharedRegistry(key, create) {
|
|
68
|
+
const symbol = Symbol.for(key);
|
|
69
|
+
const scope = globalThis;
|
|
70
|
+
const existing = scope[symbol];
|
|
71
|
+
if (existing !== void 0) return existing;
|
|
72
|
+
const registry = create();
|
|
73
|
+
Object.defineProperty(globalThis, symbol, { value: registry });
|
|
74
|
+
return registry;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
var StylePropertyLease = class _StylePropertyLease {
|
|
78
|
+
static #registry = sharedRegistry(
|
|
79
|
+
"stimeo-ui.style-property-lease.registry.v1",
|
|
80
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
|
|
81
|
+
);
|
|
36
82
|
#property;
|
|
37
|
-
#
|
|
38
|
-
|
|
39
|
-
constructor(property) {
|
|
83
|
+
#record;
|
|
84
|
+
#held = /* @__PURE__ */ new Set();
|
|
85
|
+
constructor(property, owner) {
|
|
40
86
|
this.#property = property;
|
|
87
|
+
this.#record = `data-${owner}-style-${property}-lease`;
|
|
88
|
+
const names = _StylePropertyLease.#registry.names;
|
|
89
|
+
names.set(property, (names.get(property) ?? /* @__PURE__ */ new Set()).add(this.#record));
|
|
41
90
|
}
|
|
42
|
-
/** Writes or removes the leased declaration while preserving its authored value. */
|
|
43
91
|
write(element, value, priority = "") {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
writtenValue: value,
|
|
53
|
-
writtenPriority: value === null ? "" : priority
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
this.#reflect(element, value, priority);
|
|
92
|
+
const stack = this.#stack(element);
|
|
93
|
+
const hold = this.#take(stack) ?? this.#acquire(element, stack);
|
|
94
|
+
this.#held.add(element);
|
|
95
|
+
const shows = !this.#covered(element, stack, hold);
|
|
96
|
+
hold.writtenValue = value;
|
|
97
|
+
hold.writtenPriority = value === null ? "" : priority;
|
|
98
|
+
this.#mark(element, stack);
|
|
99
|
+
if (shows) this.#show(element, value, hold.writtenPriority);
|
|
57
100
|
}
|
|
58
|
-
/** Returns one lease without overwriting a later consumer declaration. */
|
|
59
101
|
return(element) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
this.#
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
102
|
+
const held = this.#held.delete(element);
|
|
103
|
+
const known = _StylePropertyLease.#registry.stacks.get(element)?.has(this.#property);
|
|
104
|
+
const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
|
|
105
|
+
const hold = this.#take(stack);
|
|
106
|
+
if (!hold) return;
|
|
107
|
+
const owns = this.#carries(element, hold) && !this.#covered(element, stack, hold);
|
|
108
|
+
const index = stack.indexOf(hold);
|
|
109
|
+
stack.splice(index, 1);
|
|
110
|
+
const above = stack[index];
|
|
111
|
+
if (above) above.linked &&= hold.linked;
|
|
112
|
+
this.#mark(element, stack);
|
|
113
|
+
if (!owns) return;
|
|
114
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
115
|
+
if (below) this.#show(element, below.writtenValue, below.writtenPriority);
|
|
116
|
+
else this.#show(element, hold.originalValue, hold.originalPriority);
|
|
68
117
|
}
|
|
69
|
-
/** Returns every outstanding declaration lease. */
|
|
70
118
|
returnAll() {
|
|
71
|
-
for (const element of Array.from(this.#
|
|
119
|
+
for (const element of Array.from(this.#held)) this.return(element);
|
|
120
|
+
}
|
|
121
|
+
#recorded(element, name) {
|
|
122
|
+
try {
|
|
123
|
+
const parsed = JSON.parse(element.getAttribute(name) ?? "null");
|
|
124
|
+
if (!Array.isArray(parsed)) return null;
|
|
125
|
+
const [originalValue, originalPriority, writtenValue, writtenPriority, ...rest] = parsed;
|
|
126
|
+
if (typeof originalValue !== "string" || typeof originalPriority !== "string") return null;
|
|
127
|
+
if (typeof writtenValue !== "string" && writtenValue !== null) return null;
|
|
128
|
+
if (typeof writtenPriority !== "string") return null;
|
|
129
|
+
const linked = rest[0] !== false;
|
|
130
|
+
const beneath = linked ? rest : rest.slice(1);
|
|
131
|
+
if (!beneath.every((under) => typeof under === "string")) return null;
|
|
132
|
+
return { originalValue, originalPriority, writtenValue, writtenPriority, linked, beneath };
|
|
133
|
+
} catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
72
136
|
}
|
|
73
|
-
|
|
74
|
-
|
|
137
|
+
#stack(element) {
|
|
138
|
+
const stacks = _StylePropertyLease.#registry.stacks;
|
|
139
|
+
const byProperty = stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
140
|
+
stacks.set(element, byProperty);
|
|
141
|
+
const stack = byProperty.get(this.#property) ?? this.#seed(element);
|
|
142
|
+
byProperty.set(this.#property, stack);
|
|
143
|
+
return stack;
|
|
144
|
+
}
|
|
145
|
+
#seed(element) {
|
|
146
|
+
const found = [];
|
|
147
|
+
for (const record of _StylePropertyLease.#registry.names.get(this.#property) ?? []) {
|
|
148
|
+
const read = this.#recorded(element, record);
|
|
149
|
+
if (read) found.push({ ...read, record });
|
|
150
|
+
}
|
|
151
|
+
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
152
|
+
return found.sort((one, other) => depth(one) - depth(other)).map((entry, index) => ({
|
|
153
|
+
lease: null,
|
|
154
|
+
record: entry.record,
|
|
155
|
+
writtenValue: entry.writtenValue,
|
|
156
|
+
writtenPriority: entry.writtenPriority,
|
|
157
|
+
originalValue: entry.originalValue,
|
|
158
|
+
originalPriority: entry.originalPriority,
|
|
159
|
+
linked: entry.linked && index > 0
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
#take(stack) {
|
|
163
|
+
const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
|
|
164
|
+
if (hold) hold.lease = this;
|
|
165
|
+
return hold;
|
|
166
|
+
}
|
|
167
|
+
#acquire(element, stack) {
|
|
168
|
+
const top = stack.at(-1);
|
|
169
|
+
const over = top && this.#carries(element, top) ? top : void 0;
|
|
75
170
|
const style = element.style;
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
171
|
+
const hold = {
|
|
172
|
+
lease: this,
|
|
173
|
+
record: this.#record,
|
|
174
|
+
writtenValue: null,
|
|
175
|
+
writtenPriority: "",
|
|
176
|
+
originalValue: over ? over.originalValue : style.getPropertyValue(this.#property),
|
|
177
|
+
originalPriority: over ? over.originalPriority : style.getPropertyPriority(this.#property),
|
|
178
|
+
linked: over !== void 0
|
|
179
|
+
};
|
|
180
|
+
stack.push(hold);
|
|
181
|
+
return hold;
|
|
182
|
+
}
|
|
183
|
+
#covered(element, stack, hold) {
|
|
184
|
+
return stack.slice(stack.indexOf(hold) + 1).some((above) => this.#carries(element, above));
|
|
185
|
+
}
|
|
186
|
+
#mark(element, stack) {
|
|
187
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
188
|
+
stack.forEach((hold, index) => {
|
|
189
|
+
const names = stack.slice(0, index).map((under) => under.record);
|
|
190
|
+
const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
|
|
191
|
+
const marker = hold.linked || beneath.length === 0 ? [] : [false];
|
|
192
|
+
const { originalValue, originalPriority, writtenValue, writtenPriority } = hold;
|
|
193
|
+
records.set(
|
|
194
|
+
hold.record,
|
|
195
|
+
(writtenValue ?? "") === originalValue && writtenPriority === originalPriority && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([
|
|
196
|
+
originalValue,
|
|
197
|
+
originalPriority,
|
|
198
|
+
writtenValue,
|
|
199
|
+
writtenPriority,
|
|
200
|
+
...marker,
|
|
201
|
+
...beneath
|
|
202
|
+
])
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
for (const [name, recorded] of records) {
|
|
206
|
+
if (element.getAttribute(name) === recorded) continue;
|
|
207
|
+
if (recorded === null) element.removeAttribute(name);
|
|
208
|
+
else element.setAttribute(name, recorded);
|
|
80
209
|
}
|
|
81
|
-
|
|
82
|
-
|
|
210
|
+
}
|
|
211
|
+
#carries(element, hold) {
|
|
212
|
+
return this.#holds(element, hold.writtenValue ?? "", hold.writtenPriority);
|
|
213
|
+
}
|
|
214
|
+
#holds(element, value, priority) {
|
|
215
|
+
const style = element.style;
|
|
216
|
+
return style.getPropertyValue(this.#property) === value && style.getPropertyPriority(this.#property) === priority;
|
|
217
|
+
}
|
|
218
|
+
#show(element, value, priority) {
|
|
219
|
+
if (this.#holds(element, value ?? "", priority)) return;
|
|
220
|
+
if (value === null) element.style.removeProperty(this.#property);
|
|
221
|
+
else element.style.setProperty(this.#property, value, priority);
|
|
83
222
|
}
|
|
84
223
|
};
|
|
85
224
|
|
|
86
|
-
// src/utils/transient_hooks.ts
|
|
87
225
|
var TransientHooks = class {
|
|
88
226
|
#attributes;
|
|
89
227
|
constructor(options) {
|
|
90
228
|
this.#attributes = options.attributes;
|
|
91
229
|
}
|
|
92
|
-
/** Drops the declared hooks from `element`; what it carries besides stays. */
|
|
93
230
|
reset(element) {
|
|
94
231
|
for (const attribute of this.#attributes) element.removeAttribute(attribute);
|
|
95
232
|
}
|
|
96
233
|
};
|
|
97
234
|
|
|
98
|
-
// src/controllers/preview_guard_controller.ts
|
|
99
235
|
var TRANSIENT = new TransientHooks({ attributes: ["data-preview-hidden"] });
|
|
236
|
+
var CONTENT_RECORD = "content";
|
|
100
237
|
var PreviewGuardController = class extends Controller {
|
|
101
238
|
static values = {
|
|
102
239
|
placeholder: { type: String, default: "" }
|
|
103
240
|
};
|
|
104
241
|
static events = ["hide", "show"];
|
|
105
|
-
#visibility = new StylePropertyLease("visibility");
|
|
106
|
-
#beforeCache = new BeforeCacheReset(() => this.#restore());
|
|
242
|
+
#visibility = new StylePropertyLease("visibility", this.identifier);
|
|
107
243
|
#observer = null;
|
|
108
244
|
#connected = false;
|
|
109
245
|
#hidden = false;
|
|
110
|
-
/** Child nodes a placeholder displaced; non-null marks that content — not visibility — was swapped. */
|
|
111
246
|
#savedNodes = null;
|
|
112
|
-
/** The descendant that held focus when the guard went up, so show can hand it back. */
|
|
113
247
|
#focused = null;
|
|
248
|
+
#morphRender = new MorphRenderWatcher(() => {
|
|
249
|
+
this.#sync();
|
|
250
|
+
if (this.#hidden) this.#reguard();
|
|
251
|
+
});
|
|
114
252
|
connect() {
|
|
253
|
+
this.#morphRender.observe(this.element);
|
|
115
254
|
this.#connected = true;
|
|
116
|
-
if (this.#hidden)
|
|
117
|
-
|
|
118
|
-
|
|
255
|
+
if (this.#hidden) {
|
|
256
|
+
this.#reguard();
|
|
257
|
+
} else {
|
|
258
|
+
if (this.element.hasAttribute("data-preview-hidden")) this.#restoreRecordedContent();
|
|
259
|
+
this.#visibility.return(this.element);
|
|
260
|
+
TRANSIENT.reset(this.element);
|
|
261
|
+
}
|
|
119
262
|
if (typeof MutationObserver !== "undefined") {
|
|
120
263
|
this.#observer = new MutationObserver(() => this.#sync());
|
|
121
264
|
this.#observer.observe(document.documentElement, {
|
|
@@ -126,24 +269,15 @@ var PreviewGuardController = class extends Controller {
|
|
|
126
269
|
this.#sync();
|
|
127
270
|
}
|
|
128
271
|
disconnect() {
|
|
272
|
+
this.#morphRender.disconnect();
|
|
129
273
|
this.#connected = false;
|
|
130
|
-
this.#beforeCache.deactivate();
|
|
131
274
|
this.#observer?.disconnect();
|
|
132
275
|
this.#observer = null;
|
|
133
276
|
}
|
|
134
|
-
/**
|
|
135
|
-
* Re-guards to match a `placeholder` changed at runtime — the value is the content on
|
|
136
|
-
* display while the guard is up, so a morph that swaps it must not leave the old one.
|
|
137
|
-
*/
|
|
138
277
|
placeholderValueChanged() {
|
|
139
278
|
if (!this.#connected || !this.#hidden) return;
|
|
140
279
|
this.#reguard();
|
|
141
280
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Reflects the current `data-turbo-preview` state onto the element.
|
|
144
|
-
*
|
|
145
|
-
* @stimeoRenderRoot
|
|
146
|
-
*/
|
|
147
281
|
#sync() {
|
|
148
282
|
const previewing = document.documentElement.hasAttribute("data-turbo-preview");
|
|
149
283
|
if (previewing && !this.#hidden) this.#hide();
|
|
@@ -154,30 +288,33 @@ var PreviewGuardController = class extends Controller {
|
|
|
154
288
|
this.#applyGuard();
|
|
155
289
|
this.dispatch("hide", { detail: {} });
|
|
156
290
|
}
|
|
157
|
-
/** Puts the guard up in the form the current `placeholder` calls for. */
|
|
158
291
|
#applyGuard() {
|
|
159
292
|
this.#hidden = true;
|
|
160
293
|
if (this.placeholderValue === "") {
|
|
161
294
|
this.#visibility.write(this.element, "hidden");
|
|
162
295
|
} else {
|
|
296
|
+
this.element.setAttribute(this.#contentRecord, JSON.stringify(this.element.innerHTML));
|
|
163
297
|
this.#savedNodes = document.createDocumentFragment();
|
|
164
298
|
this.#savedNodes.append(...this.element.childNodes);
|
|
165
299
|
this.element.textContent = this.placeholderValue;
|
|
166
300
|
}
|
|
167
301
|
this.element.setAttribute("data-preview-hidden", "true");
|
|
168
302
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
303
|
+
get #contentRecord() {
|
|
304
|
+
return `data-${this.identifier}-${CONTENT_RECORD}`;
|
|
305
|
+
}
|
|
306
|
+
#restoreRecordedContent() {
|
|
307
|
+
const raw = this.element.getAttribute(this.#contentRecord) ?? "null";
|
|
308
|
+
this.element.removeAttribute(this.#contentRecord);
|
|
309
|
+
let content = null;
|
|
310
|
+
try {
|
|
311
|
+
content = JSON.parse(raw);
|
|
312
|
+
} catch {
|
|
313
|
+
}
|
|
314
|
+
if (typeof content === "string") this.element.innerHTML = content;
|
|
315
|
+
}
|
|
180
316
|
#reguard() {
|
|
317
|
+
this.element.setAttribute("data-preview-hidden", "true");
|
|
181
318
|
if (this.#savedNodes && this.placeholderValue !== "") {
|
|
182
319
|
this.element.textContent = this.placeholderValue;
|
|
183
320
|
return;
|
|
@@ -191,46 +328,26 @@ var PreviewGuardController = class extends Controller {
|
|
|
191
328
|
this.#restore();
|
|
192
329
|
this.dispatch("show", { detail: {} });
|
|
193
330
|
}
|
|
194
|
-
/** Reverts the guard and hands focus back. Used by show and by the snapshot rewind. */
|
|
195
331
|
#restore() {
|
|
196
332
|
this.#revert();
|
|
197
333
|
this.#refocus();
|
|
198
334
|
}
|
|
199
|
-
/**
|
|
200
|
-
* Puts the element back the way the guard found it.
|
|
201
|
-
*
|
|
202
|
-
* Every step is a no-op on an element this controller never guarded: the lease returns
|
|
203
|
-
* only declarations it recorded, and the hook is removed whether or not it is there.
|
|
204
|
-
*/
|
|
205
335
|
#revert() {
|
|
206
336
|
this.#hidden = false;
|
|
207
337
|
if (this.#savedNodes) {
|
|
208
338
|
this.element.textContent = "";
|
|
209
339
|
this.element.append(this.#savedNodes);
|
|
210
340
|
this.#savedNodes = null;
|
|
341
|
+
this.element.removeAttribute(this.#contentRecord);
|
|
211
342
|
} else {
|
|
212
343
|
this.#visibility.return(this.element);
|
|
213
344
|
}
|
|
214
345
|
this.element.removeAttribute("data-preview-hidden");
|
|
215
346
|
}
|
|
216
|
-
/**
|
|
217
|
-
* The focused element the guard is about to make unfocusable, if any.
|
|
218
|
-
*
|
|
219
|
-
* The element itself counts as well as its descendants: guarding takes focus either way
|
|
220
|
-
* — a `visibility: hidden` subtree cannot hold it, and a placeholder displaces the nodes
|
|
221
|
-
* outright — so the browser drops focus to `<body>` the moment the guard goes up.
|
|
222
|
-
*/
|
|
223
347
|
#focusedInside() {
|
|
224
348
|
const active = document.activeElement;
|
|
225
349
|
return active instanceof HTMLElement && this.element.contains(active) ? active : null;
|
|
226
350
|
}
|
|
227
|
-
/**
|
|
228
|
-
* Hands focus back to the element the guard took it from.
|
|
229
|
-
*
|
|
230
|
-
* Only when that element is still in the document and focus has not moved on since —
|
|
231
|
-
* anything else is the user's or another controller's, and putting it back would be
|
|
232
|
-
* taking it.
|
|
233
|
-
*/
|
|
234
351
|
#refocus() {
|
|
235
352
|
const target = this.#focused;
|
|
236
353
|
this.#focused = null;
|
|
@@ -240,5 +357,4 @@ var PreviewGuardController = class extends Controller {
|
|
|
240
357
|
};
|
|
241
358
|
|
|
242
359
|
export { PreviewGuardController };
|
|
243
|
-
//# sourceMappingURL=preview_guard_controller.js.map
|
|
244
360
|
//# sourceMappingURL=preview_guard_controller.js.map
|