stimeo-ui 0.17.0 → 0.18.1
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 +136 -2
- data/README.md +19 -10
- data/dist/cable/index.js +22 -14
- data/dist/controllers/accordion_controller.js +14 -6
- data/dist/controllers/alert_dialog_controller.js +145 -118
- data/dist/controllers/announcer_controller.js +113 -17
- data/dist/controllers/auto_submit_controller.js +185 -60
- data/dist/controllers/avatar_controller.js +55 -43
- data/dist/controllers/bulk_select_controller.js +64 -50
- data/dist/controllers/calendar_controller.js +55 -53
- data/dist/controllers/carousel_controller.js +124 -86
- data/dist/controllers/character_counter_controller.js +291 -95
- data/dist/controllers/checkbox_controller.js +6 -0
- data/dist/controllers/clipboard_controller.js +118 -27
- data/dist/controllers/collapsible_controller.js +52 -49
- data/dist/controllers/color_picker_controller.js +29 -7
- data/dist/controllers/combobox_controller.js +210 -71
- data/dist/controllers/command_palette_controller.js +290 -140
- data/dist/controllers/conditional_fields_controller.js +145 -58
- data/dist/controllers/confirm_controller.js +145 -118
- data/dist/controllers/context_menu_controller.js +138 -73
- data/dist/controllers/countdown_controller.js +109 -21
- data/dist/controllers/currency_input_controller.js +446 -72
- data/dist/controllers/data_grid_controller.js +134 -28
- data/dist/controllers/date_range_picker_controller.js +93 -72
- data/dist/controllers/dialog_controller.js +145 -118
- data/dist/controllers/direct_upload_controller.js +24 -14
- data/dist/controllers/dirty_form_controller.js +68 -31
- data/dist/controllers/dismissible_controller.js +66 -46
- data/dist/controllers/drawer_controller.js +145 -118
- data/dist/controllers/dropdown_controller.js +76 -63
- data/dist/controllers/editable_controller.js +200 -62
- data/dist/controllers/empty_state_controller.js +13 -6
- data/dist/controllers/file_dropzone_controller.js +55 -48
- data/dist/controllers/filter_controller.js +9 -2
- data/dist/controllers/flash_controller.js +66 -33
- data/dist/controllers/focus_controller.js +39 -14
- data/dist/controllers/form_field_controller.js +52 -43
- data/dist/controllers/form_validation_controller.js +18 -11
- data/dist/controllers/frame_loading_controller.js +55 -48
- data/dist/controllers/hover_card_controller.js +67 -61
- data/dist/controllers/idle_controller.js +10 -6
- data/dist/controllers/input_mask_controller.js +434 -24
- data/dist/controllers/intersection_controller.js +3 -0
- data/dist/controllers/lazy_frame_controller.js +15 -3
- data/dist/controllers/listbox_controller.js +260 -79
- data/dist/controllers/local_time_controller.js +48 -13
- data/dist/controllers/masonry_controller.js +11 -4
- data/dist/controllers/menu_controller.js +138 -82
- data/dist/controllers/menubar_controller.js +65 -19
- data/dist/controllers/meter_controller.js +270 -24
- data/dist/controllers/multi_select_controller.js +272 -95
- data/dist/controllers/navigation_menu_controller.js +67 -19
- data/dist/controllers/nested_form_controller.js +98 -64
- data/dist/controllers/network_status_controller.js +70 -52
- data/dist/controllers/number_input_controller.js +344 -94
- data/dist/controllers/optimistic_controller.js +29 -11
- data/dist/controllers/otp_controller.js +502 -104
- data/dist/controllers/overflow_indicator_controller.js +6 -0
- data/dist/controllers/overflow_menu_controller.js +136 -21
- data/dist/controllers/pagination_controller.js +47 -14
- data/dist/controllers/password_reveal_controller.js +52 -49
- data/dist/controllers/password_strength_controller.js +13 -6
- data/dist/controllers/persist_controller.js +48 -128
- data/dist/controllers/pointer_drag_controller.js +255 -24
- data/dist/controllers/popover_controller.js +91 -65
- data/dist/controllers/portal_controller.js +6 -0
- data/dist/controllers/preview_guard_controller.js +14 -3
- data/dist/controllers/progress_controller.js +271 -27
- data/dist/controllers/radio_group_controller.js +167 -80
- data/dist/controllers/range_slider_controller.js +27 -7
- data/dist/controllers/rating_controller.js +93 -57
- data/dist/controllers/read_more_controller.js +10 -6
- data/dist/controllers/reading_progress_controller.js +22 -5
- data/dist/controllers/relative_time_controller.js +75 -11
- data/dist/controllers/reset_on_restore_controller.js +6 -0
- data/dist/controllers/resizable_controller.js +55 -22
- data/dist/controllers/roving_controller.js +10 -4
- data/dist/controllers/scroll_area_controller.js +129 -88
- data/dist/controllers/scroll_restore_controller.js +14 -2
- data/dist/controllers/scroll_visibility_controller.js +93 -60
- data/dist/controllers/scrollspy_controller.js +11 -5
- data/dist/controllers/separator_controller.js +59 -43
- data/dist/controllers/sidebar_controller.js +150 -122
- data/dist/controllers/skeleton_controller.js +55 -48
- data/dist/controllers/slider_controller.js +27 -6
- data/dist/controllers/smart_sticky_header_controller.js +13 -5
- data/dist/controllers/sortable_controller.js +27 -14
- data/dist/controllers/spinner_controller.js +55 -48
- data/dist/controllers/step_indicator_controller.js +6 -0
- data/dist/controllers/stepper_controller.js +6 -0
- data/dist/controllers/stick_to_bottom_controller.js +19 -8
- data/dist/controllers/sticky_observer_controller.js +49 -43
- data/dist/controllers/submit_once_controller.js +145 -85
- data/dist/controllers/switch_controller.js +172 -28
- data/dist/controllers/tabs_controller.js +6 -1
- data/dist/controllers/tags_input_controller.js +157 -28
- data/dist/controllers/textarea_autosize_controller.js +40 -19
- data/dist/controllers/theme_controller.js +10 -4
- data/dist/controllers/time_picker_controller.js +192 -54
- data/dist/controllers/toast_controller.js +58 -27
- data/dist/controllers/toggle_group_controller.js +158 -56
- data/dist/controllers/toolbar_controller.js +150 -21
- data/dist/controllers/tree_view_controller.js +134 -25
- data/dist/index.js +2515 -1315
- data/dist/positioning/index.js +6 -0
- data/lib/generators/stimeo/install/install_generator.rb +7 -2
- data/lib/generators/stimeo/install/templates/stimeo.js +19 -6
- data/lib/stimeo/ui/version.rb +1 -1
- metadata +2 -2
|
@@ -41,6 +41,48 @@ var ListenerSet = class {
|
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
var HoverRecheck = class {
|
|
45
|
+
#document;
|
|
46
|
+
#release;
|
|
47
|
+
#listeners = new ListenerSet();
|
|
48
|
+
#pending = /* @__PURE__ */ new Set();
|
|
49
|
+
#tickets = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
constructor(document2, release) {
|
|
51
|
+
this.#document = document2;
|
|
52
|
+
this.#release = release;
|
|
53
|
+
}
|
|
54
|
+
wait(element) {
|
|
55
|
+
this.#pending.add(element);
|
|
56
|
+
this.#tickets.set(element, /* @__PURE__ */ Symbol());
|
|
57
|
+
this.#listeners.add(this.#document, "pointermove", this.#onPointerMove, {
|
|
58
|
+
capture: true,
|
|
59
|
+
passive: true
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
cancel(element) {
|
|
63
|
+
this.#tickets.delete(element);
|
|
64
|
+
this.#pending.delete(element);
|
|
65
|
+
if (this.#pending.size === 0) this.#listeners.dispose();
|
|
66
|
+
}
|
|
67
|
+
dispose() {
|
|
68
|
+
this.#listeners.dispose();
|
|
69
|
+
this.#pending.clear();
|
|
70
|
+
this.#tickets = /* @__PURE__ */ new WeakMap();
|
|
71
|
+
}
|
|
72
|
+
#onPointerMove = () => {
|
|
73
|
+
this.#listeners.dispose();
|
|
74
|
+
const waiting = [...this.#pending].map(
|
|
75
|
+
(element) => [element, this.#tickets.get(element)]
|
|
76
|
+
);
|
|
77
|
+
this.#pending.clear();
|
|
78
|
+
for (const [element, ticket] of waiting) {
|
|
79
|
+
if (this.#tickets.get(element) !== ticket) continue;
|
|
80
|
+
if (element.matches(":hover")) continue;
|
|
81
|
+
this.#release(element);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
44
86
|
var MicrotaskCoalescer = class {
|
|
45
87
|
#run;
|
|
46
88
|
#queued = false;
|
|
@@ -57,6 +99,9 @@ var MicrotaskCoalescer = class {
|
|
|
57
99
|
this.#queued = false;
|
|
58
100
|
this.#generation += 1;
|
|
59
101
|
}
|
|
102
|
+
get pending() {
|
|
103
|
+
return this.#queued;
|
|
104
|
+
}
|
|
60
105
|
schedule() {
|
|
61
106
|
if (!this.#active || this.#queued) return;
|
|
62
107
|
this.#queued = true;
|
|
@@ -87,6 +132,9 @@ var MorphRenderWatcher = class {
|
|
|
87
132
|
schedule() {
|
|
88
133
|
this.#pass.schedule();
|
|
89
134
|
}
|
|
135
|
+
get pending() {
|
|
136
|
+
return this.#pass.pending;
|
|
137
|
+
}
|
|
90
138
|
disconnect() {
|
|
91
139
|
this.#listeners.dispose();
|
|
92
140
|
this.#pass.cancel();
|
|
@@ -323,10 +371,13 @@ var ToastController = class _ToastController extends Controller {
|
|
|
323
371
|
#phases = /* @__PURE__ */ new WeakMap();
|
|
324
372
|
#reapply = new MorphRenderWatcher(() => this.#reapplyLimit());
|
|
325
373
|
#spared = [];
|
|
326
|
-
#pointer = new
|
|
327
|
-
|
|
374
|
+
#pointer = new HoverRecheck(
|
|
375
|
+
this.element.ownerDocument,
|
|
376
|
+
(item) => this.#release(item, "hover", null)
|
|
377
|
+
);
|
|
328
378
|
#rafHandles = /* @__PURE__ */ new Map();
|
|
329
379
|
#delegatedList = null;
|
|
380
|
+
#listListeners = new ListenerSet();
|
|
330
381
|
#connected = false;
|
|
331
382
|
#arrivals = /* @__PURE__ */ new Set();
|
|
332
383
|
#appliedMax = null;
|
|
@@ -357,7 +408,6 @@ var ToastController = class _ToastController extends Controller {
|
|
|
357
408
|
this.#reapply.disconnect();
|
|
358
409
|
this.#spared = [];
|
|
359
410
|
this.#pointer.dispose();
|
|
360
|
-
this.#awaitingPointer.clear();
|
|
361
411
|
for (const handle of this.#rafHandles.values()) {
|
|
362
412
|
window.cancelAnimationFrame(handle);
|
|
363
413
|
}
|
|
@@ -506,34 +556,18 @@ var ToastController = class _ToastController extends Controller {
|
|
|
506
556
|
}
|
|
507
557
|
#afterMove(item) {
|
|
508
558
|
if (!item.contains(document.activeElement)) this.#release(item, "focus", null);
|
|
509
|
-
if (this.#dismiss.isHeld(item)) this.#
|
|
559
|
+
if (this.#dismiss.isHeld(item)) this.#pointer.wait(item);
|
|
510
560
|
}
|
|
511
561
|
#readHolds(item) {
|
|
512
562
|
if (item.contains(document.activeElement)) this.#dismiss.pause(item, "focus");
|
|
513
563
|
if (!item.matches(":hover")) return;
|
|
514
564
|
this.#dismiss.pause(item, "hover");
|
|
515
|
-
this.#
|
|
565
|
+
this.#pointer.wait(item);
|
|
516
566
|
}
|
|
517
|
-
#awaitPointer(item) {
|
|
518
|
-
this.#awaitingPointer.add(item);
|
|
519
|
-
this.#pointer.add(document, "pointermove", this.#onPointerMove, {
|
|
520
|
-
capture: true,
|
|
521
|
-
passive: true
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
#onPointerMove = () => {
|
|
525
|
-
this.#pointer.dispose();
|
|
526
|
-
const waiting = [...this.#awaitingPointer];
|
|
527
|
-
this.#awaitingPointer.clear();
|
|
528
|
-
for (const item of waiting) {
|
|
529
|
-
if (!item.matches(":hover")) this.#release(item, "hover", null);
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
567
|
#letGo(item) {
|
|
533
568
|
if (this.#dismiss.isHeld(item)) this.#limitLater(null);
|
|
534
569
|
this.#dismiss.clear(item);
|
|
535
|
-
this.#
|
|
536
|
-
if (this.#awaitingPointer.size === 0) this.#pointer.dispose();
|
|
570
|
+
this.#pointer.cancel(item);
|
|
537
571
|
}
|
|
538
572
|
#itemFromSource(source) {
|
|
539
573
|
const target = source.origin ?? source.host;
|
|
@@ -598,14 +632,11 @@ var ToastController = class _ToastController extends Controller {
|
|
|
598
632
|
if (!list) return;
|
|
599
633
|
this.#delegatedList = list;
|
|
600
634
|
for (const type of DELEGATED_EVENTS) {
|
|
601
|
-
this.#
|
|
635
|
+
this.#listListeners.add(list, type, this.#onListEvent);
|
|
602
636
|
}
|
|
603
637
|
}
|
|
604
638
|
#disconnectDelegatedEvents() {
|
|
605
|
-
|
|
606
|
-
for (const type of DELEGATED_EVENTS) {
|
|
607
|
-
this.#delegatedList.removeEventListener(type, this.#onListEvent);
|
|
608
|
-
}
|
|
639
|
+
this.#listListeners.dispose();
|
|
609
640
|
this.#delegatedList = null;
|
|
610
641
|
}
|
|
611
642
|
#onListEvent = (event) => {
|
|
@@ -37,6 +37,107 @@ function isReservedArrowChord(event, allow = []) {
|
|
|
37
37
|
if (!event.key.startsWith("Arrow")) return false;
|
|
38
38
|
return event.altKey && !allow.includes("alt") || event.ctrlKey && !allow.includes("ctrl") || event.metaKey && !allow.includes("meta") || event.shiftKey && !allow.includes("shift");
|
|
39
39
|
}
|
|
40
|
+
function hasModifierChord(event) {
|
|
41
|
+
return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function setAttributeIfChanged(element, name, value, beforeWrite) {
|
|
45
|
+
if (element.getAttribute(name) === value) return false;
|
|
46
|
+
beforeWrite?.();
|
|
47
|
+
if (value === null) element.removeAttribute(name);
|
|
48
|
+
else element.setAttribute(name, value);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
var AuthoredMutationWatcher = class {
|
|
53
|
+
#onAuthored;
|
|
54
|
+
#claims = null;
|
|
55
|
+
#observer = null;
|
|
56
|
+
constructor(onAuthored) {
|
|
57
|
+
this.#onAuthored = onAuthored;
|
|
58
|
+
}
|
|
59
|
+
observe(root, options) {
|
|
60
|
+
this.disconnect();
|
|
61
|
+
const observer = new MutationObserver((records) => {
|
|
62
|
+
if (this.#observer !== observer) return;
|
|
63
|
+
const authored = this.#filter(records);
|
|
64
|
+
if (authored.length > 0) this.#onAuthored(authored);
|
|
65
|
+
});
|
|
66
|
+
this.#observer = observer;
|
|
67
|
+
this.#claims = { attributes: /* @__PURE__ */ new Map(), children: /* @__PURE__ */ new Map() };
|
|
68
|
+
observer.observe(root, {
|
|
69
|
+
attributes: true,
|
|
70
|
+
attributeFilter: [...options.attributes],
|
|
71
|
+
subtree: options.subtree ?? false,
|
|
72
|
+
childList: options.childList ?? false
|
|
73
|
+
});
|
|
74
|
+
if (options.ancestorAttributes) {
|
|
75
|
+
let ancestor = root.parentElement;
|
|
76
|
+
while (ancestor) {
|
|
77
|
+
observer.observe(ancestor, {
|
|
78
|
+
attributes: true,
|
|
79
|
+
attributeFilter: [...options.ancestorAttributes]
|
|
80
|
+
});
|
|
81
|
+
ancestor = ancestor.parentElement;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
claim(target, name, value) {
|
|
86
|
+
const claims = this.#claims?.attributes;
|
|
87
|
+
let attributes = claims?.get(target);
|
|
88
|
+
if (!attributes) {
|
|
89
|
+
attributes = /* @__PURE__ */ new Map();
|
|
90
|
+
claims?.set(target, attributes);
|
|
91
|
+
}
|
|
92
|
+
const pending = attributes.get(name);
|
|
93
|
+
attributes.set(name, { value, count: (pending?.count ?? 0) + 1 });
|
|
94
|
+
}
|
|
95
|
+
claimCurrent(target, name) {
|
|
96
|
+
this.claim(target, name, target.getAttribute(name));
|
|
97
|
+
}
|
|
98
|
+
claimChildList(target, added, removed) {
|
|
99
|
+
const claims = this.#claims?.children;
|
|
100
|
+
const pending = claims?.get(target) ?? { added: /* @__PURE__ */ new Map(), removed: /* @__PURE__ */ new Map() };
|
|
101
|
+
for (const node of added) pending.added.set(node, (pending.added.get(node) ?? 0) + 1);
|
|
102
|
+
for (const node of removed) pending.removed.set(node, (pending.removed.get(node) ?? 0) + 1);
|
|
103
|
+
claims?.set(target, pending);
|
|
104
|
+
}
|
|
105
|
+
take() {
|
|
106
|
+
return this.#filter(this.#observer?.takeRecords() ?? []);
|
|
107
|
+
}
|
|
108
|
+
disconnect() {
|
|
109
|
+
this.#observer?.disconnect();
|
|
110
|
+
this.#observer = null;
|
|
111
|
+
this.#claims = null;
|
|
112
|
+
}
|
|
113
|
+
#filter(records) {
|
|
114
|
+
const authored = records.filter((record) => !this.#consume(record));
|
|
115
|
+
this.#claims?.attributes.clear();
|
|
116
|
+
this.#claims?.children.clear();
|
|
117
|
+
return authored;
|
|
118
|
+
}
|
|
119
|
+
#consume(record) {
|
|
120
|
+
if (record.type === "attributes") {
|
|
121
|
+
const target = record.target;
|
|
122
|
+
const pending2 = this.#claims?.attributes.get(target)?.get(record.attributeName);
|
|
123
|
+
if (!pending2 || pending2.count === 0 || target.getAttribute(record.attributeName) !== pending2.value) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
pending2.count -= 1;
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
const pending = this.#claims?.children.get(record.target);
|
|
130
|
+
if (!pending) return false;
|
|
131
|
+
const added = [...record.addedNodes];
|
|
132
|
+
const removed = [...record.removedNodes];
|
|
133
|
+
if (added.some((node) => !pending.added.get(node)) || removed.some((node) => !pending.removed.get(node))) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
for (const node of added) pending.added.set(node, (pending.added.get(node) ?? 0) - 1);
|
|
137
|
+
for (const node of removed) pending.removed.set(node, (pending.removed.get(node) ?? 0) - 1);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
40
141
|
|
|
41
142
|
function ownerIndex(candidates, node) {
|
|
42
143
|
if (!(node instanceof Node)) return -1;
|
|
@@ -121,6 +222,9 @@ var MicrotaskCoalescer = class {
|
|
|
121
222
|
this.#queued = false;
|
|
122
223
|
this.#generation += 1;
|
|
123
224
|
}
|
|
225
|
+
get pending() {
|
|
226
|
+
return this.#queued;
|
|
227
|
+
}
|
|
124
228
|
schedule() {
|
|
125
229
|
if (!this.#active || this.#queued) return;
|
|
126
230
|
this.#queued = true;
|
|
@@ -151,6 +255,9 @@ var MorphRenderWatcher = class {
|
|
|
151
255
|
schedule() {
|
|
152
256
|
this.#pass.schedule();
|
|
153
257
|
}
|
|
258
|
+
get pending() {
|
|
259
|
+
return this.#pass.pending;
|
|
260
|
+
}
|
|
154
261
|
disconnect() {
|
|
155
262
|
this.#listeners.dispose();
|
|
156
263
|
this.#pass.cancel();
|
|
@@ -206,9 +313,9 @@ var ITEM_ATTRIBUTES = [
|
|
|
206
313
|
"contenteditable",
|
|
207
314
|
"controls"
|
|
208
315
|
];
|
|
209
|
-
var hasModifier = (event) => event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
210
316
|
var ToggleGroupController = class extends Controller {
|
|
211
317
|
#moves = new MoveCounter();
|
|
318
|
+
#connectionGeneration = 0;
|
|
212
319
|
static targets = ["item", "fields"];
|
|
213
320
|
static values = {
|
|
214
321
|
mode: { type: String, default: "multiple" },
|
|
@@ -221,13 +328,17 @@ var ToggleGroupController = class extends Controller {
|
|
|
221
328
|
#handledEvents = /* @__PURE__ */ new WeakSet();
|
|
222
329
|
#managedItems = /* @__PURE__ */ new Set();
|
|
223
330
|
#originalTabindex = /* @__PURE__ */ new WeakMap();
|
|
224
|
-
#ownedPressed = /* @__PURE__ */ new
|
|
225
|
-
#internalPressedValues = /* @__PURE__ */ new Map();
|
|
331
|
+
#ownedPressed = /* @__PURE__ */ new Map();
|
|
226
332
|
#pass = new MorphRenderWatcher(() => this.#reconcileDom());
|
|
227
|
-
#observer =
|
|
333
|
+
#observer = new AuthoredMutationWatcher((records) => {
|
|
334
|
+
this.#releaseAuthoredPressed(records);
|
|
335
|
+
this.#pass.schedule();
|
|
336
|
+
});
|
|
228
337
|
#connected = false;
|
|
229
338
|
#committedValues = [];
|
|
339
|
+
#listeners = new ListenerSet();
|
|
230
340
|
connect() {
|
|
341
|
+
this.#releaseDefaultsRewrittenWhileAway();
|
|
231
342
|
const currentItems = new Set(this.itemTargets);
|
|
232
343
|
for (const item of this.#managedItems) {
|
|
233
344
|
if (!currentItems.has(item)) this.#releaseItem(item);
|
|
@@ -241,26 +352,21 @@ var ToggleGroupController = class extends Controller {
|
|
|
241
352
|
this.#ensureTabStop(preferred);
|
|
242
353
|
this.#mirrorFields(false);
|
|
243
354
|
this.#committedValues = this.#pressedValues();
|
|
244
|
-
this.element
|
|
245
|
-
this.element
|
|
246
|
-
this.element
|
|
247
|
-
this.element
|
|
248
|
-
this.element
|
|
355
|
+
this.#listeners.add(this.element, "click", this.#onClickCapture, { capture: true });
|
|
356
|
+
this.#listeners.add(this.element, "keydown", this.#onKeydownCapture, { capture: true });
|
|
357
|
+
this.#listeners.add(this.element, "click", this.#onClick);
|
|
358
|
+
this.#listeners.add(this.element, "keydown", this.#onKeydown);
|
|
359
|
+
this.#listeners.add(this.element, "focusin", this.#onFocusin);
|
|
249
360
|
this.#connected = true;
|
|
250
|
-
this.#internalPressedValues.clear();
|
|
251
361
|
this.#pass.observe(this.element);
|
|
252
362
|
this.#observeMutations();
|
|
253
363
|
}
|
|
254
364
|
disconnect() {
|
|
365
|
+
this.#connectionGeneration += 1;
|
|
255
366
|
this.#connected = false;
|
|
256
367
|
this.#pass.disconnect();
|
|
257
|
-
this.
|
|
258
|
-
this.
|
|
259
|
-
this.element.removeEventListener("click", this.#onClick);
|
|
260
|
-
this.element.removeEventListener("keydown", this.#onKeydown);
|
|
261
|
-
this.element.removeEventListener("focusin", this.#onFocusin);
|
|
262
|
-
this.#observer?.disconnect();
|
|
263
|
-
this.#observer = null;
|
|
368
|
+
this.#listeners.dispose();
|
|
369
|
+
this.#observer.disconnect();
|
|
264
370
|
}
|
|
265
371
|
itemTargetConnected(item) {
|
|
266
372
|
if (!this.#connected) return;
|
|
@@ -327,7 +433,7 @@ var ToggleGroupController = class extends Controller {
|
|
|
327
433
|
if (event.defaultPrevented || !this.#isSupportedHost(item)) return;
|
|
328
434
|
if (event.isComposing) return;
|
|
329
435
|
if (isReservedArrowChord(event)) return;
|
|
330
|
-
if ((event.key === "Home" || event.key === "End") &&
|
|
436
|
+
if ((event.key === "Home" || event.key === "End") && hasModifierChord(event)) return;
|
|
331
437
|
if (!this.#managedItems.has(item)) this.#reconcileHost(item, true);
|
|
332
438
|
this.#ensureTabStop();
|
|
333
439
|
const items = this.#managedTargets;
|
|
@@ -363,6 +469,7 @@ var ToggleGroupController = class extends Controller {
|
|
|
363
469
|
}
|
|
364
470
|
#toggleItem(item, reason = "user") {
|
|
365
471
|
if (!this.#isSupportedHost(item) || this.#isActivationDisabled(item)) return;
|
|
472
|
+
const generation = this.#connectionGeneration;
|
|
366
473
|
if (!this.#managedItems.has(item)) this.#reconcileHost(item, true);
|
|
367
474
|
const willPress = !this.#isPressed(item);
|
|
368
475
|
if (this.modeValue === "single") {
|
|
@@ -382,7 +489,7 @@ var ToggleGroupController = class extends Controller {
|
|
|
382
489
|
}
|
|
383
490
|
const token = this.#moves.record();
|
|
384
491
|
this.#mirrorFields(true);
|
|
385
|
-
if (!this.#moves.isLatest(token)) return;
|
|
492
|
+
if (generation !== this.#connectionGeneration || !this.#moves.isLatest(token)) return;
|
|
386
493
|
this.dispatch("change", {
|
|
387
494
|
detail: { value: this.#itemValue(item), pressed: willPress, values: [...values], reason }
|
|
388
495
|
});
|
|
@@ -390,22 +497,21 @@ var ToggleGroupController = class extends Controller {
|
|
|
390
497
|
#mirrorFields(notify) {
|
|
391
498
|
if (!this.hasFieldsTarget) return;
|
|
392
499
|
const options = { name: this.nameValue, form: this.formValue };
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
500
|
+
const removed = [...this.fieldsTarget.childNodes];
|
|
501
|
+
const changed = writeFields(this.fieldsTarget, this.#pressedValues(), options);
|
|
502
|
+
if (changed)
|
|
503
|
+
this.#observer.claimChildList(this.fieldsTarget, [...this.fieldsTarget.childNodes], removed);
|
|
504
|
+
if (changed && notify) commitField(this.fieldsTarget);
|
|
396
505
|
}
|
|
397
506
|
#reconcileDom() {
|
|
398
|
-
|
|
399
|
-
if (observer) {
|
|
400
|
-
this.#releaseAuthoredPressed(observer.takeRecords());
|
|
401
|
-
observer.disconnect();
|
|
402
|
-
}
|
|
507
|
+
this.#releaseAuthoredPressed(this.#observer.take());
|
|
403
508
|
for (const item of this.itemTargets) this.#reconcileHost(item, true);
|
|
404
509
|
this.#normalizeSelection();
|
|
405
510
|
this.#ensureTabStop();
|
|
406
511
|
this.#mirrorFields(false);
|
|
407
|
-
this.#
|
|
408
|
-
|
|
512
|
+
const authored = this.#observer.take();
|
|
513
|
+
this.#releaseAuthoredPressed(authored);
|
|
514
|
+
if (authored.length > 0) this.#pass.schedule();
|
|
409
515
|
this.#reportMove();
|
|
410
516
|
}
|
|
411
517
|
#reportMove() {
|
|
@@ -434,16 +540,15 @@ var ToggleGroupController = class extends Controller {
|
|
|
434
540
|
const original = this.#originalTabindex.get(item);
|
|
435
541
|
if (original === null) item.removeAttribute("tabindex");
|
|
436
542
|
else if (original !== void 0) item.setAttribute("tabindex", original);
|
|
437
|
-
if (this.#ownedPressed.delete(item)) item
|
|
543
|
+
if (this.#ownedPressed.delete(item)) this.#writePressed(item, null);
|
|
438
544
|
}
|
|
439
545
|
#normalizePressed(item) {
|
|
440
546
|
const value = item.getAttribute("aria-pressed");
|
|
441
547
|
if (value === null) {
|
|
442
|
-
this.#ownedPressed.
|
|
443
|
-
this.#
|
|
444
|
-
item.setAttribute("aria-pressed", "false");
|
|
548
|
+
this.#ownedPressed.set(item, "false");
|
|
549
|
+
this.#writePressed(item, "false");
|
|
445
550
|
} else if (value !== "true" && value !== "false") {
|
|
446
|
-
item
|
|
551
|
+
this.#writePressed(item, "false");
|
|
447
552
|
}
|
|
448
553
|
}
|
|
449
554
|
#normalizeSelection() {
|
|
@@ -521,34 +626,23 @@ var ToggleGroupController = class extends Controller {
|
|
|
521
626
|
if (record.attributeName !== "aria-pressed") continue;
|
|
522
627
|
const item = record.target;
|
|
523
628
|
const value = item.getAttribute("aria-pressed");
|
|
524
|
-
if (value !== null
|
|
629
|
+
if (value !== null) {
|
|
525
630
|
this.#ownedPressed.delete(item);
|
|
526
631
|
}
|
|
527
632
|
}
|
|
528
|
-
this.#internalPressedValues.clear();
|
|
529
633
|
}
|
|
530
634
|
#observeMutations() {
|
|
531
|
-
|
|
532
|
-
this.#releaseAuthoredPressed(records);
|
|
533
|
-
this.#pass.schedule();
|
|
534
|
-
});
|
|
535
|
-
this.#observer = observer;
|
|
536
|
-
this.#observeWith(observer);
|
|
537
|
-
}
|
|
538
|
-
#observeWith(observer) {
|
|
539
|
-
observer.observe(this.element, {
|
|
635
|
+
this.#observer.observe(this.element, {
|
|
540
636
|
subtree: true,
|
|
541
637
|
childList: true,
|
|
542
|
-
attributes:
|
|
543
|
-
|
|
638
|
+
attributes: ITEM_ATTRIBUTES,
|
|
639
|
+
ancestorAttributes: ["contenteditable", "disabled"]
|
|
544
640
|
});
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
});
|
|
551
|
-
ancestor = ancestor.parentElement;
|
|
641
|
+
}
|
|
642
|
+
#releaseDefaultsRewrittenWhileAway() {
|
|
643
|
+
for (const [item, written] of this.#ownedPressed) {
|
|
644
|
+
const current = item.getAttribute("aria-pressed");
|
|
645
|
+
if (current !== null && current !== written) this.#ownedPressed.delete(item);
|
|
552
646
|
}
|
|
553
647
|
}
|
|
554
648
|
get #managedTargets() {
|
|
@@ -562,8 +656,8 @@ var ToggleGroupController = class extends Controller {
|
|
|
562
656
|
}
|
|
563
657
|
#setPressed(item, pressed) {
|
|
564
658
|
const value = pressed ? "true" : "false";
|
|
565
|
-
this.#
|
|
566
|
-
item
|
|
659
|
+
if (this.#ownedPressed.has(item)) this.#ownedPressed.set(item, value);
|
|
660
|
+
this.#writePressed(item, value);
|
|
567
661
|
}
|
|
568
662
|
#pressedValues() {
|
|
569
663
|
return this.#managedTargets.filter((item) => this.#isPressed(item)).map((item) => this.#itemValue(item));
|
|
@@ -571,6 +665,14 @@ var ToggleGroupController = class extends Controller {
|
|
|
571
665
|
#itemValue(item) {
|
|
572
666
|
return item.getAttribute("data-value") ?? "";
|
|
573
667
|
}
|
|
668
|
+
#writePressed(item, value) {
|
|
669
|
+
setAttributeIfChanged(
|
|
670
|
+
item,
|
|
671
|
+
"aria-pressed",
|
|
672
|
+
value,
|
|
673
|
+
() => this.#observer.claim(item, "aria-pressed", value)
|
|
674
|
+
);
|
|
675
|
+
}
|
|
574
676
|
};
|
|
575
677
|
|
|
576
678
|
export { ToggleGroupController };
|