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,78 +1,158 @@
|
|
|
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
|
+
if (value === null) element.removeAttribute(name);
|
|
6
|
+
else element.setAttribute(name, value);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function sharedRegistry(key, create) {
|
|
11
|
+
const symbol = Symbol.for(key);
|
|
12
|
+
const scope = globalThis;
|
|
13
|
+
const existing = scope[symbol];
|
|
14
|
+
if (existing !== void 0) return existing;
|
|
15
|
+
const registry2 = create();
|
|
16
|
+
Object.defineProperty(globalThis, symbol, { value: registry2 });
|
|
17
|
+
return registry2;
|
|
18
|
+
}
|
|
4
19
|
|
|
5
|
-
|
|
20
|
+
var registry = sharedRegistry(
|
|
21
|
+
"stimeo-ui.attribute-lease.registry.v1",
|
|
22
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
|
|
23
|
+
);
|
|
24
|
+
function isAttributeValue(value) {
|
|
25
|
+
return value === null || typeof value === "string";
|
|
26
|
+
}
|
|
27
|
+
function readLeaseRecord(element, record) {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(element.getAttribute(record) ?? "null");
|
|
30
|
+
if (!Array.isArray(parsed)) return void 0;
|
|
31
|
+
const [original, written, ...rest] = parsed;
|
|
32
|
+
const linked = rest[0] !== false;
|
|
33
|
+
const beneath = linked ? rest : rest.slice(1);
|
|
34
|
+
if (!beneath.every((under) => typeof under === "string")) return void 0;
|
|
35
|
+
return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
|
|
36
|
+
} catch {
|
|
37
|
+
return void 0;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function attributeStack(element, attribute) {
|
|
41
|
+
const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
42
|
+
registry.stacks.set(element, byAttribute);
|
|
43
|
+
const known = byAttribute.get(attribute);
|
|
44
|
+
if (known) return known;
|
|
45
|
+
const found = [];
|
|
46
|
+
for (const record of registry.names.get(attribute) ?? []) {
|
|
47
|
+
const read = readLeaseRecord(element, record);
|
|
48
|
+
if (read) found.push({ ...read, record });
|
|
49
|
+
}
|
|
50
|
+
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
51
|
+
const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
|
|
52
|
+
lease: null,
|
|
53
|
+
record,
|
|
54
|
+
written,
|
|
55
|
+
original,
|
|
56
|
+
linked: linked && index > 0
|
|
57
|
+
}));
|
|
58
|
+
byAttribute.set(attribute, stack);
|
|
59
|
+
return stack;
|
|
60
|
+
}
|
|
61
|
+
function findHold(stack, lease, record) {
|
|
62
|
+
return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
|
|
63
|
+
}
|
|
6
64
|
var AttributeLease = class {
|
|
7
65
|
#attribute;
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
|
|
66
|
+
#record;
|
|
67
|
+
#base;
|
|
68
|
+
#preserveAuthor;
|
|
69
|
+
#held = /* @__PURE__ */ new Set();
|
|
70
|
+
constructor(attribute, owner, options = {}) {
|
|
11
71
|
this.#attribute = attribute;
|
|
72
|
+
this.#record = `data-${owner}-${attribute}-lease`;
|
|
73
|
+
this.#base = options.base === true;
|
|
74
|
+
this.#preserveAuthor = options.preserveAuthor === true;
|
|
75
|
+
const names = registry.names;
|
|
76
|
+
names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
|
|
12
77
|
}
|
|
13
|
-
/** Writes or removes the leased attribute while preserving its authored value. */
|
|
14
78
|
write(element, value) {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
this.#reflect(element, value);
|
|
79
|
+
const stack = attributeStack(element, this.#attribute);
|
|
80
|
+
const hold = this.#take(stack) ?? this.#acquire(element, stack);
|
|
81
|
+
this.#held.add(element);
|
|
82
|
+
const shows = !this.#covered(element, stack, hold);
|
|
83
|
+
hold.written = value;
|
|
84
|
+
this.#mark(element, stack);
|
|
85
|
+
if (shows) this.#reflect(element, value);
|
|
25
86
|
}
|
|
26
|
-
/** Returns one lease without overwriting a value subsequently authored by a consumer. */
|
|
27
87
|
return(element) {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
this.#
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
88
|
+
const held = this.#held.delete(element);
|
|
89
|
+
const known = registry.stacks.get(element)?.has(this.#attribute);
|
|
90
|
+
const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
|
|
91
|
+
const hold = this.#take(stack);
|
|
92
|
+
if (!hold) return false;
|
|
93
|
+
const carries = element.getAttribute(this.#attribute) === hold.written;
|
|
94
|
+
const owns = carries && !this.#covered(element, stack, hold);
|
|
95
|
+
const index = stack.indexOf(hold);
|
|
96
|
+
stack.splice(index, 1);
|
|
97
|
+
const above = stack[index];
|
|
98
|
+
if (above) above.linked &&= hold.linked;
|
|
99
|
+
this.#mark(element, stack);
|
|
100
|
+
if (!owns) return true;
|
|
101
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
102
|
+
this.#reflect(element, below ? below.written : hold.original);
|
|
103
|
+
return true;
|
|
39
104
|
}
|
|
40
|
-
/** Returns every outstanding lease using the same ownership check as {@link return}. */
|
|
41
105
|
returnAll() {
|
|
42
|
-
for (const element of Array.from(this.#
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
106
|
+
for (const element of Array.from(this.#held)) this.return(element);
|
|
107
|
+
}
|
|
108
|
+
#take(stack) {
|
|
109
|
+
const hold = findHold(stack, this, this.#record);
|
|
110
|
+
if (hold) hold.lease = this;
|
|
111
|
+
return hold;
|
|
112
|
+
}
|
|
113
|
+
#acquire(element, stack) {
|
|
114
|
+
const current = element.getAttribute(this.#attribute);
|
|
115
|
+
const top = stack.at(-1);
|
|
116
|
+
const bottom = stack[0];
|
|
117
|
+
const over = top?.written === current ? top : void 0;
|
|
118
|
+
const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
|
|
119
|
+
const hold = {
|
|
120
|
+
lease: this,
|
|
121
|
+
record: this.#record,
|
|
122
|
+
written: current,
|
|
123
|
+
original: from ? from.original : current,
|
|
124
|
+
linked: !this.#base && over !== void 0
|
|
125
|
+
};
|
|
126
|
+
if (this.#base && bottom) {
|
|
127
|
+
bottom.linked = true;
|
|
128
|
+
stack.unshift(hold);
|
|
129
|
+
} else stack.push(hold);
|
|
130
|
+
return hold;
|
|
131
|
+
}
|
|
132
|
+
#covered(element, stack, hold) {
|
|
133
|
+
const current = element.getAttribute(this.#attribute);
|
|
134
|
+
return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
|
|
135
|
+
}
|
|
136
|
+
#mark(element, stack) {
|
|
137
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
138
|
+
stack.forEach((hold, index) => {
|
|
139
|
+
const names = stack.slice(0, index).map((under) => under.record);
|
|
140
|
+
const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
|
|
141
|
+
const marker = hold.linked || beneath.length === 0 ? [] : [false];
|
|
142
|
+
records.set(
|
|
143
|
+
hold.record,
|
|
144
|
+
hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
|
|
145
|
+
);
|
|
146
|
+
});
|
|
147
|
+
for (const [name, recorded] of records) {
|
|
148
|
+
setAttributeIfChanged(element, name, recorded);
|
|
65
149
|
}
|
|
66
150
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
_BeforeCacheReset.#subscribers.delete(this);
|
|
70
|
-
if (_BeforeCacheReset.#subscribers.size > 0) return;
|
|
71
|
-
document.removeEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
|
|
151
|
+
#reflect(element, value) {
|
|
152
|
+
setAttributeIfChanged(element, this.#attribute, value);
|
|
72
153
|
}
|
|
73
154
|
};
|
|
74
155
|
|
|
75
|
-
// src/utils/focus_candidate.ts
|
|
76
156
|
function inheritsFieldsetDisabled(control) {
|
|
77
157
|
let fieldset = control.closest("fieldset[disabled]");
|
|
78
158
|
while (fieldset) {
|
|
@@ -82,8 +162,19 @@ function inheritsFieldsetDisabled(control) {
|
|
|
82
162
|
}
|
|
83
163
|
return false;
|
|
84
164
|
}
|
|
165
|
+
function unslotted(element) {
|
|
166
|
+
return element.assignedSlot === null && element.parentElement?.shadowRoot != null;
|
|
167
|
+
}
|
|
168
|
+
function flatTreeParent(element) {
|
|
169
|
+
if (unslotted(element)) return null;
|
|
170
|
+
const parent = element.assignedSlot ?? element.parentNode;
|
|
171
|
+
if (parent instanceof ShadowRoot) return parent.host;
|
|
172
|
+
return parent instanceof Element ? parent : null;
|
|
173
|
+
}
|
|
85
174
|
function canTakeFocus(element) {
|
|
86
|
-
|
|
175
|
+
for (let node = element; node; node = flatTreeParent(node)) {
|
|
176
|
+
if (unslotted(node) || node.matches("[hidden], [inert]")) return false;
|
|
177
|
+
}
|
|
87
178
|
if (element instanceof HTMLInputElement && element.type === "hidden") return false;
|
|
88
179
|
if (!("disabled" in element)) return true;
|
|
89
180
|
if (element.disabled) return false;
|
|
@@ -149,15 +240,47 @@ function firstTabStop(root) {
|
|
|
149
240
|
function hasTabStop(root) {
|
|
150
241
|
return firstTabStop(root) !== null;
|
|
151
242
|
}
|
|
243
|
+
function deepActiveElement(ownerDocument) {
|
|
244
|
+
let active = ownerDocument.activeElement;
|
|
245
|
+
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
|
|
246
|
+
return active;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
var ListenerSet = class {
|
|
250
|
+
#abort = new AbortController();
|
|
251
|
+
add(target, type, handler, options) {
|
|
252
|
+
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
253
|
+
}
|
|
254
|
+
dispose() {
|
|
255
|
+
this.#abort.abort();
|
|
256
|
+
this.#abort = new AbortController();
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
var FontLoadWatcher = class {
|
|
261
|
+
#listeners = new ListenerSet();
|
|
262
|
+
#onSettled;
|
|
263
|
+
#fonts = null;
|
|
264
|
+
constructor(run) {
|
|
265
|
+
this.#onSettled = () => run();
|
|
266
|
+
}
|
|
267
|
+
observe(element) {
|
|
268
|
+
const fonts = element.ownerDocument.fonts ?? null;
|
|
269
|
+
if (fonts === this.#fonts) return;
|
|
270
|
+
this.disconnect();
|
|
271
|
+
if (!fonts) return;
|
|
272
|
+
this.#fonts = fonts;
|
|
273
|
+
this.#listeners.add(fonts, "loadingdone", this.#onSettled);
|
|
274
|
+
this.#listeners.add(fonts, "loadingerror", this.#onSettled);
|
|
275
|
+
}
|
|
276
|
+
disconnect() {
|
|
277
|
+
this.#listeners.dispose();
|
|
278
|
+
this.#fonts = null;
|
|
279
|
+
}
|
|
280
|
+
};
|
|
152
281
|
|
|
153
|
-
// src/utils/frame_coalescer.ts
|
|
154
282
|
var FrameCoalescer = class {
|
|
155
283
|
#frame = null;
|
|
156
|
-
/**
|
|
157
|
-
* Runs `run` on the next frame, unless a frame is already pending — the first
|
|
158
|
-
* request of a burst wins and the rest are dropped. The pending frame is
|
|
159
|
-
* released before `run`, so `run` may request the next one.
|
|
160
|
-
*/
|
|
161
284
|
schedule(run) {
|
|
162
285
|
if (this.#frame !== null) return;
|
|
163
286
|
this.#frame = requestAnimationFrame(() => {
|
|
@@ -165,14 +288,6 @@ var FrameCoalescer = class {
|
|
|
165
288
|
run();
|
|
166
289
|
});
|
|
167
290
|
}
|
|
168
|
-
/**
|
|
169
|
-
* Drops the pending frame, and reaches the platform only when there is one.
|
|
170
|
-
*
|
|
171
|
-
* There is no handle value that stands for "nothing pending":
|
|
172
|
-
* `cancelAnimationFrame` takes an `unsigned long`, so a negative placeholder
|
|
173
|
-
* arrives as a large positive number that the same allocator can hand out, and
|
|
174
|
-
* an idle cancel would then drop a frame belonging to someone else.
|
|
175
|
-
*/
|
|
176
291
|
cancel() {
|
|
177
292
|
if (this.#frame === null) return;
|
|
178
293
|
cancelAnimationFrame(this.#frame);
|
|
@@ -180,18 +295,15 @@ var FrameCoalescer = class {
|
|
|
180
295
|
}
|
|
181
296
|
};
|
|
182
297
|
|
|
183
|
-
// src/utils/layout_observer.ts
|
|
184
298
|
var LayoutObserver = class {
|
|
185
299
|
#callback;
|
|
186
300
|
#resizeObserverFactory;
|
|
187
301
|
#resizeObserver = null;
|
|
188
302
|
#observingViewport = false;
|
|
189
303
|
#loadContainer = null;
|
|
190
|
-
/** Stable bound handler so add/removeEventListener target the same reference. */
|
|
191
304
|
#handleViewportResize = () => {
|
|
192
305
|
this.#callback();
|
|
193
306
|
};
|
|
194
|
-
/** Stable bound handler for the capture-phase `load`; see {@link observeDescendantLoads}. */
|
|
195
307
|
#handleDescendantLoad = () => {
|
|
196
308
|
this.#callback();
|
|
197
309
|
};
|
|
@@ -199,11 +311,6 @@ var LayoutObserver = class {
|
|
|
199
311
|
this.#callback = callback;
|
|
200
312
|
this.#resizeObserverFactory = options.resizeObserverFactory ?? (typeof ResizeObserver === "undefined" ? null : (cb) => new ResizeObserver(cb));
|
|
201
313
|
}
|
|
202
|
-
/**
|
|
203
|
-
* Starts observing an element's size. Repeated calls observe additional
|
|
204
|
-
* elements through the same shared observer. No-ops when no
|
|
205
|
-
* `ResizeObserver` implementation is available.
|
|
206
|
-
*/
|
|
207
314
|
observe(element) {
|
|
208
315
|
if (!this.#resizeObserverFactory) return;
|
|
209
316
|
if (!this.#resizeObserver) {
|
|
@@ -213,47 +320,28 @@ var LayoutObserver = class {
|
|
|
213
320
|
}
|
|
214
321
|
this.#resizeObserver.observe(element);
|
|
215
322
|
}
|
|
216
|
-
/** Stops observing a single element while leaving any others in place. */
|
|
217
323
|
unobserve(element) {
|
|
218
324
|
this.#resizeObserver?.unobserve(element);
|
|
219
325
|
}
|
|
220
|
-
/** Starts observing viewport resizes. Idempotent: the listener is added once. */
|
|
221
326
|
observeViewport() {
|
|
222
327
|
if (this.#observingViewport) return;
|
|
223
328
|
this.#observingViewport = true;
|
|
224
329
|
window.addEventListener("resize", this.#handleViewportResize);
|
|
225
330
|
}
|
|
226
|
-
/** Stops observing viewport resizes without affecting element observation. */
|
|
227
331
|
unobserveViewport() {
|
|
228
332
|
if (!this.#observingViewport) return;
|
|
229
333
|
this.#observingViewport = false;
|
|
230
334
|
window.removeEventListener("resize", this.#handleViewportResize);
|
|
231
335
|
}
|
|
232
|
-
/**
|
|
233
|
-
* Starts reporting a `load` from anywhere inside `container` — an image or a
|
|
234
|
-
* frame settling changes the box it sits in, and it measures as zero high until
|
|
235
|
-
* then. `load` does not bubble, so the subscription is a capture-phase listener
|
|
236
|
-
* on the container itself and nothing the caller spells.
|
|
237
|
-
*
|
|
238
|
-
* **One container at a time.** A further call moves the observation, so a widget
|
|
239
|
-
* whose content element is swapped at runtime releases the element it let go by
|
|
240
|
-
* naming the new one — there is no second place for the release to drift from.
|
|
241
|
-
*/
|
|
242
336
|
observeDescendantLoads(container) {
|
|
243
337
|
this.unobserveDescendantLoads();
|
|
244
338
|
this.#loadContainer = container;
|
|
245
339
|
container.addEventListener("load", this.#handleDescendantLoad, true);
|
|
246
340
|
}
|
|
247
|
-
/** Stops reporting descendant loads without affecting element or viewport observation. */
|
|
248
341
|
unobserveDescendantLoads() {
|
|
249
342
|
this.#loadContainer?.removeEventListener("load", this.#handleDescendantLoad, true);
|
|
250
343
|
this.#loadContainer = null;
|
|
251
344
|
}
|
|
252
|
-
/**
|
|
253
|
-
* Releases every observation: disconnects the {@link ResizeObserver} and removes
|
|
254
|
-
* the viewport and descendant-load listeners. Safe to call multiple times. Call
|
|
255
|
-
* this from a controller's `disconnect()`.
|
|
256
|
-
*/
|
|
257
345
|
disconnect() {
|
|
258
346
|
this.#resizeObserver?.disconnect();
|
|
259
347
|
this.#resizeObserver = null;
|
|
@@ -262,7 +350,6 @@ var LayoutObserver = class {
|
|
|
262
350
|
}
|
|
263
351
|
};
|
|
264
352
|
|
|
265
|
-
// src/utils/logical_scroll.ts
|
|
266
353
|
function isRtl(element) {
|
|
267
354
|
return window.getComputedStyle(element).direction === "rtl";
|
|
268
355
|
}
|
|
@@ -276,27 +363,25 @@ function logicalScrollMetrics(element, horizontal) {
|
|
|
276
363
|
return { position: Math.min(max, Math.max(0, position)), max };
|
|
277
364
|
}
|
|
278
365
|
|
|
279
|
-
// src/utils/microtask_coalescer.ts
|
|
280
366
|
var MicrotaskCoalescer = class {
|
|
281
367
|
#run;
|
|
282
368
|
#queued = false;
|
|
283
369
|
#active = false;
|
|
284
370
|
#generation = 0;
|
|
285
|
-
/** @param run - the single reconciliation pass, invoked at most once per batch. */
|
|
286
371
|
constructor(run) {
|
|
287
372
|
this.#run = run;
|
|
288
373
|
}
|
|
289
|
-
/** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
|
|
290
374
|
activate() {
|
|
291
375
|
this.#active = true;
|
|
292
376
|
}
|
|
293
|
-
/** Closes the window and drops any pending pass; call from `disconnect()`. */
|
|
294
377
|
cancel() {
|
|
295
378
|
this.#active = false;
|
|
296
379
|
this.#queued = false;
|
|
297
380
|
this.#generation += 1;
|
|
298
381
|
}
|
|
299
|
-
|
|
382
|
+
get pending() {
|
|
383
|
+
return this.#queued;
|
|
384
|
+
}
|
|
300
385
|
schedule() {
|
|
301
386
|
if (!this.#active || this.#queued) return;
|
|
302
387
|
this.#queued = true;
|
|
@@ -309,90 +394,300 @@ var MicrotaskCoalescer = class {
|
|
|
309
394
|
}
|
|
310
395
|
};
|
|
311
396
|
|
|
312
|
-
|
|
313
|
-
|
|
397
|
+
var MorphRenderWatcher = class {
|
|
398
|
+
#listeners = new ListenerSet();
|
|
399
|
+
#pass;
|
|
400
|
+
#element = null;
|
|
401
|
+
#onMorph = () => this.#pass.schedule();
|
|
402
|
+
constructor(run) {
|
|
403
|
+
this.#pass = new MicrotaskCoalescer(run);
|
|
404
|
+
}
|
|
405
|
+
observe(element) {
|
|
406
|
+
if (this.#element === element) return;
|
|
407
|
+
this.disconnect();
|
|
408
|
+
this.#element = element;
|
|
409
|
+
this.#pass.activate();
|
|
410
|
+
this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
|
|
411
|
+
}
|
|
412
|
+
schedule() {
|
|
413
|
+
this.#pass.schedule();
|
|
414
|
+
}
|
|
415
|
+
get pending() {
|
|
416
|
+
return this.#pass.pending;
|
|
417
|
+
}
|
|
418
|
+
disconnect() {
|
|
419
|
+
this.#listeners.dispose();
|
|
420
|
+
this.#pass.cancel();
|
|
421
|
+
this.#element = null;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
var StylePropertyLease = class _StylePropertyLease {
|
|
426
|
+
static #registry = sharedRegistry(
|
|
427
|
+
"stimeo-ui.style-property-lease.registry.v1",
|
|
428
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
|
|
429
|
+
);
|
|
314
430
|
#property;
|
|
315
|
-
#
|
|
316
|
-
|
|
317
|
-
constructor(property) {
|
|
431
|
+
#record;
|
|
432
|
+
#held = /* @__PURE__ */ new Set();
|
|
433
|
+
constructor(property, owner) {
|
|
318
434
|
this.#property = property;
|
|
435
|
+
this.#record = `data-${owner}-style-${property}-lease`;
|
|
436
|
+
const names = _StylePropertyLease.#registry.names;
|
|
437
|
+
names.set(property, (names.get(property) ?? /* @__PURE__ */ new Set()).add(this.#record));
|
|
319
438
|
}
|
|
320
|
-
/** Writes or removes the leased declaration while preserving its authored value. */
|
|
321
439
|
write(element, value, priority = "") {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
writtenValue: value,
|
|
331
|
-
writtenPriority: value === null ? "" : priority
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
this.#reflect(element, value, priority);
|
|
440
|
+
const stack = this.#stack(element);
|
|
441
|
+
const hold = this.#take(stack) ?? this.#acquire(element, stack);
|
|
442
|
+
this.#held.add(element);
|
|
443
|
+
const shows = !this.#covered(element, stack, hold);
|
|
444
|
+
hold.writtenValue = value;
|
|
445
|
+
hold.writtenPriority = value === null ? "" : priority;
|
|
446
|
+
this.#mark(element, stack);
|
|
447
|
+
if (shows) this.#show(element, value, hold.writtenPriority);
|
|
335
448
|
}
|
|
336
|
-
/** Returns one lease without overwriting a later consumer declaration. */
|
|
337
449
|
return(element) {
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
this.#
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
450
|
+
const held = this.#held.delete(element);
|
|
451
|
+
const known = _StylePropertyLease.#registry.stacks.get(element)?.has(this.#property);
|
|
452
|
+
const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
|
|
453
|
+
const hold = this.#take(stack);
|
|
454
|
+
if (!hold) return;
|
|
455
|
+
const owns = this.#carries(element, hold) && !this.#covered(element, stack, hold);
|
|
456
|
+
const index = stack.indexOf(hold);
|
|
457
|
+
stack.splice(index, 1);
|
|
458
|
+
const above = stack[index];
|
|
459
|
+
if (above) above.linked &&= hold.linked;
|
|
460
|
+
this.#mark(element, stack);
|
|
461
|
+
if (!owns) return;
|
|
462
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
463
|
+
if (below) this.#show(element, below.writtenValue, below.writtenPriority);
|
|
464
|
+
else this.#show(element, hold.originalValue, hold.originalPriority);
|
|
346
465
|
}
|
|
347
|
-
/** Returns every outstanding declaration lease. */
|
|
348
466
|
returnAll() {
|
|
349
|
-
for (const element of Array.from(this.#
|
|
467
|
+
for (const element of Array.from(this.#held)) this.return(element);
|
|
468
|
+
}
|
|
469
|
+
#recorded(element, name) {
|
|
470
|
+
try {
|
|
471
|
+
const parsed = JSON.parse(element.getAttribute(name) ?? "null");
|
|
472
|
+
if (!Array.isArray(parsed)) return null;
|
|
473
|
+
const [originalValue, originalPriority, writtenValue, writtenPriority, ...rest] = parsed;
|
|
474
|
+
if (typeof originalValue !== "string" || typeof originalPriority !== "string") return null;
|
|
475
|
+
if (typeof writtenValue !== "string" && writtenValue !== null) return null;
|
|
476
|
+
if (typeof writtenPriority !== "string") return null;
|
|
477
|
+
const linked = rest[0] !== false;
|
|
478
|
+
const beneath = linked ? rest : rest.slice(1);
|
|
479
|
+
if (!beneath.every((under) => typeof under === "string")) return null;
|
|
480
|
+
return { originalValue, originalPriority, writtenValue, writtenPriority, linked, beneath };
|
|
481
|
+
} catch {
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
350
484
|
}
|
|
351
|
-
|
|
352
|
-
|
|
485
|
+
#stack(element) {
|
|
486
|
+
const stacks = _StylePropertyLease.#registry.stacks;
|
|
487
|
+
const byProperty = stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
488
|
+
stacks.set(element, byProperty);
|
|
489
|
+
const stack = byProperty.get(this.#property) ?? this.#seed(element);
|
|
490
|
+
byProperty.set(this.#property, stack);
|
|
491
|
+
return stack;
|
|
492
|
+
}
|
|
493
|
+
#seed(element) {
|
|
494
|
+
const found = [];
|
|
495
|
+
for (const record of _StylePropertyLease.#registry.names.get(this.#property) ?? []) {
|
|
496
|
+
const read = this.#recorded(element, record);
|
|
497
|
+
if (read) found.push({ ...read, record });
|
|
498
|
+
}
|
|
499
|
+
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
500
|
+
return found.sort((one, other) => depth(one) - depth(other)).map((entry, index) => ({
|
|
501
|
+
lease: null,
|
|
502
|
+
record: entry.record,
|
|
503
|
+
writtenValue: entry.writtenValue,
|
|
504
|
+
writtenPriority: entry.writtenPriority,
|
|
505
|
+
originalValue: entry.originalValue,
|
|
506
|
+
originalPriority: entry.originalPriority,
|
|
507
|
+
linked: entry.linked && index > 0
|
|
508
|
+
}));
|
|
509
|
+
}
|
|
510
|
+
#take(stack) {
|
|
511
|
+
const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
|
|
512
|
+
if (hold) hold.lease = this;
|
|
513
|
+
return hold;
|
|
514
|
+
}
|
|
515
|
+
#acquire(element, stack) {
|
|
516
|
+
const top = stack.at(-1);
|
|
517
|
+
const over = top && this.#carries(element, top) ? top : void 0;
|
|
353
518
|
const style = element.style;
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
519
|
+
const hold = {
|
|
520
|
+
lease: this,
|
|
521
|
+
record: this.#record,
|
|
522
|
+
writtenValue: null,
|
|
523
|
+
writtenPriority: "",
|
|
524
|
+
originalValue: over ? over.originalValue : style.getPropertyValue(this.#property),
|
|
525
|
+
originalPriority: over ? over.originalPriority : style.getPropertyPriority(this.#property),
|
|
526
|
+
linked: over !== void 0
|
|
527
|
+
};
|
|
528
|
+
stack.push(hold);
|
|
529
|
+
return hold;
|
|
530
|
+
}
|
|
531
|
+
#covered(element, stack, hold) {
|
|
532
|
+
return stack.slice(stack.indexOf(hold) + 1).some((above) => this.#carries(element, above));
|
|
533
|
+
}
|
|
534
|
+
#mark(element, stack) {
|
|
535
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
536
|
+
stack.forEach((hold, index) => {
|
|
537
|
+
const names = stack.slice(0, index).map((under) => under.record);
|
|
538
|
+
const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
|
|
539
|
+
const marker = hold.linked || beneath.length === 0 ? [] : [false];
|
|
540
|
+
const { originalValue, originalPriority, writtenValue, writtenPriority } = hold;
|
|
541
|
+
records.set(
|
|
542
|
+
hold.record,
|
|
543
|
+
(writtenValue ?? "") === originalValue && writtenPriority === originalPriority && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([
|
|
544
|
+
originalValue,
|
|
545
|
+
originalPriority,
|
|
546
|
+
writtenValue,
|
|
547
|
+
writtenPriority,
|
|
548
|
+
...marker,
|
|
549
|
+
...beneath
|
|
550
|
+
])
|
|
551
|
+
);
|
|
552
|
+
});
|
|
553
|
+
for (const [name, recorded] of records) {
|
|
554
|
+
setAttributeIfChanged(element, name, recorded);
|
|
358
555
|
}
|
|
359
|
-
|
|
360
|
-
|
|
556
|
+
}
|
|
557
|
+
#carries(element, hold) {
|
|
558
|
+
return this.#holds(element, hold.writtenValue ?? "", hold.writtenPriority);
|
|
559
|
+
}
|
|
560
|
+
#holds(element, value, priority) {
|
|
561
|
+
const style = element.style;
|
|
562
|
+
return style.getPropertyValue(this.#property) === value && style.getPropertyPriority(this.#property) === priority;
|
|
563
|
+
}
|
|
564
|
+
#show(element, value, priority) {
|
|
565
|
+
if (this.#holds(element, value ?? "", priority)) return;
|
|
566
|
+
if (value === null) element.style.removeProperty(this.#property);
|
|
567
|
+
else element.style.setProperty(this.#property, value, priority);
|
|
361
568
|
}
|
|
362
569
|
};
|
|
363
570
|
|
|
364
|
-
|
|
365
|
-
|
|
571
|
+
function queryOpenDescendants(root, selector) {
|
|
572
|
+
const matches = [];
|
|
573
|
+
const roots = [root];
|
|
574
|
+
for (const scope of roots) {
|
|
575
|
+
matches.push(...scope.querySelectorAll(selector));
|
|
576
|
+
if (scope.nodeType === Node.ELEMENT_NODE) {
|
|
577
|
+
const shadow = scope.shadowRoot;
|
|
578
|
+
if (shadow) roots.push(shadow);
|
|
579
|
+
}
|
|
580
|
+
for (const element of scope.querySelectorAll("*")) {
|
|
581
|
+
if (element.shadowRoot) roots.push(element.shadowRoot);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return matches;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
function holdsFocus(element) {
|
|
588
|
+
return element.matches(":focus") || deepActiveElement(element.ownerDocument) === element;
|
|
589
|
+
}
|
|
590
|
+
var TabindexLoan = class _TabindexLoan {
|
|
591
|
+
static #registry = sharedRegistry(
|
|
592
|
+
"stimeo-ui.tabindex-loan.registry.v1",
|
|
593
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Set() })
|
|
594
|
+
);
|
|
366
595
|
#value;
|
|
596
|
+
#record;
|
|
597
|
+
#preserveFocus;
|
|
367
598
|
#lent = /* @__PURE__ */ new Set();
|
|
368
|
-
|
|
369
|
-
#beforeCache = new BeforeCacheReset(() => this.returnAll());
|
|
370
|
-
/**
|
|
371
|
-
* @param value - the `tabindex` to lend. `"-1"` (the default) is
|
|
372
|
-
* programmatically focusable but not a Tab stop; `"0"` is a real Tab stop,
|
|
373
|
-
* which a scroll region with no focusable content of its own needs.
|
|
374
|
-
*/
|
|
375
|
-
constructor(value = "-1") {
|
|
599
|
+
constructor(value, owner, options = {}) {
|
|
376
600
|
this.#value = value;
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
601
|
+
this.#record = `data-${owner}-tabindex-loan`;
|
|
602
|
+
this.#preserveFocus = options.preserveFocus === true;
|
|
603
|
+
_TabindexLoan.#registry.names.add(this.#record);
|
|
604
|
+
}
|
|
605
|
+
lend(element, options = {}) {
|
|
606
|
+
const stack = this.#stack(element);
|
|
607
|
+
const current = element.getAttribute("tabindex");
|
|
608
|
+
const held = stack.find((hold) => hold.loan === this) ?? stack.find(
|
|
609
|
+
(hold) => hold.loan === null && hold.record === this.#record && hold.value === this.#value
|
|
610
|
+
);
|
|
611
|
+
const linked = stack.at(-1)?.value === current;
|
|
612
|
+
if (!held && options.onlyIfUnfocusable && (current !== null || element.tabIndex >= 0)) return;
|
|
613
|
+
if (!held && current !== null && !linked) return;
|
|
382
614
|
this.#lent.add(element);
|
|
383
|
-
|
|
615
|
+
if (held) held.loan = this;
|
|
616
|
+
else stack.push({ loan: this, record: this.#record, value: this.#value, linked });
|
|
617
|
+
this.#mark(element, stack);
|
|
618
|
+
if (current === null || !held && current !== this.#value) {
|
|
619
|
+
element.setAttribute("tabindex", this.#value);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return(element) {
|
|
623
|
+
const stack = this.#stack(element);
|
|
624
|
+
const hold = stack.find((held) => held.loan === this) ?? stack.find(
|
|
625
|
+
(held) => held.loan === null && held.record === this.#record && held.value === this.#value
|
|
626
|
+
);
|
|
627
|
+
if (!hold) return false;
|
|
628
|
+
if (!this.#release(element, stack, hold, this.#preserveFocus)) {
|
|
629
|
+
hold.loan = this;
|
|
630
|
+
this.#lent.add(element);
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
this.#lent.delete(element);
|
|
634
|
+
return true;
|
|
384
635
|
}
|
|
385
|
-
/** Takes back every loan whose value is still the one that was lent. */
|
|
386
636
|
returnAll() {
|
|
387
|
-
for (const element of this.#lent)
|
|
388
|
-
|
|
637
|
+
for (const element of Array.from(this.#lent)) this.return(element);
|
|
638
|
+
}
|
|
639
|
+
reclaim(element) {
|
|
640
|
+
if (element.getAttribute(this.#record) !== this.#value) return;
|
|
641
|
+
const stack = this.#stack(element);
|
|
642
|
+
const hold = stack.find((held) => held.loan === null && held.record === this.#record);
|
|
643
|
+
if (hold && !holdsFocus(element)) this.#release(element, stack, hold);
|
|
644
|
+
}
|
|
645
|
+
reclaimWithin(root) {
|
|
646
|
+
for (const element of queryOpenDescendants(root, `[${this.#record}]`)) {
|
|
647
|
+
this.reclaim(element);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
#stack(element) {
|
|
651
|
+
const stacks = _TabindexLoan.#registry.stacks;
|
|
652
|
+
const stack = stacks.get(element) ?? this.#seed(element);
|
|
653
|
+
stacks.set(element, stack);
|
|
654
|
+
return stack;
|
|
655
|
+
}
|
|
656
|
+
#seed(element) {
|
|
657
|
+
const current = element.getAttribute("tabindex");
|
|
658
|
+
const holds = [];
|
|
659
|
+
for (const record of _TabindexLoan.#registry.names) {
|
|
660
|
+
const value = element.getAttribute(record);
|
|
661
|
+
if (value !== null) holds.push({ loan: null, record, value, linked: true });
|
|
662
|
+
}
|
|
663
|
+
holds.sort((one, other) => Number(one.value === current) - Number(other.value === current));
|
|
664
|
+
for (const [index, hold] of holds.entries()) hold.linked = index > 0;
|
|
665
|
+
return holds;
|
|
666
|
+
}
|
|
667
|
+
#release(element, stack, hold, preserveFocus = false) {
|
|
668
|
+
const current = element.getAttribute("tabindex");
|
|
669
|
+
const index = stack.indexOf(hold);
|
|
670
|
+
const owns = current === hold.value && !stack.slice(index + 1).some((above2) => above2.value === current);
|
|
671
|
+
if (owns && preserveFocus && holdsFocus(element)) return false;
|
|
672
|
+
stack.splice(index, 1);
|
|
673
|
+
const above = stack[index];
|
|
674
|
+
if (above) above.linked &&= hold.linked;
|
|
675
|
+
this.#mark(element, stack);
|
|
676
|
+
if (!owns) return true;
|
|
677
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
678
|
+
if (!below) element.removeAttribute("tabindex");
|
|
679
|
+
else if (below.value !== current) element.setAttribute("tabindex", below.value);
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
682
|
+
#mark(element, stack) {
|
|
683
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
684
|
+
for (const hold of stack) records.set(hold.record, hold.value);
|
|
685
|
+
for (const [name, recorded] of records) {
|
|
686
|
+
setAttributeIfChanged(element, name, recorded);
|
|
389
687
|
}
|
|
390
|
-
this.#lent.clear();
|
|
391
|
-
this.#beforeCache.deactivate();
|
|
392
688
|
}
|
|
393
689
|
};
|
|
394
690
|
|
|
395
|
-
// src/controllers/scroll_area_controller.ts
|
|
396
691
|
var EDGE_EPSILON = 1;
|
|
397
692
|
var ScrollAreaController = class extends Controller {
|
|
398
693
|
static targets = ["viewport"];
|
|
@@ -401,21 +696,22 @@ var ScrollAreaController = class extends Controller {
|
|
|
401
696
|
};
|
|
402
697
|
static events = ["reach"];
|
|
403
698
|
#layout = new LayoutObserver(() => this.#refresh());
|
|
404
|
-
#rebind = new
|
|
405
|
-
#
|
|
406
|
-
#
|
|
407
|
-
#
|
|
408
|
-
#
|
|
409
|
-
#
|
|
410
|
-
|
|
699
|
+
#rebind = new MorphRenderWatcher(() => this.#syncViewport());
|
|
700
|
+
#tabindex = new TabindexLoan("0", this.identifier);
|
|
701
|
+
#role = new AttributeLease("role", this.identifier);
|
|
702
|
+
#overflowState = new AttributeLease("data-overflow", this.identifier);
|
|
703
|
+
#scrollState = new AttributeLease("data-scroll", this.identifier);
|
|
704
|
+
#progress = new StylePropertyLease(
|
|
705
|
+
"--stimeo--scroll-progress",
|
|
706
|
+
this.identifier
|
|
707
|
+
);
|
|
411
708
|
#viewport = null;
|
|
709
|
+
#viewportListeners = new ListenerSet();
|
|
412
710
|
#content = null;
|
|
413
711
|
#nameSources = null;
|
|
414
712
|
#nameGraph = null;
|
|
415
713
|
#observedNameIds = /* @__PURE__ */ new Set();
|
|
416
714
|
#observedNameSources = [];
|
|
417
|
-
#fonts = null;
|
|
418
|
-
/** Coalesces scroll bursts into one position sync per frame. */
|
|
419
715
|
#frames = new FrameCoalescer();
|
|
420
716
|
#overflowing = false;
|
|
421
717
|
#lastEdge = null;
|
|
@@ -427,40 +723,33 @@ var ScrollAreaController = class extends Controller {
|
|
|
427
723
|
#onFontsSettled = () => {
|
|
428
724
|
this.#refresh();
|
|
429
725
|
};
|
|
726
|
+
#fonts = new FontLoadWatcher(this.#onFontsSettled);
|
|
430
727
|
connect() {
|
|
431
|
-
this.#
|
|
432
|
-
this.#rebind.activate();
|
|
728
|
+
this.#rebind.observe(this.element);
|
|
433
729
|
this.#layout.observeViewport();
|
|
434
|
-
this.#
|
|
730
|
+
this.#fonts.observe(this.element);
|
|
435
731
|
this.#syncViewport();
|
|
436
732
|
}
|
|
437
733
|
disconnect() {
|
|
438
|
-
this.#
|
|
439
|
-
this.#rebind.cancel();
|
|
440
|
-
this.#frames.cancel();
|
|
734
|
+
this.#rebind.disconnect();
|
|
441
735
|
if (this.#viewport) this.#unbindViewport(this.#viewport);
|
|
442
736
|
this.#layout.disconnect();
|
|
443
|
-
this.#
|
|
737
|
+
this.#fonts.disconnect();
|
|
444
738
|
this.#clearHostState();
|
|
445
739
|
}
|
|
446
|
-
/** Re-measures when a retained viewport's orientation Value is morphed. */
|
|
447
740
|
orientationValueChanged() {
|
|
448
741
|
this.#refresh();
|
|
449
742
|
}
|
|
450
|
-
/** Schedules a complete resource rebind for a runtime viewport target. */
|
|
451
743
|
viewportTargetConnected() {
|
|
452
744
|
this.#rebind.schedule();
|
|
453
745
|
}
|
|
454
|
-
/** Schedules cleanup or replacement binding after a viewport leaves. */
|
|
455
746
|
viewportTargetDisconnected() {
|
|
456
747
|
this.#rebind.schedule();
|
|
457
748
|
}
|
|
458
|
-
/** Rebinds every viewport-owned resource against the final target in the mutation batch. */
|
|
459
749
|
#syncViewport() {
|
|
460
750
|
const next = this.hasViewportTarget ? this.viewportTarget : null;
|
|
461
751
|
if (next === this.#viewport) {
|
|
462
752
|
if (next) this.#refresh();
|
|
463
|
-
else this.#clearHostState();
|
|
464
753
|
return;
|
|
465
754
|
}
|
|
466
755
|
if (this.#viewport) this.#unbindViewport(this.#viewport);
|
|
@@ -469,13 +758,12 @@ var ScrollAreaController = class extends Controller {
|
|
|
469
758
|
this.#clearHostState();
|
|
470
759
|
return;
|
|
471
760
|
}
|
|
472
|
-
|
|
761
|
+
this.#viewportListeners.add(next, "scroll", this.#onScroll, { passive: true });
|
|
473
762
|
this.#layout.observeDescendantLoads(next);
|
|
474
763
|
this.#layout.observe(next);
|
|
475
764
|
this.#bindContentObserver(next);
|
|
476
765
|
this.#refresh();
|
|
477
766
|
}
|
|
478
|
-
/** Observes structural and attribute changes that can alter overflow or Tab stops. */
|
|
479
767
|
#bindContentObserver(viewport) {
|
|
480
768
|
this.#content = new MutationObserver((records) => {
|
|
481
769
|
if (this.#viewport !== viewport || !this.#hasRelevantContentMutation(records)) return;
|
|
@@ -488,7 +776,6 @@ var ScrollAreaController = class extends Controller {
|
|
|
488
776
|
characterData: true
|
|
489
777
|
});
|
|
490
778
|
}
|
|
491
|
-
/** Ignores only state-hook mutations whose exact value this controller just wrote. */
|
|
492
779
|
#hasRelevantContentMutation(records) {
|
|
493
780
|
let relevant = false;
|
|
494
781
|
const consumed = /* @__PURE__ */ new Set();
|
|
@@ -503,10 +790,9 @@ var ScrollAreaController = class extends Controller {
|
|
|
503
790
|
for (const attribute of consumed) this.#ownedHostMutations.delete(attribute);
|
|
504
791
|
return relevant;
|
|
505
792
|
}
|
|
506
|
-
/** Releases every resource and borrowed attribute owned by one former viewport. */
|
|
507
793
|
#unbindViewport(viewport) {
|
|
508
794
|
this.#frames.cancel();
|
|
509
|
-
|
|
795
|
+
this.#viewportListeners.dispose();
|
|
510
796
|
this.#layout.unobserveDescendantLoads();
|
|
511
797
|
this.#layout.unobserve(viewport);
|
|
512
798
|
this.#content?.disconnect();
|
|
@@ -518,11 +804,6 @@ var ScrollAreaController = class extends Controller {
|
|
|
518
804
|
this.#overflowing = false;
|
|
519
805
|
this.#lastEdge = null;
|
|
520
806
|
}
|
|
521
|
-
/**
|
|
522
|
-
* Runs the full structural and positional measurement pass.
|
|
523
|
-
*
|
|
524
|
-
* @stimeoRenderRoot
|
|
525
|
-
*/
|
|
526
807
|
#refresh() {
|
|
527
808
|
const viewport = this.#viewport;
|
|
528
809
|
if (!viewport) return;
|
|
@@ -532,13 +813,11 @@ var ScrollAreaController = class extends Controller {
|
|
|
532
813
|
this.#syncKeyboardReach(viewport, this.#overflowing);
|
|
533
814
|
this.#syncPosition(viewport, this.#overflowing);
|
|
534
815
|
}
|
|
535
|
-
/** Measures overflow and reflects the state hook without identical DOM writes. */
|
|
536
816
|
#syncOverflow(viewport) {
|
|
537
817
|
const overflowing = this.#measureOverflow(viewport);
|
|
538
818
|
this.#writeHostAttribute(this.#overflowState, "data-overflow", overflowing ? "true" : "false");
|
|
539
819
|
return overflowing;
|
|
540
820
|
}
|
|
541
|
-
/** Measures the primary-axis position and dispatches a newly established edge. */
|
|
542
821
|
#syncPosition(viewport, overflowing) {
|
|
543
822
|
const { position, progress } = this.#measurePosition(viewport);
|
|
544
823
|
this.#writeHostAttribute(this.#scrollState, "data-scroll", position);
|
|
@@ -548,41 +827,40 @@ var ScrollAreaController = class extends Controller {
|
|
|
548
827
|
this.#lastEdge = edge;
|
|
549
828
|
if (edge) this.dispatch("reach", { detail: { edge } });
|
|
550
829
|
}
|
|
551
|
-
/** Writes one leased host attribute and records self-generated observer input. */
|
|
552
830
|
#writeHostAttribute(lease, attribute, value) {
|
|
831
|
+
const record = `data-${this.identifier}-${attribute}-lease`;
|
|
553
832
|
const before = this.element.getAttribute(attribute);
|
|
833
|
+
const recordBefore = this.element.getAttribute(record);
|
|
554
834
|
lease.write(this.element, value);
|
|
555
835
|
this.#recordOwnedHostMutation(attribute, before);
|
|
836
|
+
this.#recordOwnedHostMutation(record, recordBefore);
|
|
556
837
|
}
|
|
557
|
-
/** Writes the leased progress property and records its serialized style mutation. */
|
|
558
838
|
#writeHostProgress(value) {
|
|
839
|
+
const record = `data-${this.identifier}-style---stimeo--scroll-progress-lease`;
|
|
559
840
|
const before = this.element.getAttribute("style");
|
|
841
|
+
const recordBefore = this.element.getAttribute(record);
|
|
560
842
|
this.#progress.write(this.element, value);
|
|
561
843
|
this.#recordOwnedHostMutation("style", before);
|
|
844
|
+
this.#recordOwnedHostMutation(record, recordBefore);
|
|
562
845
|
}
|
|
563
|
-
/** Records an exact host mutation only when the host is also the observed viewport. */
|
|
564
846
|
#recordOwnedHostMutation(attribute, before) {
|
|
565
847
|
if (this.#viewport !== this.element) return;
|
|
566
848
|
const after = this.element.getAttribute(attribute);
|
|
567
849
|
if (after !== before) this.#ownedHostMutations.set(attribute, after);
|
|
568
850
|
}
|
|
569
|
-
/** Returns host hooks to authored values and clears edge bookkeeping. */
|
|
570
851
|
#clearHostState() {
|
|
571
852
|
this.#overflowState.returnAll();
|
|
572
853
|
this.#scrollState.returnAll();
|
|
573
854
|
this.#progress.returnAll();
|
|
574
|
-
this.#ownedHostMutations.clear();
|
|
575
855
|
this.#overflowing = false;
|
|
576
856
|
this.#lastEdge = null;
|
|
577
857
|
}
|
|
578
|
-
/** Whether the configured axis currently has a scroll range. */
|
|
579
858
|
#measureOverflow(viewport) {
|
|
580
859
|
const orientation = this.orientationValue;
|
|
581
860
|
const vertical = orientation !== "horizontal" && viewport.scrollHeight > viewport.clientHeight + EDGE_EPSILON;
|
|
582
861
|
const horizontal = orientation !== "vertical" && viewport.scrollWidth > viewport.clientWidth + EDGE_EPSILON;
|
|
583
862
|
return vertical || horizontal;
|
|
584
863
|
}
|
|
585
|
-
/** Reports the primary-axis position bucket and normalized 0–1 progress. */
|
|
586
864
|
#measurePosition(viewport) {
|
|
587
865
|
const horizontalPrimary = this.orientationValue === "horizontal" || this.orientationValue === "both" && viewport.scrollHeight <= viewport.clientHeight + EDGE_EPSILON;
|
|
588
866
|
const { position: scrollPosition, max: maxScroll } = logicalScrollMetrics(
|
|
@@ -595,7 +873,6 @@ var ScrollAreaController = class extends Controller {
|
|
|
595
873
|
if (scrollPosition >= maxScroll - EDGE_EPSILON) return { position: "end", progress };
|
|
596
874
|
return { position: "middle", progress };
|
|
597
875
|
}
|
|
598
|
-
/** Borrows keyboard reach only when no usable descendant already owns a Tab stop. */
|
|
599
876
|
#syncKeyboardReach(viewport, overflowing) {
|
|
600
877
|
const wantsTabindex = overflowing && !hasTabStop(viewport);
|
|
601
878
|
if (!wantsTabindex) {
|
|
@@ -606,15 +883,17 @@ var ScrollAreaController = class extends Controller {
|
|
|
606
883
|
if (this.#hasAccessibleName(viewport)) {
|
|
607
884
|
if (!viewport.hasAttribute("role")) this.#role.write(viewport, "region");
|
|
608
885
|
} else {
|
|
609
|
-
this.#
|
|
886
|
+
this.#returnRole(viewport);
|
|
610
887
|
}
|
|
611
888
|
}
|
|
612
|
-
/** Returns only the viewport attributes borrowed by this controller. */
|
|
613
889
|
#clearViewportAttributes(viewport) {
|
|
614
890
|
this.#tabindex.returnAll();
|
|
891
|
+
this.#tabindex.reclaim(viewport);
|
|
892
|
+
this.#returnRole(viewport);
|
|
893
|
+
}
|
|
894
|
+
#returnRole(viewport) {
|
|
615
895
|
this.#role.return(viewport);
|
|
616
896
|
}
|
|
617
|
-
/** Whether the viewport already has a non-empty accessible name. */
|
|
618
897
|
#hasAccessibleName(viewport) {
|
|
619
898
|
const sources = this.#resolveNameSources(viewport);
|
|
620
899
|
if (sources.length > 0) {
|
|
@@ -625,21 +904,15 @@ var ScrollAreaController = class extends Controller {
|
|
|
625
904
|
}
|
|
626
905
|
return Boolean(viewport.getAttribute("aria-label")?.trim());
|
|
627
906
|
}
|
|
628
|
-
/** Resolves unique, live `aria-labelledby` references in authored order. */
|
|
629
907
|
#resolveNameSources(viewport) {
|
|
630
908
|
const ids = this.#nameReferenceIds(viewport);
|
|
631
909
|
const sources = [];
|
|
632
|
-
const seen = /* @__PURE__ */ new Set();
|
|
633
910
|
for (const id of ids) {
|
|
634
911
|
const source = viewport.ownerDocument.getElementById(id);
|
|
635
|
-
if (source
|
|
636
|
-
seen.add(source);
|
|
637
|
-
sources.push(source);
|
|
638
|
-
}
|
|
912
|
+
if (source) sources.push(source);
|
|
639
913
|
}
|
|
640
914
|
return sources;
|
|
641
915
|
}
|
|
642
|
-
/** Observes external name sources so a retained region never becomes unnamed. */
|
|
643
916
|
#syncNameSources(viewport) {
|
|
644
917
|
const ids = this.#nameReferenceIds(viewport);
|
|
645
918
|
const sources = this.#resolveNameSources(viewport).filter(
|
|
@@ -681,12 +954,10 @@ var ScrollAreaController = class extends Controller {
|
|
|
681
954
|
});
|
|
682
955
|
}
|
|
683
956
|
}
|
|
684
|
-
/** Returns normalized unique label-reference ids in authored order. */
|
|
685
957
|
#nameReferenceIds(viewport) {
|
|
686
958
|
const tokens = viewport.getAttribute("aria-labelledby")?.trim().split(/\s+/).filter(Boolean);
|
|
687
959
|
return Array.from(new Set(tokens));
|
|
688
960
|
}
|
|
689
|
-
/** Whether document-graph changes can resolve or invalidate a referenced id. */
|
|
690
961
|
#hasRelevantNameGraphMutation(records) {
|
|
691
962
|
for (const record of records) {
|
|
692
963
|
if (record.type === "attributes") {
|
|
@@ -702,7 +973,6 @@ var ScrollAreaController = class extends Controller {
|
|
|
702
973
|
}
|
|
703
974
|
return false;
|
|
704
975
|
}
|
|
705
|
-
/** Whether a changed subtree contains one of the current label-reference ids. */
|
|
706
976
|
#nodeContainsObservedNameId(node) {
|
|
707
977
|
if (!(node instanceof Element)) return false;
|
|
708
978
|
if (this.#observedNameIds.has(node.id)) return true;
|
|
@@ -710,7 +980,6 @@ var ScrollAreaController = class extends Controller {
|
|
|
710
980
|
(element) => this.#observedNameIds.has(element.id)
|
|
711
981
|
);
|
|
712
982
|
}
|
|
713
|
-
/** Stops observing accessible-name sources. */
|
|
714
983
|
#disconnectNameSources() {
|
|
715
984
|
this.#nameSources?.disconnect();
|
|
716
985
|
this.#nameSources = null;
|
|
@@ -719,32 +988,7 @@ var ScrollAreaController = class extends Controller {
|
|
|
719
988
|
this.#observedNameIds.clear();
|
|
720
989
|
this.#observedNameSources = [];
|
|
721
990
|
}
|
|
722
|
-
/** Subscribes to font completion when the current engine exposes `document.fonts`. */
|
|
723
|
-
#bindFonts() {
|
|
724
|
-
const fonts = this.element.ownerDocument.fonts;
|
|
725
|
-
if (!fonts || this.#fonts === fonts) return;
|
|
726
|
-
this.#unbindFonts();
|
|
727
|
-
this.#fonts = fonts;
|
|
728
|
-
fonts.addEventListener("loadingdone", this.#onFontsSettled);
|
|
729
|
-
fonts.addEventListener("loadingerror", this.#onFontsSettled);
|
|
730
|
-
}
|
|
731
|
-
/** Removes the font completion subscriptions. */
|
|
732
|
-
#unbindFonts() {
|
|
733
|
-
this.#fonts?.removeEventListener("loadingdone", this.#onFontsSettled);
|
|
734
|
-
this.#fonts?.removeEventListener("loadingerror", this.#onFontsSettled);
|
|
735
|
-
this.#fonts = null;
|
|
736
|
-
}
|
|
737
|
-
/** Suspends live resources and returns all derived state before snapshotting. */
|
|
738
|
-
#rewindForCache() {
|
|
739
|
-
this.#rebind.cancel();
|
|
740
|
-
this.#frames.cancel();
|
|
741
|
-
if (this.#viewport) this.#unbindViewport(this.#viewport);
|
|
742
|
-
this.#layout.disconnect();
|
|
743
|
-
this.#unbindFonts();
|
|
744
|
-
this.#clearHostState();
|
|
745
|
-
}
|
|
746
991
|
};
|
|
747
992
|
|
|
748
993
|
export { ScrollAreaController };
|
|
749
|
-
//# sourceMappingURL=scroll_area_controller.js.map
|
|
750
994
|
//# sourceMappingURL=scroll_area_controller.js.map
|