stimeo-ui 0.16.0 → 0.18.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.
- package/CHANGELOG.md +136 -0
- package/README.md +27 -11
- package/dist/cable/index.d.ts +88 -31
- package/dist/cable/index.js +384 -449
- package/dist/cable/index.js.map +1 -1
- package/dist/coerce-JtZVNG5h.d.ts +20 -0
- package/dist/controllers/accordion_controller.d.ts +4 -2
- package/dist/controllers/accordion_controller.js +174 -55
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.d.ts +12 -2
- package/dist/controllers/alert_dialog_controller.js +903 -235
- package/dist/controllers/alert_dialog_controller.js.map +1 -1
- package/dist/controllers/announcer_controller.d.ts +37 -5
- package/dist/controllers/announcer_controller.js +238 -205
- package/dist/controllers/announcer_controller.js.map +1 -1
- package/dist/controllers/aspect_ratio_controller.js +0 -10
- package/dist/controllers/aspect_ratio_controller.js.map +1 -1
- package/dist/controllers/auto_submit_controller.d.ts +30 -6
- package/dist/controllers/auto_submit_controller.js +414 -145
- package/dist/controllers/auto_submit_controller.js.map +1 -1
- package/dist/controllers/avatar_controller.js +185 -107
- package/dist/controllers/avatar_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.js +0 -130
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/bulk_select_controller.d.ts +21 -3
- package/dist/controllers/bulk_select_controller.js +282 -58
- package/dist/controllers/bulk_select_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +38 -16
- package/dist/controllers/calendar_controller.js +228 -260
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +43 -12
- package/dist/controllers/carousel_controller.js +536 -436
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/character_counter_controller.d.ts +44 -7
- package/dist/controllers/character_counter_controller.js +493 -207
- package/dist/controllers/character_counter_controller.js.map +1 -1
- package/dist/controllers/checkbox_controller.d.ts +7 -2
- package/dist/controllers/checkbox_controller.js +38 -74
- package/dist/controllers/checkbox_controller.js.map +1 -1
- package/dist/controllers/clipboard_controller.d.ts +16 -5
- package/dist/controllers/clipboard_controller.js +261 -149
- package/dist/controllers/clipboard_controller.js.map +1 -1
- package/dist/controllers/collapsible_controller.d.ts +17 -5
- package/dist/controllers/collapsible_controller.js +304 -120
- package/dist/controllers/collapsible_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.d.ts +18 -6
- package/dist/controllers/color_picker_controller.js +178 -146
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.d.ts +24 -6
- package/dist/controllers/combobox_controller.js +522 -156
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +51 -20
- package/dist/controllers/command_palette_controller.js +1156 -395
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/conditional_fields_controller.d.ts +15 -2
- package/dist/controllers/conditional_fields_controller.js +300 -171
- package/dist/controllers/conditional_fields_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.d.ts +49 -12
- package/dist/controllers/confirm_controller.js +980 -262
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +80 -18
- package/dist/controllers/context_menu_controller.js +346 -153
- package/dist/controllers/context_menu_controller.js.map +1 -1
- package/dist/controllers/count_up_controller.d.ts +13 -1
- package/dist/controllers/count_up_controller.js +73 -21
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/countdown_controller.d.ts +47 -3
- package/dist/controllers/countdown_controller.js +281 -158
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +93 -10
- package/dist/controllers/currency_input_controller.js +575 -225
- package/dist/controllers/currency_input_controller.js.map +1 -1
- package/dist/controllers/data_grid_controller.d.ts +25 -12
- package/dist/controllers/data_grid_controller.js +248 -214
- package/dist/controllers/data_grid_controller.js.map +1 -1
- package/dist/controllers/date_range_picker_controller.d.ts +42 -14
- package/dist/controllers/date_range_picker_controller.js +338 -235
- package/dist/controllers/date_range_picker_controller.js.map +1 -1
- package/dist/controllers/dialog_controller.d.ts +17 -6
- package/dist/controllers/dialog_controller.js +899 -237
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.d.ts +25 -8
- package/dist/controllers/direct_upload_controller.js +97 -167
- package/dist/controllers/direct_upload_controller.js.map +1 -1
- package/dist/controllers/dirty_form_controller.d.ts +6 -1
- package/dist/controllers/dirty_form_controller.js +72 -69
- package/dist/controllers/dirty_form_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.d.ts +19 -0
- package/dist/controllers/dismissible_controller.js +196 -24
- package/dist/controllers/dismissible_controller.js.map +1 -1
- package/dist/controllers/drawer_controller.d.ts +39 -11
- package/dist/controllers/drawer_controller.js +974 -355
- package/dist/controllers/drawer_controller.js.map +1 -1
- package/dist/controllers/dropdown_controller.d.ts +31 -1
- package/dist/controllers/dropdown_controller.js +339 -96
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.d.ts +12 -1
- package/dist/controllers/editable_controller.js +315 -88
- package/dist/controllers/editable_controller.js.map +1 -1
- package/dist/controllers/empty_state_controller.js +79 -58
- package/dist/controllers/empty_state_controller.js.map +1 -1
- package/dist/controllers/file_dropzone_controller.d.ts +63 -18
- package/dist/controllers/file_dropzone_controller.js +322 -211
- package/dist/controllers/file_dropzone_controller.js.map +1 -1
- package/dist/controllers/filter_controller.js +77 -42
- package/dist/controllers/filter_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +35 -12
- package/dist/controllers/flash_controller.js +238 -347
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +15 -6
- package/dist/controllers/focus_controller.js +679 -240
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.js +156 -132
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.d.ts +3 -3
- package/dist/controllers/form_validation_controller.js +31 -97
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.d.ts +47 -14
- package/dist/controllers/frame_loading_controller.js +275 -217
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.d.ts +27 -6
- package/dist/controllers/highlight_controller.js +107 -75
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +60 -4
- package/dist/controllers/hover_card_controller.js +327 -130
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +48 -6
- package/dist/controllers/idle_controller.js +271 -101
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/input_mask_controller.d.ts +30 -13
- package/dist/controllers/input_mask_controller.js +483 -97
- package/dist/controllers/input_mask_controller.js.map +1 -1
- package/dist/controllers/intersection_controller.d.ts +32 -13
- package/dist/controllers/intersection_controller.js +150 -106
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.d.ts +19 -2
- package/dist/controllers/lazy_frame_controller.js +24 -68
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +44 -9
- package/dist/controllers/listbox_controller.js +523 -240
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.d.ts +9 -7
- package/dist/controllers/local_time_controller.js +102 -77
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.d.ts +11 -3
- package/dist/controllers/masonry_controller.js +80 -96
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/menu_controller.d.ts +55 -11
- package/dist/controllers/menu_controller.js +302 -188
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +51 -9
- package/dist/controllers/menubar_controller.js +232 -345
- package/dist/controllers/menubar_controller.js.map +1 -1
- package/dist/controllers/meter_controller.d.ts +33 -20
- package/dist/controllers/meter_controller.js +417 -87
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +48 -18
- package/dist/controllers/multi_select_controller.js +785 -393
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/navigation_menu_controller.d.ts +27 -6
- package/dist/controllers/navigation_menu_controller.js +190 -250
- package/dist/controllers/navigation_menu_controller.js.map +1 -1
- package/dist/controllers/nested_form_controller.d.ts +10 -0
- package/dist/controllers/nested_form_controller.js +396 -192
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/network_status_controller.d.ts +23 -0
- package/dist/controllers/network_status_controller.js +268 -62
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +50 -8
- package/dist/controllers/number_input_controller.js +610 -303
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/optimistic_controller.d.ts +8 -5
- package/dist/controllers/optimistic_controller.js +45 -87
- package/dist/controllers/optimistic_controller.js.map +1 -1
- package/dist/controllers/otp_controller.d.ts +55 -8
- package/dist/controllers/otp_controller.js +658 -255
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.d.ts +5 -0
- package/dist/controllers/overflow_indicator_controller.js +122 -113
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +58 -20
- package/dist/controllers/overflow_menu_controller.js +470 -295
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +37 -7
- package/dist/controllers/pagination_controller.js +332 -123
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +46 -8
- package/dist/controllers/password_reveal_controller.js +392 -121
- package/dist/controllers/password_reveal_controller.js.map +1 -1
- package/dist/controllers/password_strength_controller.d.ts +15 -6
- package/dist/controllers/password_strength_controller.js +111 -158
- package/dist/controllers/password_strength_controller.js.map +1 -1
- package/dist/controllers/persist_controller.d.ts +11 -4
- package/dist/controllers/persist_controller.js +165 -111
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +35 -12
- package/dist/controllers/pointer_drag_controller.js +434 -188
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +41 -5
- package/dist/controllers/popover_controller.js +269 -113
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +44 -4
- package/dist/controllers/portal_controller.js +215 -76
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/preview_guard_controller.d.ts +10 -4
- package/dist/controllers/preview_guard_controller.js +243 -116
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/progress_controller.d.ts +20 -19
- package/dist/controllers/progress_controller.js +391 -78
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.d.ts +21 -9
- package/dist/controllers/radio_group_controller.js +278 -211
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +47 -6
- package/dist/controllers/range_slider_controller.js +220 -113
- package/dist/controllers/range_slider_controller.js.map +1 -1
- package/dist/controllers/rating_controller.d.ts +20 -4
- package/dist/controllers/rating_controller.js +458 -211
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.d.ts +2 -0
- package/dist/controllers/read_more_controller.js +138 -63
- package/dist/controllers/read_more_controller.js.map +1 -1
- package/dist/controllers/reading_progress_controller.d.ts +1 -1
- package/dist/controllers/reading_progress_controller.js +166 -137
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/relative_time_controller.d.ts +20 -6
- package/dist/controllers/relative_time_controller.js +211 -112
- package/dist/controllers/relative_time_controller.js.map +1 -1
- package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
- package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +103 -38
- package/dist/controllers/reset_on_restore_controller.js.map +1 -0
- package/dist/controllers/resizable_controller.d.ts +31 -2
- package/dist/controllers/resizable_controller.js +299 -150
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.d.ts +3 -3
- package/dist/controllers/roving_controller.js +49 -88
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.d.ts +7 -3
- package/dist/controllers/scroll_area_controller.js +490 -246
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_restore_controller.d.ts +3 -3
- package/dist/controllers/scroll_restore_controller.js +14 -55
- package/dist/controllers/scroll_restore_controller.js.map +1 -1
- package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
- package/dist/controllers/scroll_visibility_controller.js +432 -149
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.d.ts +6 -1
- package/dist/controllers/scrollspy_controller.js +193 -248
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +20 -5
- package/dist/controllers/separator_controller.js +285 -142
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/sidebar_controller.d.ts +65 -8
- package/dist/controllers/sidebar_controller.js +1069 -404
- package/dist/controllers/sidebar_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.d.ts +23 -0
- package/dist/controllers/skeleton_controller.js +259 -101
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +29 -2
- package/dist/controllers/slider_controller.js +187 -86
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.d.ts +22 -4
- package/dist/controllers/smart_sticky_header_controller.js +173 -66
- package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.d.ts +4 -4
- package/dist/controllers/sortable_controller.js +26 -125
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.d.ts +39 -4
- package/dist/controllers/spinner_controller.js +288 -173
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +9 -4
- package/dist/controllers/step_indicator_controller.js +105 -46
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +14 -6
- package/dist/controllers/stepper_controller.js +120 -73
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +9 -1
- package/dist/controllers/stick_to_bottom_controller.js +275 -140
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.d.ts +11 -0
- package/dist/controllers/sticky_observer_controller.js +220 -49
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +24 -8
- package/dist/controllers/submit_once_controller.js +376 -227
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +18 -4
- package/dist/controllers/switch_controller.js +201 -84
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +9 -6
- package/dist/controllers/tabs_controller.js +41 -30
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +16 -3
- package/dist/controllers/tags_input_controller.js +293 -173
- package/dist/controllers/tags_input_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.d.ts +11 -1
- package/dist/controllers/textarea_autosize_controller.js +108 -74
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/theme_controller.d.ts +24 -11
- package/dist/controllers/theme_controller.js +140 -116
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +55 -5
- package/dist/controllers/time_picker_controller.js +331 -127
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/toast_controller.d.ts +40 -16
- package/dist/controllers/toast_controller.js +244 -324
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.d.ts +14 -6
- package/dist/controllers/toggle_group_controller.js +252 -191
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.d.ts +8 -6
- package/dist/controllers/toolbar_controller.js +219 -120
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +49 -4
- package/dist/controllers/tooltip_controller.js +158 -124
- package/dist/controllers/tooltip_controller.js.map +1 -1
- package/dist/controllers/transition_controller.d.ts +22 -4
- package/dist/controllers/transition_controller.js +123 -119
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +22 -12
- package/dist/controllers/tree_view_controller.js +283 -369
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.js +8573 -10410
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +38 -14
- package/dist/inspector/cli.js +108 -40
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +145 -64
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +20 -20
- package/dist/inspector/manifest.json +802 -101
- package/dist/positioning/index.d.ts +15 -7
- package/dist/positioning/index.js +154 -47
- package/dist/positioning/index.js.map +1 -1
- package/package.json +11 -10
- package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
- package/dist/controllers/reset_before_cache_controller.js.map +0 -1
|
@@ -1,14 +1,108 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
function setAttributeIfChanged(element, name, value, beforeWrite) {
|
|
4
|
+
if (element.getAttribute(name) === value) return false;
|
|
5
|
+
beforeWrite?.();
|
|
6
|
+
if (value === null) element.removeAttribute(name);
|
|
7
|
+
else element.setAttribute(name, value);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
var AuthoredMutationWatcher = class {
|
|
12
|
+
#onAuthored;
|
|
13
|
+
#claims = null;
|
|
14
|
+
#observer = null;
|
|
15
|
+
constructor(onAuthored) {
|
|
16
|
+
this.#onAuthored = onAuthored;
|
|
17
|
+
}
|
|
18
|
+
observe(root, options) {
|
|
19
|
+
this.disconnect();
|
|
20
|
+
const observer = new MutationObserver((records) => {
|
|
21
|
+
if (this.#observer !== observer) return;
|
|
22
|
+
const authored = this.#filter(records);
|
|
23
|
+
if (authored.length > 0) this.#onAuthored(authored);
|
|
24
|
+
});
|
|
25
|
+
this.#observer = observer;
|
|
26
|
+
this.#claims = { attributes: /* @__PURE__ */ new Map(), children: /* @__PURE__ */ new Map() };
|
|
27
|
+
observer.observe(root, {
|
|
28
|
+
attributes: true,
|
|
29
|
+
attributeFilter: [...options.attributes],
|
|
30
|
+
subtree: options.subtree ?? false,
|
|
31
|
+
childList: options.childList ?? false
|
|
32
|
+
});
|
|
33
|
+
if (options.ancestorAttributes) {
|
|
34
|
+
let ancestor = root.parentElement;
|
|
35
|
+
while (ancestor) {
|
|
36
|
+
observer.observe(ancestor, {
|
|
37
|
+
attributes: true,
|
|
38
|
+
attributeFilter: [...options.ancestorAttributes]
|
|
39
|
+
});
|
|
40
|
+
ancestor = ancestor.parentElement;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
claim(target, name, value) {
|
|
45
|
+
const claims = this.#claims?.attributes;
|
|
46
|
+
let attributes = claims?.get(target);
|
|
47
|
+
if (!attributes) {
|
|
48
|
+
attributes = /* @__PURE__ */ new Map();
|
|
49
|
+
claims?.set(target, attributes);
|
|
50
|
+
}
|
|
51
|
+
const pending = attributes.get(name);
|
|
52
|
+
attributes.set(name, { value, count: (pending?.count ?? 0) + 1 });
|
|
53
|
+
}
|
|
54
|
+
claimCurrent(target, name) {
|
|
55
|
+
this.claim(target, name, target.getAttribute(name));
|
|
56
|
+
}
|
|
57
|
+
claimChildList(target, added, removed) {
|
|
58
|
+
const claims = this.#claims?.children;
|
|
59
|
+
const pending = claims?.get(target) ?? { added: /* @__PURE__ */ new Map(), removed: /* @__PURE__ */ new Map() };
|
|
60
|
+
for (const node of added) pending.added.set(node, (pending.added.get(node) ?? 0) + 1);
|
|
61
|
+
for (const node of removed) pending.removed.set(node, (pending.removed.get(node) ?? 0) + 1);
|
|
62
|
+
claims?.set(target, pending);
|
|
63
|
+
}
|
|
64
|
+
take() {
|
|
65
|
+
return this.#filter(this.#observer?.takeRecords() ?? []);
|
|
66
|
+
}
|
|
67
|
+
disconnect() {
|
|
68
|
+
this.#observer?.disconnect();
|
|
69
|
+
this.#observer = null;
|
|
70
|
+
this.#claims = null;
|
|
71
|
+
}
|
|
72
|
+
#filter(records) {
|
|
73
|
+
const authored = records.filter((record) => !this.#consume(record));
|
|
74
|
+
this.#claims?.attributes.clear();
|
|
75
|
+
this.#claims?.children.clear();
|
|
76
|
+
return authored;
|
|
77
|
+
}
|
|
78
|
+
#consume(record) {
|
|
79
|
+
if (record.type === "attributes") {
|
|
80
|
+
const target = record.target;
|
|
81
|
+
const pending2 = this.#claims?.attributes.get(target)?.get(record.attributeName);
|
|
82
|
+
if (!pending2 || pending2.count === 0 || target.getAttribute(record.attributeName) !== pending2.value) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
pending2.count -= 1;
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
const pending = this.#claims?.children.get(record.target);
|
|
89
|
+
if (!pending) return false;
|
|
90
|
+
const added = [...record.addedNodes];
|
|
91
|
+
const removed = [...record.removedNodes];
|
|
92
|
+
if (added.some((node) => !pending.added.get(node)) || removed.some((node) => !pending.removed.get(node))) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
for (const node of added) pending.added.set(node, (pending.added.get(node) ?? 0) - 1);
|
|
96
|
+
for (const node of removed) pending.removed.set(node, (pending.removed.get(node) ?? 0) - 1);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
4
100
|
|
|
5
|
-
// src/utils/event_owner.ts
|
|
6
101
|
function ownerIndex(candidates, node) {
|
|
7
102
|
if (!(node instanceof Node)) return -1;
|
|
8
103
|
return candidates.findIndex((candidate) => candidate.contains(node));
|
|
9
104
|
}
|
|
10
105
|
|
|
11
|
-
// src/utils/focus_candidate.ts
|
|
12
106
|
function inheritsFieldsetDisabled(control) {
|
|
13
107
|
let fieldset = control.closest("fieldset[disabled]");
|
|
14
108
|
while (fieldset) {
|
|
@@ -18,33 +112,42 @@ function inheritsFieldsetDisabled(control) {
|
|
|
18
112
|
}
|
|
19
113
|
return false;
|
|
20
114
|
}
|
|
115
|
+
function unslotted(element) {
|
|
116
|
+
return element.assignedSlot === null && element.parentElement?.shadowRoot != null;
|
|
117
|
+
}
|
|
118
|
+
function flatTreeParent(element) {
|
|
119
|
+
if (unslotted(element)) return null;
|
|
120
|
+
const parent = element.assignedSlot ?? element.parentNode;
|
|
121
|
+
if (parent instanceof ShadowRoot) return parent.host;
|
|
122
|
+
return parent instanceof Element ? parent : null;
|
|
123
|
+
}
|
|
21
124
|
function canTakeFocus(element) {
|
|
22
|
-
|
|
125
|
+
for (let node = element; node; node = flatTreeParent(node)) {
|
|
126
|
+
if (unslotted(node) || node.matches("[hidden], [inert]")) return false;
|
|
127
|
+
}
|
|
23
128
|
if (element instanceof HTMLInputElement && element.type === "hidden") return false;
|
|
24
129
|
if (!("disabled" in element)) return true;
|
|
25
130
|
if (element.disabled) return false;
|
|
26
131
|
return !inheritsFieldsetDisabled(element);
|
|
27
132
|
}
|
|
133
|
+
function deepActiveElement(ownerDocument) {
|
|
134
|
+
let active = ownerDocument.activeElement;
|
|
135
|
+
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
|
|
136
|
+
return active;
|
|
137
|
+
}
|
|
28
138
|
|
|
29
|
-
// src/utils/form_reset_watcher.ts
|
|
30
139
|
var FormResetWatcher = class {
|
|
31
140
|
#owns;
|
|
32
141
|
#onReset;
|
|
33
142
|
#frames = /* @__PURE__ */ new Set();
|
|
34
143
|
#generation = 0;
|
|
35
|
-
/**
|
|
36
|
-
* @param owns - whether `form` owns a control this controller derives from.
|
|
37
|
-
* @param onReset - the reconciliation pass, run once per honoured reset.
|
|
38
|
-
*/
|
|
39
144
|
constructor(owns, onReset) {
|
|
40
145
|
this.#owns = owns;
|
|
41
146
|
this.#onReset = onReset;
|
|
42
147
|
}
|
|
43
|
-
/** Subscribes to `reset` at the document; call from `connect()`. Idempotent. */
|
|
44
148
|
observe() {
|
|
45
149
|
document.addEventListener("reset", this.#handleReset, true);
|
|
46
150
|
}
|
|
47
|
-
/** Unsubscribes and drops every pending pass; call from `disconnect()`. */
|
|
48
151
|
disconnect() {
|
|
49
152
|
document.removeEventListener("reset", this.#handleReset, true);
|
|
50
153
|
this.#generation += 1;
|
|
@@ -68,57 +171,41 @@ var FormResetWatcher = class {
|
|
|
68
171
|
this.#frames.add(frame);
|
|
69
172
|
});
|
|
70
173
|
};
|
|
71
|
-
/** Runs the pass unless a listener cancelled the reset before it landed. */
|
|
72
174
|
#settle(event) {
|
|
73
175
|
if (!event.defaultPrevented) this.#onReset();
|
|
74
176
|
}
|
|
75
177
|
};
|
|
76
178
|
|
|
77
|
-
// src/utils/listener_set.ts
|
|
78
179
|
var ListenerSet = class {
|
|
79
|
-
/** The generation every `add` joins until the next `dispose()`. */
|
|
80
180
|
#abort = new AbortController();
|
|
81
|
-
/**
|
|
82
|
-
* Attaches `handler` to the open generation, exactly as the caller spelled it.
|
|
83
|
-
*
|
|
84
|
-
* The set supplies the signal, so `options` carries everything else the DOM
|
|
85
|
-
* accepts — `capture` included, which has to match at release time and no
|
|
86
|
-
* longer has a second place to drift from.
|
|
87
|
-
*/
|
|
88
181
|
add(target, type, handler, options) {
|
|
89
182
|
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
90
183
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Releases every listener of the open generation, synchronously, and opens the
|
|
93
|
-
* next one. Idempotent, and safe before anything has been added.
|
|
94
|
-
*/
|
|
95
184
|
dispose() {
|
|
96
185
|
this.#abort.abort();
|
|
97
186
|
this.#abort = new AbortController();
|
|
98
187
|
}
|
|
99
188
|
};
|
|
100
189
|
|
|
101
|
-
// src/utils/microtask_coalescer.ts
|
|
102
190
|
var MicrotaskCoalescer = class {
|
|
103
191
|
#run;
|
|
104
192
|
#queued = false;
|
|
105
193
|
#active = false;
|
|
106
194
|
#generation = 0;
|
|
107
|
-
/** @param run - the single reconciliation pass, invoked at most once per batch. */
|
|
108
195
|
constructor(run) {
|
|
109
196
|
this.#run = run;
|
|
110
197
|
}
|
|
111
|
-
/** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
|
|
112
198
|
activate() {
|
|
113
199
|
this.#active = true;
|
|
114
200
|
}
|
|
115
|
-
/** Closes the window and drops any pending pass; call from `disconnect()`. */
|
|
116
201
|
cancel() {
|
|
117
202
|
this.#active = false;
|
|
118
203
|
this.#queued = false;
|
|
119
204
|
this.#generation += 1;
|
|
120
205
|
}
|
|
121
|
-
|
|
206
|
+
get pending() {
|
|
207
|
+
return this.#queued;
|
|
208
|
+
}
|
|
122
209
|
schedule() {
|
|
123
210
|
if (!this.#active || this.#queued) return;
|
|
124
211
|
this.#queued = true;
|
|
@@ -131,68 +218,166 @@ var MicrotaskCoalescer = class {
|
|
|
131
218
|
}
|
|
132
219
|
};
|
|
133
220
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
};
|
|
142
|
-
#rewind;
|
|
143
|
-
/** @param rewind - the pass that returns this controller's state to its initial form. */
|
|
144
|
-
constructor(rewind) {
|
|
145
|
-
this.#rewind = rewind;
|
|
221
|
+
var MorphRenderWatcher = class {
|
|
222
|
+
#listeners = new ListenerSet();
|
|
223
|
+
#pass;
|
|
224
|
+
#element = null;
|
|
225
|
+
#onMorph = () => this.#pass.schedule();
|
|
226
|
+
constructor(run) {
|
|
227
|
+
this.#pass = new MicrotaskCoalescer(run);
|
|
146
228
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
229
|
+
observe(element) {
|
|
230
|
+
if (this.#element === element) return;
|
|
231
|
+
this.disconnect();
|
|
232
|
+
this.#element = element;
|
|
233
|
+
this.#pass.activate();
|
|
234
|
+
this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
|
|
235
|
+
}
|
|
236
|
+
schedule() {
|
|
237
|
+
this.#pass.schedule();
|
|
238
|
+
}
|
|
239
|
+
get pending() {
|
|
240
|
+
return this.#pass.pending;
|
|
154
241
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
document.removeEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
|
|
242
|
+
disconnect() {
|
|
243
|
+
this.#listeners.dispose();
|
|
244
|
+
this.#pass.cancel();
|
|
245
|
+
this.#element = null;
|
|
160
246
|
}
|
|
161
247
|
};
|
|
162
248
|
|
|
163
|
-
|
|
164
|
-
|
|
249
|
+
function queryOpenDescendants(root, selector) {
|
|
250
|
+
const matches = [];
|
|
251
|
+
const roots = [root];
|
|
252
|
+
for (const scope of roots) {
|
|
253
|
+
matches.push(...scope.querySelectorAll(selector));
|
|
254
|
+
if (scope.nodeType === Node.ELEMENT_NODE) {
|
|
255
|
+
const shadow = scope.shadowRoot;
|
|
256
|
+
if (shadow) roots.push(shadow);
|
|
257
|
+
}
|
|
258
|
+
for (const element of scope.querySelectorAll("*")) {
|
|
259
|
+
if (element.shadowRoot) roots.push(element.shadowRoot);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return matches;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function sharedRegistry(key, create) {
|
|
266
|
+
const symbol = Symbol.for(key);
|
|
267
|
+
const scope = globalThis;
|
|
268
|
+
const existing = scope[symbol];
|
|
269
|
+
if (existing !== void 0) return existing;
|
|
270
|
+
const registry = create();
|
|
271
|
+
Object.defineProperty(globalThis, symbol, { value: registry });
|
|
272
|
+
return registry;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function holdsFocus(element) {
|
|
276
|
+
return element.matches(":focus") || deepActiveElement(element.ownerDocument) === element;
|
|
277
|
+
}
|
|
278
|
+
var TabindexLoan = class _TabindexLoan {
|
|
279
|
+
static #registry = sharedRegistry(
|
|
280
|
+
"stimeo-ui.tabindex-loan.registry.v1",
|
|
281
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Set() })
|
|
282
|
+
);
|
|
165
283
|
#value;
|
|
284
|
+
#record;
|
|
285
|
+
#preserveFocus;
|
|
166
286
|
#lent = /* @__PURE__ */ new Set();
|
|
167
|
-
|
|
168
|
-
#beforeCache = new BeforeCacheReset(() => this.returnAll());
|
|
169
|
-
/**
|
|
170
|
-
* @param value - the `tabindex` to lend. `"-1"` (the default) is
|
|
171
|
-
* programmatically focusable but not a Tab stop; `"0"` is a real Tab stop,
|
|
172
|
-
* which a scroll region with no focusable content of its own needs.
|
|
173
|
-
*/
|
|
174
|
-
constructor(value = "-1") {
|
|
287
|
+
constructor(value, owner, options = {}) {
|
|
175
288
|
this.#value = value;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
289
|
+
this.#record = `data-${owner}-tabindex-loan`;
|
|
290
|
+
this.#preserveFocus = options.preserveFocus === true;
|
|
291
|
+
_TabindexLoan.#registry.names.add(this.#record);
|
|
292
|
+
}
|
|
293
|
+
lend(element, options = {}) {
|
|
294
|
+
const stack = this.#stack(element);
|
|
295
|
+
const current = element.getAttribute("tabindex");
|
|
296
|
+
const held = stack.find((hold) => hold.loan === this) ?? stack.find(
|
|
297
|
+
(hold) => hold.loan === null && hold.record === this.#record && hold.value === this.#value
|
|
298
|
+
);
|
|
299
|
+
const linked = stack.at(-1)?.value === current;
|
|
300
|
+
if (!held && options.onlyIfUnfocusable && (current !== null || element.tabIndex >= 0)) return;
|
|
301
|
+
if (!held && current !== null && !linked) return;
|
|
181
302
|
this.#lent.add(element);
|
|
182
|
-
|
|
303
|
+
if (held) held.loan = this;
|
|
304
|
+
else stack.push({ loan: this, record: this.#record, value: this.#value, linked });
|
|
305
|
+
this.#mark(element, stack);
|
|
306
|
+
if (current === null || !held && current !== this.#value) {
|
|
307
|
+
element.setAttribute("tabindex", this.#value);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return(element) {
|
|
311
|
+
const stack = this.#stack(element);
|
|
312
|
+
const hold = stack.find((held) => held.loan === this) ?? stack.find(
|
|
313
|
+
(held) => held.loan === null && held.record === this.#record && held.value === this.#value
|
|
314
|
+
);
|
|
315
|
+
if (!hold) return false;
|
|
316
|
+
if (!this.#release(element, stack, hold, this.#preserveFocus)) {
|
|
317
|
+
hold.loan = this;
|
|
318
|
+
this.#lent.add(element);
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
this.#lent.delete(element);
|
|
322
|
+
return true;
|
|
183
323
|
}
|
|
184
|
-
/** Takes back every loan whose value is still the one that was lent. */
|
|
185
324
|
returnAll() {
|
|
186
|
-
for (const element of this.#lent)
|
|
187
|
-
|
|
325
|
+
for (const element of Array.from(this.#lent)) this.return(element);
|
|
326
|
+
}
|
|
327
|
+
reclaim(element) {
|
|
328
|
+
if (element.getAttribute(this.#record) !== this.#value) return;
|
|
329
|
+
const stack = this.#stack(element);
|
|
330
|
+
const hold = stack.find((held) => held.loan === null && held.record === this.#record);
|
|
331
|
+
if (hold && !holdsFocus(element)) this.#release(element, stack, hold);
|
|
332
|
+
}
|
|
333
|
+
reclaimWithin(root) {
|
|
334
|
+
for (const element of queryOpenDescendants(root, `[${this.#record}]`)) {
|
|
335
|
+
this.reclaim(element);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
#stack(element) {
|
|
339
|
+
const stacks = _TabindexLoan.#registry.stacks;
|
|
340
|
+
const stack = stacks.get(element) ?? this.#seed(element);
|
|
341
|
+
stacks.set(element, stack);
|
|
342
|
+
return stack;
|
|
343
|
+
}
|
|
344
|
+
#seed(element) {
|
|
345
|
+
const current = element.getAttribute("tabindex");
|
|
346
|
+
const holds = [];
|
|
347
|
+
for (const record of _TabindexLoan.#registry.names) {
|
|
348
|
+
const value = element.getAttribute(record);
|
|
349
|
+
if (value !== null) holds.push({ loan: null, record, value, linked: true });
|
|
350
|
+
}
|
|
351
|
+
holds.sort((one, other) => Number(one.value === current) - Number(other.value === current));
|
|
352
|
+
for (const [index, hold] of holds.entries()) hold.linked = index > 0;
|
|
353
|
+
return holds;
|
|
354
|
+
}
|
|
355
|
+
#release(element, stack, hold, preserveFocus = false) {
|
|
356
|
+
const current = element.getAttribute("tabindex");
|
|
357
|
+
const index = stack.indexOf(hold);
|
|
358
|
+
const owns = current === hold.value && !stack.slice(index + 1).some((above2) => above2.value === current);
|
|
359
|
+
if (owns && preserveFocus && holdsFocus(element)) return false;
|
|
360
|
+
stack.splice(index, 1);
|
|
361
|
+
const above = stack[index];
|
|
362
|
+
if (above) above.linked &&= hold.linked;
|
|
363
|
+
this.#mark(element, stack);
|
|
364
|
+
if (!owns) return true;
|
|
365
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
366
|
+
if (!below) element.removeAttribute("tabindex");
|
|
367
|
+
else if (below.value !== current) element.setAttribute("tabindex", below.value);
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
#mark(element, stack) {
|
|
371
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
372
|
+
for (const hold of stack) records.set(hold.record, hold.value);
|
|
373
|
+
for (const [name, recorded] of records) {
|
|
374
|
+
setAttributeIfChanged(element, name, recorded);
|
|
188
375
|
}
|
|
189
|
-
this.#lent.clear();
|
|
190
|
-
this.#beforeCache.deactivate();
|
|
191
376
|
}
|
|
192
377
|
};
|
|
193
378
|
|
|
194
|
-
// src/controllers/conditional_fields_controller.ts
|
|
195
379
|
var DISABLED_MARKER = "data-conditional-disabled";
|
|
380
|
+
var CONTROLS = "input, textarea, select, button";
|
|
196
381
|
var OBSERVED_ATTRIBUTES = [
|
|
197
382
|
"hidden",
|
|
198
383
|
"aria-hidden",
|
|
@@ -215,23 +400,17 @@ var ConditionalFieldsController = class extends Controller {
|
|
|
215
400
|
};
|
|
216
401
|
static actions = ["evaluate"];
|
|
217
402
|
static events = ["change", "reconcile"];
|
|
218
|
-
/** Logical state last committed for each current region; rebuilt on every connect. */
|
|
219
403
|
#lastVisible = /* @__PURE__ */ new WeakMap();
|
|
220
|
-
|
|
221
|
-
#
|
|
222
|
-
#
|
|
223
|
-
/** Coalesces one target/morph/mutation batch into one full DOM reconciliation. */
|
|
224
|
-
#reconcile = new MicrotaskCoalescer(() => this.#reconcileDom());
|
|
404
|
+
#departed = /* @__PURE__ */ new Set();
|
|
405
|
+
#concealed = /* @__PURE__ */ new WeakSet();
|
|
406
|
+
#reconcile = new MorphRenderWatcher(() => this.#reconcileDom());
|
|
225
407
|
#listeners = new ListenerSet();
|
|
226
408
|
#formReset = new FormResetWatcher(
|
|
227
409
|
(form) => this.#hasTriggerOwnedBy(form),
|
|
228
410
|
() => this.#reconcile.schedule()
|
|
229
411
|
);
|
|
230
|
-
|
|
231
|
-
#
|
|
232
|
-
/** Watches retained targets and controls whose declarative or reflected state changed. */
|
|
233
|
-
#observer = new MutationObserver((records) => this.#onMutations(records));
|
|
234
|
-
/** Evaluates only events whose source is one of this instance's live trigger targets. */
|
|
412
|
+
#rootTabindex = new TabindexLoan("-1", this.identifier);
|
|
413
|
+
#observer = new AuthoredMutationWatcher((records) => this.#onMutations(records));
|
|
235
414
|
#onTriggerInput = (event) => {
|
|
236
415
|
const target = event.target;
|
|
237
416
|
const triggers = this.triggerTargets;
|
|
@@ -239,75 +418,57 @@ var ConditionalFieldsController = class extends Controller {
|
|
|
239
418
|
this.#commitChange(triggers);
|
|
240
419
|
}
|
|
241
420
|
};
|
|
242
|
-
/** Reconciles property-only retained-element changes after Turbo morphs. */
|
|
243
|
-
#onMorph = () => {
|
|
244
|
-
this.#reconcile.schedule();
|
|
245
|
-
};
|
|
246
|
-
/** Reflects initial live state and opens every retained-DOM reconciliation path. */
|
|
247
421
|
connect() {
|
|
422
|
+
this.#rootTabindex.reclaim(this.element);
|
|
248
423
|
this.#lastVisible = /* @__PURE__ */ new WeakMap();
|
|
249
|
-
this.#internalWrites = /* @__PURE__ */ new WeakMap();
|
|
250
|
-
this.#reconcile.activate();
|
|
251
424
|
this.#settle();
|
|
425
|
+
this.#reconcile.observe(this.element);
|
|
252
426
|
this.#observer.observe(this.element, {
|
|
253
|
-
attributes:
|
|
254
|
-
attributeFilter: OBSERVED_ATTRIBUTES,
|
|
427
|
+
attributes: OBSERVED_ATTRIBUTES,
|
|
255
428
|
childList: true,
|
|
256
429
|
subtree: true
|
|
257
430
|
});
|
|
258
|
-
this.#observing = true;
|
|
259
431
|
this.#listeners.add(this.element, "change", this.#onTriggerInput);
|
|
260
432
|
this.#listeners.add(this.element, "input", this.#onTriggerInput);
|
|
261
|
-
this.#listeners.add(this.element, "turbo:morph-element", this.#onMorph);
|
|
262
433
|
this.#formReset.observe();
|
|
263
434
|
}
|
|
264
|
-
/** Releases all external resources and returns the temporary focus landmark loan. */
|
|
265
435
|
disconnect() {
|
|
266
|
-
this.#reconcile.
|
|
267
|
-
this.#observing = false;
|
|
436
|
+
this.#reconcile.disconnect();
|
|
268
437
|
this.#observer.disconnect();
|
|
269
438
|
this.#listeners.dispose();
|
|
270
439
|
this.#formReset.disconnect();
|
|
271
440
|
this.#rootTabindex.returnAll();
|
|
272
441
|
}
|
|
273
|
-
/** Reconciles after a trigger target is inserted or restored. */
|
|
274
442
|
triggerTargetConnected() {
|
|
275
443
|
this.#reconcile.schedule();
|
|
276
444
|
}
|
|
277
|
-
/** Reconciles after a trigger target is removed or replaced. */
|
|
278
445
|
triggerTargetDisconnected() {
|
|
279
446
|
this.#reconcile.schedule();
|
|
280
447
|
}
|
|
281
|
-
/** Initializes a region target inserted or restored at runtime. */
|
|
282
448
|
regionTargetConnected() {
|
|
283
449
|
this.#reconcile.schedule();
|
|
284
450
|
}
|
|
285
|
-
|
|
286
|
-
|
|
451
|
+
regionTargetDisconnected(region) {
|
|
452
|
+
this.#departed.add(region);
|
|
287
453
|
this.#reconcile.schedule();
|
|
288
454
|
}
|
|
289
|
-
/** Reconciles when application code or a morph changes the match policy. */
|
|
290
455
|
matchValueChanged() {
|
|
291
456
|
this.#reconcile.schedule();
|
|
292
457
|
}
|
|
293
|
-
/** Reconciles control ownership when hidden controls become enabled or excluded. */
|
|
294
458
|
disableHiddenValueChanged() {
|
|
295
459
|
this.#reconcile.schedule();
|
|
296
460
|
}
|
|
297
|
-
/** Re-evaluates every region and repairs all reflected DOM state. */
|
|
298
461
|
evaluate() {
|
|
299
462
|
this.#commitChange();
|
|
300
463
|
}
|
|
301
|
-
/**
|
|
302
|
-
* Computes one settled plan, shows destinations before hiding sources, and then
|
|
303
|
-
* returns logical transitions in DOM order after every region is internally coherent.
|
|
304
|
-
*
|
|
305
|
-
* @stimeoRenderRoot
|
|
306
|
-
*/
|
|
307
464
|
#settle(triggers = this.triggerTargets) {
|
|
308
465
|
const regions = this.regionTargets;
|
|
309
466
|
const plan = /* @__PURE__ */ new Map();
|
|
310
467
|
for (const region of regions) plan.set(region, this.#isVisible(region, triggers));
|
|
468
|
+
for (const departed of this.#departed) {
|
|
469
|
+
if (!plan.has(departed)) this.#release(departed, plan);
|
|
470
|
+
}
|
|
471
|
+
this.#departed.clear();
|
|
311
472
|
const changed = /* @__PURE__ */ new Set();
|
|
312
473
|
const applicationOrder = [
|
|
313
474
|
...regions.filter((region) => plan.get(region) === true),
|
|
@@ -321,19 +482,16 @@ var ConditionalFieldsController = class extends Controller {
|
|
|
321
482
|
}
|
|
322
483
|
return regions.filter((region) => changed.has(region)).map((region) => ({ region, visible: plan.get(region) === true }));
|
|
323
484
|
}
|
|
324
|
-
/** Reports logical transitions caused by user input or the public action. */
|
|
325
485
|
#commitChange(triggers = this.triggerTargets) {
|
|
326
486
|
for (const detail of this.#settle(triggers)) {
|
|
327
487
|
this.dispatch("change", { detail });
|
|
328
488
|
}
|
|
329
489
|
}
|
|
330
|
-
/** Reports logical transitions derived from DOM, lifecycle, reset, or Value state. */
|
|
331
490
|
#reconcileDom() {
|
|
332
491
|
for (const detail of this.#settle()) {
|
|
333
492
|
this.dispatch("reconcile", { detail });
|
|
334
493
|
}
|
|
335
494
|
}
|
|
336
|
-
/** Applies one planned state while keeping event history separate from DOM repair. */
|
|
337
495
|
#applyRegion(region, visible, plan) {
|
|
338
496
|
const previous = this.#lastVisible.get(region) ?? !region.hidden;
|
|
339
497
|
const changed = visible !== previous;
|
|
@@ -343,17 +501,16 @@ var ConditionalFieldsController = class extends Controller {
|
|
|
343
501
|
this.#syncRegionControls(region, visible);
|
|
344
502
|
return changed;
|
|
345
503
|
}
|
|
346
|
-
/** Reflects visibility idempotently, recording writes so the observer ignores its own work. */
|
|
347
504
|
#syncRegionState(region, visible) {
|
|
505
|
+
if (!visible && this.#predicateFor(region) !== null) this.#concealed.add(region);
|
|
506
|
+
else this.#concealed.delete(region);
|
|
348
507
|
this.#writeAttribute(region, "hidden", visible ? null : "");
|
|
349
508
|
this.#writeAttribute(region, "aria-hidden", visible ? null : "true");
|
|
350
509
|
this.#writeAttribute(region, "data-visible", visible ? "true" : null);
|
|
351
510
|
}
|
|
352
|
-
/** Enables/disables descendant controls, touching only state carrying our marker. */
|
|
353
511
|
#syncRegionControls(region, visible) {
|
|
354
512
|
const shouldDisable = !visible && this.disableHiddenValue;
|
|
355
|
-
const
|
|
356
|
-
for (const control of controls) {
|
|
513
|
+
for (const control of region.querySelectorAll(CONTROLS)) {
|
|
357
514
|
const marked = control.hasAttribute(DISABLED_MARKER);
|
|
358
515
|
if (shouldDisable) {
|
|
359
516
|
if (!control.disabled) {
|
|
@@ -363,18 +520,30 @@ var ConditionalFieldsController = class extends Controller {
|
|
|
363
520
|
this.#writeAttribute(control, DISABLED_MARKER, "true");
|
|
364
521
|
}
|
|
365
522
|
} else if (marked) {
|
|
366
|
-
this.#
|
|
367
|
-
|
|
523
|
+
this.#enable(control);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
#enable(control) {
|
|
528
|
+
this.#writeAttribute(control, "disabled", null);
|
|
529
|
+
this.#writeAttribute(control, DISABLED_MARKER, null);
|
|
530
|
+
}
|
|
531
|
+
#release(element, plan) {
|
|
532
|
+
this.#lastVisible.delete(element);
|
|
533
|
+
if (this.#concealed.delete(element)) this.#writeAttribute(element, "hidden", null);
|
|
534
|
+
this.#writeAttribute(element, "aria-hidden", null);
|
|
535
|
+
this.#writeAttribute(element, "data-visible", null);
|
|
536
|
+
for (const control of element.querySelectorAll(CONTROLS)) {
|
|
537
|
+
if (control.hasAttribute(DISABLED_MARKER) && this.#survivesPlan(control, plan)) {
|
|
538
|
+
this.#enable(control);
|
|
368
539
|
}
|
|
369
540
|
}
|
|
370
541
|
}
|
|
371
|
-
/** Whether a region's declared condition holds across `triggers` per `match`. */
|
|
372
542
|
#isVisible(region, triggers) {
|
|
373
543
|
const predicate = this.#predicateFor(region);
|
|
374
544
|
if (predicate === null) return !region.hidden;
|
|
375
545
|
return triggers.length > 0 && (this.matchValue === "all" ? triggers.every(predicate) : triggers.some(predicate));
|
|
376
546
|
}
|
|
377
|
-
/** Builds the deterministic per-trigger predicate from the region's condition. */
|
|
378
547
|
#predicateFor(region) {
|
|
379
548
|
if (region.hasAttribute("data-when-checked")) {
|
|
380
549
|
return (trigger) => this.#isChecked(trigger);
|
|
@@ -391,19 +560,16 @@ var ConditionalFieldsController = class extends Controller {
|
|
|
391
560
|
#isChecked(trigger) {
|
|
392
561
|
return trigger instanceof HTMLInputElement && trigger.checked;
|
|
393
562
|
}
|
|
394
|
-
/** A trigger has a value when a radio/checkbox is selected, or its control value matches. */
|
|
395
563
|
#matchesValue(trigger, wanted) {
|
|
396
564
|
if (trigger instanceof HTMLInputElement && (trigger.type === "checkbox" || trigger.type === "radio")) {
|
|
397
565
|
return trigger.checked && trigger.value === wanted;
|
|
398
566
|
}
|
|
399
567
|
return trigger.value === wanted;
|
|
400
568
|
}
|
|
401
|
-
/** Moves focus to the first safe trigger, or to the controller landmark as a fallback. */
|
|
402
569
|
#retreatFocus(region, plan) {
|
|
403
570
|
const active = document.activeElement;
|
|
404
571
|
if (active && region.contains(active)) this.#moveFocus(plan);
|
|
405
572
|
}
|
|
406
|
-
/** Moves focus after the caller establishes that the active node is being hidden. */
|
|
407
573
|
#moveFocus(plan) {
|
|
408
574
|
const destination = this.triggerTargets.find(
|
|
409
575
|
(trigger) => canTakeFocus(trigger) && this.#survivesPlan(trigger, plan)
|
|
@@ -416,65 +582,28 @@ var ConditionalFieldsController = class extends Controller {
|
|
|
416
582
|
this.#rootTabindex.lend(this.element);
|
|
417
583
|
this.element.focus();
|
|
418
584
|
}
|
|
419
|
-
/** Whether a focus candidate sits outside every region this pass will hide. */
|
|
420
585
|
#survivesPlan(candidate, plan) {
|
|
421
586
|
return [...plan].every(([region, visible]) => visible || !region.contains(candidate));
|
|
422
587
|
}
|
|
423
|
-
/** Records one idempotent attribute write before MutationObserver sees it. */
|
|
424
588
|
#writeAttribute(element, name, value) {
|
|
425
|
-
|
|
426
|
-
if (this.#observing) {
|
|
427
|
-
let writes = this.#internalWrites.get(element);
|
|
428
|
-
if (!writes) {
|
|
429
|
-
writes = /* @__PURE__ */ new Map();
|
|
430
|
-
this.#internalWrites.set(element, writes);
|
|
431
|
-
}
|
|
432
|
-
writes.set(name, value);
|
|
433
|
-
}
|
|
434
|
-
if (value === null) element.removeAttribute(name);
|
|
435
|
-
else element.setAttribute(name, value);
|
|
436
|
-
}
|
|
589
|
+
setAttributeIfChanged(element, name, value, () => this.#observer.claim(element, name, value));
|
|
437
590
|
}
|
|
438
|
-
/** Separates authored records from controller writes and queues one relevant repair. */
|
|
439
591
|
#onMutations(records) {
|
|
440
592
|
const triggers = this.triggerTargets;
|
|
441
593
|
const regions = this.regionTargets;
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
const name = record.attributeName;
|
|
447
|
-
const writes = this.#internalWrites.get(record.target);
|
|
448
|
-
if (name && writes?.has(name)) {
|
|
449
|
-
let names = touchedWrites.get(record.target);
|
|
450
|
-
if (!names) {
|
|
451
|
-
names = /* @__PURE__ */ new Set();
|
|
452
|
-
touchedWrites.set(record.target, names);
|
|
453
|
-
}
|
|
454
|
-
names.add(name);
|
|
455
|
-
if (record.target.getAttribute(name) === writes.get(name)) continue;
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
if (record.target instanceof Element && this.#elementAffectsState(record.target, triggers, regions)) {
|
|
459
|
-
needsReconcile = true;
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
for (const [element, names] of touchedWrites) {
|
|
463
|
-
const writes = this.#internalWrites.get(element);
|
|
464
|
-
for (const name of names) writes?.delete(name);
|
|
594
|
+
if (records.some(
|
|
595
|
+
(record) => record.target instanceof Element && this.#elementAffectsState(record.target, triggers, regions)
|
|
596
|
+
)) {
|
|
597
|
+
this.#reconcile.schedule();
|
|
465
598
|
}
|
|
466
|
-
if (needsReconcile) this.#reconcile.schedule();
|
|
467
599
|
}
|
|
468
|
-
/** Whether an authored mutation target belongs to a trigger, region, or managed control. */
|
|
469
600
|
#elementAffectsState(target, triggers, regions) {
|
|
470
601
|
return ownerIndex(triggers, target) !== -1 || ownerIndex(regions, target) !== -1;
|
|
471
602
|
}
|
|
472
|
-
/** Whether a form owns at least one current trigger, including `form=` associations. */
|
|
473
603
|
#hasTriggerOwnedBy(form) {
|
|
474
604
|
return this.triggerTargets.some((trigger) => trigger.form === form);
|
|
475
605
|
}
|
|
476
606
|
};
|
|
477
607
|
|
|
478
608
|
export { ConditionalFieldsController };
|
|
479
|
-
//# sourceMappingURL=conditional_fields_controller.js.map
|
|
480
609
|
//# sourceMappingURL=conditional_fields_controller.js.map
|