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,89 +1,192 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
var FOCUS_EVENTS = /* @__PURE__ */ new Set(["blur", "focus", "focusin", "focusout"]);
|
|
4
|
+
var POINTER_EVENTS = /* @__PURE__ */ new Set(["mouseenter", "mouseleave", "pointerenter", "pointerleave"]);
|
|
5
|
+
function stateReasonFor(event) {
|
|
6
|
+
if (!event) return "api";
|
|
7
|
+
if (FOCUS_EVENTS.has(event.type)) return "focus";
|
|
8
|
+
if (POINTER_EVENTS.has(event.type)) return "pointer";
|
|
9
|
+
return "user";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function actionSource(source) {
|
|
13
|
+
if (source instanceof HTMLElement) {
|
|
14
|
+
return { event: null, host: source, origin: source, reason: "api" };
|
|
15
|
+
}
|
|
16
|
+
const event = source ?? null;
|
|
17
|
+
return {
|
|
18
|
+
event,
|
|
19
|
+
host: event?.currentTarget instanceof Element ? event.currentTarget : null,
|
|
20
|
+
origin: event?.target instanceof Element ? event.target : null,
|
|
21
|
+
reason: stateReasonFor(event)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
4
24
|
|
|
5
|
-
// src/utils/logical_scroll.ts
|
|
6
25
|
function isRtl(element) {
|
|
7
26
|
return window.getComputedStyle(element).direction === "rtl";
|
|
8
27
|
}
|
|
9
28
|
|
|
10
|
-
// src/utils/arrow_step.ts
|
|
11
29
|
function isReservedArrowChord(event, allow = []) {
|
|
12
30
|
if (!event.key.startsWith("Arrow")) return false;
|
|
13
31
|
return event.altKey && !allow.includes("alt") || event.ctrlKey && !allow.includes("ctrl") || event.metaKey && !allow.includes("meta") || event.shiftKey && !allow.includes("shift");
|
|
14
32
|
}
|
|
33
|
+
function hasModifierChord(event) {
|
|
34
|
+
return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function setAttributeIfChanged(element, name, value, beforeWrite) {
|
|
38
|
+
if (element.getAttribute(name) === value) return false;
|
|
39
|
+
if (value === null) element.removeAttribute(name);
|
|
40
|
+
else element.setAttribute(name, value);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function sharedRegistry(key, create) {
|
|
45
|
+
const symbol = Symbol.for(key);
|
|
46
|
+
const scope = globalThis;
|
|
47
|
+
const existing = scope[symbol];
|
|
48
|
+
if (existing !== void 0) return existing;
|
|
49
|
+
const registry2 = create();
|
|
50
|
+
Object.defineProperty(globalThis, symbol, { value: registry2 });
|
|
51
|
+
return registry2;
|
|
52
|
+
}
|
|
15
53
|
|
|
16
|
-
|
|
54
|
+
var registry = sharedRegistry(
|
|
55
|
+
"stimeo-ui.attribute-lease.registry.v1",
|
|
56
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
|
|
57
|
+
);
|
|
58
|
+
function isAttributeValue(value) {
|
|
59
|
+
return value === null || typeof value === "string";
|
|
60
|
+
}
|
|
61
|
+
function readLeaseRecord(element, record) {
|
|
62
|
+
try {
|
|
63
|
+
const parsed = JSON.parse(element.getAttribute(record) ?? "null");
|
|
64
|
+
if (!Array.isArray(parsed)) return void 0;
|
|
65
|
+
const [original, written, ...rest] = parsed;
|
|
66
|
+
const linked = rest[0] !== false;
|
|
67
|
+
const beneath = linked ? rest : rest.slice(1);
|
|
68
|
+
if (!beneath.every((under) => typeof under === "string")) return void 0;
|
|
69
|
+
return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
|
|
70
|
+
} catch {
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function attributeStack(element, attribute) {
|
|
75
|
+
const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
76
|
+
registry.stacks.set(element, byAttribute);
|
|
77
|
+
const known = byAttribute.get(attribute);
|
|
78
|
+
if (known) return known;
|
|
79
|
+
const found = [];
|
|
80
|
+
for (const record of registry.names.get(attribute) ?? []) {
|
|
81
|
+
const read = readLeaseRecord(element, record);
|
|
82
|
+
if (read) found.push({ ...read, record });
|
|
83
|
+
}
|
|
84
|
+
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
85
|
+
const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
|
|
86
|
+
lease: null,
|
|
87
|
+
record,
|
|
88
|
+
written,
|
|
89
|
+
original,
|
|
90
|
+
linked: linked && index > 0
|
|
91
|
+
}));
|
|
92
|
+
byAttribute.set(attribute, stack);
|
|
93
|
+
return stack;
|
|
94
|
+
}
|
|
95
|
+
function findHold(stack, lease, record) {
|
|
96
|
+
return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
|
|
97
|
+
}
|
|
17
98
|
var AttributeLease = class {
|
|
18
99
|
#attribute;
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
100
|
+
#record;
|
|
101
|
+
#base;
|
|
102
|
+
#preserveAuthor;
|
|
103
|
+
#held = /* @__PURE__ */ new Set();
|
|
104
|
+
constructor(attribute, owner, options = {}) {
|
|
22
105
|
this.#attribute = attribute;
|
|
106
|
+
this.#record = `data-${owner}-${attribute}-lease`;
|
|
107
|
+
this.#base = options.base === true;
|
|
108
|
+
this.#preserveAuthor = options.preserveAuthor === true;
|
|
109
|
+
const names = registry.names;
|
|
110
|
+
names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
|
|
23
111
|
}
|
|
24
|
-
/** Writes or removes the leased attribute while preserving its authored value. */
|
|
25
112
|
write(element, value) {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
this.#reflect(element, value);
|
|
113
|
+
const stack = attributeStack(element, this.#attribute);
|
|
114
|
+
const hold = this.#take(stack) ?? this.#acquire(element, stack);
|
|
115
|
+
this.#held.add(element);
|
|
116
|
+
const shows = !this.#covered(element, stack, hold);
|
|
117
|
+
hold.written = value;
|
|
118
|
+
this.#mark(element, stack);
|
|
119
|
+
if (shows) this.#reflect(element, value);
|
|
36
120
|
}
|
|
37
|
-
/** Returns one lease without overwriting a value subsequently authored by a consumer. */
|
|
38
121
|
return(element) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
this.#
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
122
|
+
const held = this.#held.delete(element);
|
|
123
|
+
const known = registry.stacks.get(element)?.has(this.#attribute);
|
|
124
|
+
const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
|
|
125
|
+
const hold = this.#take(stack);
|
|
126
|
+
if (!hold) return false;
|
|
127
|
+
const carries = element.getAttribute(this.#attribute) === hold.written;
|
|
128
|
+
const owns = carries && !this.#covered(element, stack, hold);
|
|
129
|
+
const index = stack.indexOf(hold);
|
|
130
|
+
stack.splice(index, 1);
|
|
131
|
+
const above = stack[index];
|
|
132
|
+
if (above) above.linked &&= hold.linked;
|
|
133
|
+
this.#mark(element, stack);
|
|
134
|
+
if (!owns) return true;
|
|
135
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
136
|
+
this.#reflect(element, below ? below.written : hold.original);
|
|
137
|
+
return true;
|
|
44
138
|
}
|
|
45
|
-
/** Reflects only a real value transition, avoiding self-triggered mutation work. */
|
|
46
|
-
#reflect(element, value) {
|
|
47
|
-
if (element.getAttribute(this.#attribute) === value) return;
|
|
48
|
-
if (value === null) element.removeAttribute(this.#attribute);
|
|
49
|
-
else element.setAttribute(this.#attribute, value);
|
|
50
|
-
}
|
|
51
|
-
/** Returns every outstanding lease using the same ownership check as {@link return}. */
|
|
52
139
|
returnAll() {
|
|
53
|
-
for (const element of Array.from(this.#
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
140
|
+
for (const element of Array.from(this.#held)) this.return(element);
|
|
141
|
+
}
|
|
142
|
+
#take(stack) {
|
|
143
|
+
const hold = findHold(stack, this, this.#record);
|
|
144
|
+
if (hold) hold.lease = this;
|
|
145
|
+
return hold;
|
|
146
|
+
}
|
|
147
|
+
#acquire(element, stack) {
|
|
148
|
+
const current = element.getAttribute(this.#attribute);
|
|
149
|
+
const top = stack.at(-1);
|
|
150
|
+
const bottom = stack[0];
|
|
151
|
+
const over = top?.written === current ? top : void 0;
|
|
152
|
+
const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
|
|
153
|
+
const hold = {
|
|
154
|
+
lease: this,
|
|
155
|
+
record: this.#record,
|
|
156
|
+
written: current,
|
|
157
|
+
original: from ? from.original : current,
|
|
158
|
+
linked: !this.#base && over !== void 0
|
|
159
|
+
};
|
|
160
|
+
if (this.#base && bottom) {
|
|
161
|
+
bottom.linked = true;
|
|
162
|
+
stack.unshift(hold);
|
|
163
|
+
} else stack.push(hold);
|
|
164
|
+
return hold;
|
|
165
|
+
}
|
|
166
|
+
#covered(element, stack, hold) {
|
|
167
|
+
const current = element.getAttribute(this.#attribute);
|
|
168
|
+
return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
|
|
169
|
+
}
|
|
170
|
+
#mark(element, stack) {
|
|
171
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
172
|
+
stack.forEach((hold, index) => {
|
|
173
|
+
const names = stack.slice(0, index).map((under) => under.record);
|
|
174
|
+
const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
|
|
175
|
+
const marker = hold.linked || beneath.length === 0 ? [] : [false];
|
|
176
|
+
records.set(
|
|
177
|
+
hold.record,
|
|
178
|
+
hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
|
|
179
|
+
);
|
|
180
|
+
});
|
|
181
|
+
for (const [name, recorded] of records) {
|
|
182
|
+
setAttributeIfChanged(element, name, recorded);
|
|
76
183
|
}
|
|
77
184
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
_BeforeCacheReset.#subscribers.delete(this);
|
|
81
|
-
if (_BeforeCacheReset.#subscribers.size > 0) return;
|
|
82
|
-
document.removeEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
|
|
185
|
+
#reflect(element, value) {
|
|
186
|
+
setAttributeIfChanged(element, this.#attribute, value);
|
|
83
187
|
}
|
|
84
188
|
};
|
|
85
189
|
|
|
86
|
-
// src/utils/field_mirror.ts
|
|
87
190
|
function writeField(field, value) {
|
|
88
191
|
if (field.value === value) return false;
|
|
89
192
|
field.value = value;
|
|
@@ -93,27 +196,36 @@ function commitField(target) {
|
|
|
93
196
|
target.dispatchEvent(new Event("change", { bubbles: true }));
|
|
94
197
|
}
|
|
95
198
|
|
|
96
|
-
|
|
199
|
+
var ListenerSet = class {
|
|
200
|
+
#abort = new AbortController();
|
|
201
|
+
add(target, type, handler, options) {
|
|
202
|
+
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
203
|
+
}
|
|
204
|
+
dispose() {
|
|
205
|
+
this.#abort.abort();
|
|
206
|
+
this.#abort = new AbortController();
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
97
210
|
var MicrotaskCoalescer = class {
|
|
98
211
|
#run;
|
|
99
212
|
#queued = false;
|
|
100
213
|
#active = false;
|
|
101
214
|
#generation = 0;
|
|
102
|
-
/** @param run - the single reconciliation pass, invoked at most once per batch. */
|
|
103
215
|
constructor(run) {
|
|
104
216
|
this.#run = run;
|
|
105
217
|
}
|
|
106
|
-
/** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
|
|
107
218
|
activate() {
|
|
108
219
|
this.#active = true;
|
|
109
220
|
}
|
|
110
|
-
/** Closes the window and drops any pending pass; call from `disconnect()`. */
|
|
111
221
|
cancel() {
|
|
112
222
|
this.#active = false;
|
|
113
223
|
this.#queued = false;
|
|
114
224
|
this.#generation += 1;
|
|
115
225
|
}
|
|
116
|
-
|
|
226
|
+
get pending() {
|
|
227
|
+
return this.#queued;
|
|
228
|
+
}
|
|
117
229
|
schedule() {
|
|
118
230
|
if (!this.#active || this.#queued) return;
|
|
119
231
|
this.#queued = true;
|
|
@@ -126,31 +238,97 @@ var MicrotaskCoalescer = class {
|
|
|
126
238
|
}
|
|
127
239
|
};
|
|
128
240
|
|
|
129
|
-
|
|
241
|
+
var MorphRenderWatcher = class {
|
|
242
|
+
#listeners = new ListenerSet();
|
|
243
|
+
#pass;
|
|
244
|
+
#element = null;
|
|
245
|
+
#onMorph = () => this.#pass.schedule();
|
|
246
|
+
constructor(run) {
|
|
247
|
+
this.#pass = new MicrotaskCoalescer(run);
|
|
248
|
+
}
|
|
249
|
+
observe(element) {
|
|
250
|
+
if (this.#element === element) return;
|
|
251
|
+
this.disconnect();
|
|
252
|
+
this.#element = element;
|
|
253
|
+
this.#pass.activate();
|
|
254
|
+
this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
|
|
255
|
+
}
|
|
256
|
+
schedule() {
|
|
257
|
+
this.#pass.schedule();
|
|
258
|
+
}
|
|
259
|
+
get pending() {
|
|
260
|
+
return this.#pass.pending;
|
|
261
|
+
}
|
|
262
|
+
disconnect() {
|
|
263
|
+
this.#listeners.dispose();
|
|
264
|
+
this.#pass.cancel();
|
|
265
|
+
this.#element = null;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
var MoveCounter = class {
|
|
270
|
+
#sequence = 0;
|
|
271
|
+
record() {
|
|
272
|
+
this.#sequence += 1;
|
|
273
|
+
return this.#sequence;
|
|
274
|
+
}
|
|
275
|
+
isLatest(token) {
|
|
276
|
+
return token === this.#sequence;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
var NUMBER_BOUNDS = {
|
|
281
|
+
finite: { finite: true }};
|
|
282
|
+
function matchesNumberBounds(value, bounds) {
|
|
283
|
+
if (!Number.isFinite(value)) {
|
|
284
|
+
const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
|
|
285
|
+
if (direction === null) return false;
|
|
286
|
+
if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
|
|
287
|
+
}
|
|
288
|
+
if (bounds.min !== void 0 && value < bounds.min) return false;
|
|
289
|
+
if (bounds.max !== void 0 && value > bounds.max) return false;
|
|
290
|
+
if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
|
|
291
|
+
if (bounds.integer && !Number.isInteger(value)) return false;
|
|
292
|
+
if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function readNumber(raw, fallback, bounds) {
|
|
297
|
+
return matchesNumberBounds(raw, bounds) ? raw : fallback;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
var NumberValueReader = class {
|
|
301
|
+
#lastRejected = /* @__PURE__ */ new Map();
|
|
302
|
+
read(owner, name, raw, fallback, bounds) {
|
|
303
|
+
const resolved = readNumber(raw, fallback, bounds);
|
|
304
|
+
if (matchesNumberBounds(raw, bounds)) {
|
|
305
|
+
this.#lastRejected.delete(name);
|
|
306
|
+
return resolved;
|
|
307
|
+
}
|
|
308
|
+
const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
|
|
309
|
+
const literal = owner.element.getAttribute(attribute);
|
|
310
|
+
if (literal === null) {
|
|
311
|
+
this.#lastRejected.delete(name);
|
|
312
|
+
return resolved;
|
|
313
|
+
}
|
|
314
|
+
if (this.#lastRejected.get(name) !== literal) {
|
|
315
|
+
this.#lastRejected.set(name, literal);
|
|
316
|
+
console.warn(
|
|
317
|
+
`Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
return resolved;
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
|
|
130
324
|
var RovingTabindex = class {
|
|
131
|
-
/** Returns the current ordered item elements; called on every operation. */
|
|
132
325
|
#getItems;
|
|
133
|
-
/**
|
|
134
|
-
* @param getItems - Returns the current ordered item elements. Called on every
|
|
135
|
-
* operation so the live target list is always used.
|
|
136
|
-
*/
|
|
137
326
|
constructor(getItems) {
|
|
138
327
|
this.#getItems = getItems;
|
|
139
328
|
}
|
|
140
|
-
/** Index of the currently tabbable item (`tabindex="0"`), or `-1` if none. */
|
|
141
329
|
get activeIndex() {
|
|
142
330
|
return this.#getItems().findIndex((item) => item.tabIndex === 0);
|
|
143
331
|
}
|
|
144
|
-
/**
|
|
145
|
-
* Makes exactly the item at `index` tabbable (`tabindex="0"`) and removes every
|
|
146
|
-
* other item from the Tab sequence (`tabindex="-1"`). An out-of-range `index`
|
|
147
|
-
* (e.g. `-1`) leaves all items at `-1`, which a controller can use to express
|
|
148
|
-
* "nothing is currently tabbable".
|
|
149
|
-
*
|
|
150
|
-
* @param index - Position of the item to make tabbable.
|
|
151
|
-
* @param options - Pass `{ focus: true }` to also move DOM focus to that item,
|
|
152
|
-
* and `items` to reuse an event-scoped collection snapshot.
|
|
153
|
-
*/
|
|
154
332
|
setActive(index, options = {}) {
|
|
155
333
|
const { focus = false } = options;
|
|
156
334
|
const items = options.items ?? this.#getItems();
|
|
@@ -160,131 +338,234 @@ var RovingTabindex = class {
|
|
|
160
338
|
if (focus) items[index]?.focus();
|
|
161
339
|
}
|
|
162
340
|
};
|
|
341
|
+
function deepActiveElement(ownerDocument) {
|
|
342
|
+
let active = ownerDocument.activeElement;
|
|
343
|
+
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
|
|
344
|
+
return active;
|
|
345
|
+
}
|
|
163
346
|
|
|
164
|
-
|
|
165
|
-
|
|
347
|
+
function queryOpenDescendants(root, selector) {
|
|
348
|
+
const matches = [];
|
|
349
|
+
const roots = [root];
|
|
350
|
+
for (const scope of roots) {
|
|
351
|
+
matches.push(...scope.querySelectorAll(selector));
|
|
352
|
+
if (scope.nodeType === Node.ELEMENT_NODE) {
|
|
353
|
+
const shadow = scope.shadowRoot;
|
|
354
|
+
if (shadow) roots.push(shadow);
|
|
355
|
+
}
|
|
356
|
+
for (const element of scope.querySelectorAll("*")) {
|
|
357
|
+
if (element.shadowRoot) roots.push(element.shadowRoot);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return matches;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function holdsFocus(element) {
|
|
364
|
+
return element.matches(":focus") || deepActiveElement(element.ownerDocument) === element;
|
|
365
|
+
}
|
|
366
|
+
var TabindexLoan = class _TabindexLoan {
|
|
367
|
+
static #registry = sharedRegistry(
|
|
368
|
+
"stimeo-ui.tabindex-loan.registry.v1",
|
|
369
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Set() })
|
|
370
|
+
);
|
|
166
371
|
#value;
|
|
372
|
+
#record;
|
|
373
|
+
#preserveFocus;
|
|
167
374
|
#lent = /* @__PURE__ */ new Set();
|
|
168
|
-
|
|
169
|
-
#beforeCache = new BeforeCacheReset(() => this.returnAll());
|
|
170
|
-
/**
|
|
171
|
-
* @param value - the `tabindex` to lend. `"-1"` (the default) is
|
|
172
|
-
* programmatically focusable but not a Tab stop; `"0"` is a real Tab stop,
|
|
173
|
-
* which a scroll region with no focusable content of its own needs.
|
|
174
|
-
*/
|
|
175
|
-
constructor(value = "-1") {
|
|
375
|
+
constructor(value, owner, options = {}) {
|
|
176
376
|
this.#value = value;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
377
|
+
this.#record = `data-${owner}-tabindex-loan`;
|
|
378
|
+
this.#preserveFocus = options.preserveFocus === true;
|
|
379
|
+
_TabindexLoan.#registry.names.add(this.#record);
|
|
380
|
+
}
|
|
381
|
+
lend(element, options = {}) {
|
|
382
|
+
const stack = this.#stack(element);
|
|
383
|
+
const current = element.getAttribute("tabindex");
|
|
384
|
+
const held = stack.find((hold) => hold.loan === this) ?? stack.find(
|
|
385
|
+
(hold) => hold.loan === null && hold.record === this.#record && hold.value === this.#value
|
|
386
|
+
);
|
|
387
|
+
const linked = stack.at(-1)?.value === current;
|
|
388
|
+
if (!held && options.onlyIfUnfocusable && (current !== null || element.tabIndex >= 0)) return;
|
|
389
|
+
if (!held && current !== null && !linked) return;
|
|
182
390
|
this.#lent.add(element);
|
|
183
|
-
|
|
391
|
+
if (held) held.loan = this;
|
|
392
|
+
else stack.push({ loan: this, record: this.#record, value: this.#value, linked });
|
|
393
|
+
this.#mark(element, stack);
|
|
394
|
+
if (current === null || !held && current !== this.#value) {
|
|
395
|
+
element.setAttribute("tabindex", this.#value);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return(element) {
|
|
399
|
+
const stack = this.#stack(element);
|
|
400
|
+
const hold = stack.find((held) => held.loan === this) ?? stack.find(
|
|
401
|
+
(held) => held.loan === null && held.record === this.#record && held.value === this.#value
|
|
402
|
+
);
|
|
403
|
+
if (!hold) return false;
|
|
404
|
+
if (!this.#release(element, stack, hold, this.#preserveFocus)) {
|
|
405
|
+
hold.loan = this;
|
|
406
|
+
this.#lent.add(element);
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
this.#lent.delete(element);
|
|
410
|
+
return true;
|
|
184
411
|
}
|
|
185
|
-
/** Takes back every loan whose value is still the one that was lent. */
|
|
186
412
|
returnAll() {
|
|
187
|
-
for (const element of this.#lent)
|
|
188
|
-
|
|
413
|
+
for (const element of Array.from(this.#lent)) this.return(element);
|
|
414
|
+
}
|
|
415
|
+
reclaim(element) {
|
|
416
|
+
if (element.getAttribute(this.#record) !== this.#value) return;
|
|
417
|
+
const stack = this.#stack(element);
|
|
418
|
+
const hold = stack.find((held) => held.loan === null && held.record === this.#record);
|
|
419
|
+
if (hold && !holdsFocus(element)) this.#release(element, stack, hold);
|
|
420
|
+
}
|
|
421
|
+
reclaimWithin(root) {
|
|
422
|
+
for (const element of queryOpenDescendants(root, `[${this.#record}]`)) {
|
|
423
|
+
this.reclaim(element);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
#stack(element) {
|
|
427
|
+
const stacks = _TabindexLoan.#registry.stacks;
|
|
428
|
+
const stack = stacks.get(element) ?? this.#seed(element);
|
|
429
|
+
stacks.set(element, stack);
|
|
430
|
+
return stack;
|
|
431
|
+
}
|
|
432
|
+
#seed(element) {
|
|
433
|
+
const current = element.getAttribute("tabindex");
|
|
434
|
+
const holds = [];
|
|
435
|
+
for (const record of _TabindexLoan.#registry.names) {
|
|
436
|
+
const value = element.getAttribute(record);
|
|
437
|
+
if (value !== null) holds.push({ loan: null, record, value, linked: true });
|
|
438
|
+
}
|
|
439
|
+
holds.sort((one, other) => Number(one.value === current) - Number(other.value === current));
|
|
440
|
+
for (const [index, hold] of holds.entries()) hold.linked = index > 0;
|
|
441
|
+
return holds;
|
|
442
|
+
}
|
|
443
|
+
#release(element, stack, hold, preserveFocus = false) {
|
|
444
|
+
const current = element.getAttribute("tabindex");
|
|
445
|
+
const index = stack.indexOf(hold);
|
|
446
|
+
const owns = current === hold.value && !stack.slice(index + 1).some((above2) => above2.value === current);
|
|
447
|
+
if (owns && preserveFocus && holdsFocus(element)) return false;
|
|
448
|
+
stack.splice(index, 1);
|
|
449
|
+
const above = stack[index];
|
|
450
|
+
if (above) above.linked &&= hold.linked;
|
|
451
|
+
this.#mark(element, stack);
|
|
452
|
+
if (!owns) return true;
|
|
453
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
454
|
+
if (!below) element.removeAttribute("tabindex");
|
|
455
|
+
else if (below.value !== current) element.setAttribute("tabindex", below.value);
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
#mark(element, stack) {
|
|
459
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
460
|
+
for (const hold of stack) records.set(hold.record, hold.value);
|
|
461
|
+
for (const [name, recorded] of records) {
|
|
462
|
+
setAttributeIfChanged(element, name, recorded);
|
|
189
463
|
}
|
|
190
|
-
this.#lent.clear();
|
|
191
|
-
this.#beforeCache.deactivate();
|
|
192
464
|
}
|
|
193
465
|
};
|
|
194
466
|
|
|
195
|
-
|
|
196
|
-
|
|
467
|
+
function targetSelector(identifier, name) {
|
|
468
|
+
return `[data-${identifier}-target~="${name}"]`;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
var RatingController = class _RatingController extends Controller {
|
|
472
|
+
#numbers = new NumberValueReader();
|
|
473
|
+
#moves = new MoveCounter();
|
|
474
|
+
#move = 0;
|
|
197
475
|
static targets = ["symbol", "field"];
|
|
198
476
|
static values = {
|
|
199
477
|
value: { type: Number, default: 0 },
|
|
200
478
|
clearable: { type: Boolean, default: true },
|
|
201
479
|
readonly: { type: Boolean, default: false }
|
|
202
480
|
};
|
|
481
|
+
static valueConstraints = {
|
|
482
|
+
value: NUMBER_BOUNDS.finite
|
|
483
|
+
};
|
|
203
484
|
static actions = ["endPreview", "onKeydown", "preview", "select"];
|
|
204
485
|
static events = ["change", "reconcile"];
|
|
205
486
|
#roving = new RovingTabindex(() => this.symbolTargets);
|
|
206
|
-
#rootRole = new AttributeLease("role");
|
|
207
|
-
#symbolRole = new AttributeLease("role");
|
|
208
|
-
#symbolAriaHidden = new AttributeLease("aria-hidden");
|
|
209
|
-
#rootTabindex = new TabindexLoan();
|
|
210
|
-
#repaint = new
|
|
211
|
-
#beforeCache = new BeforeCacheReset(() => this.#rewindForCache());
|
|
487
|
+
#rootRole = new AttributeLease("role", this.identifier);
|
|
488
|
+
#symbolRole = new AttributeLease("role", this.identifier);
|
|
489
|
+
#symbolAriaHidden = new AttributeLease("aria-hidden", this.identifier);
|
|
490
|
+
#rootTabindex = new TabindexLoan("-1", this.identifier);
|
|
491
|
+
#repaint = new MorphRenderWatcher(() => this.#reconcileScale());
|
|
212
492
|
#connected = false;
|
|
213
493
|
#rescuedFocus = false;
|
|
214
|
-
/** The rating shown last, which the next move is measured from. */
|
|
215
494
|
#shown = 0;
|
|
216
|
-
/** Reflects declarative state without announcing an initial user change. */
|
|
217
495
|
connect() {
|
|
218
|
-
this.#
|
|
219
|
-
this.#
|
|
220
|
-
this.#shown = this.#normalize(this
|
|
496
|
+
this.#rootTabindex.reclaim(this.element);
|
|
497
|
+
this.#repaint.observe(this.element);
|
|
498
|
+
this.#shown = this.#normalize(this.#safeValue);
|
|
221
499
|
this.#apply(this.#shown, { focus: false });
|
|
222
500
|
this.#connected = true;
|
|
223
501
|
}
|
|
224
|
-
/** Drops a queued reconciliation and hands every borrowed attribute back. */
|
|
225
502
|
disconnect() {
|
|
226
503
|
this.#connected = false;
|
|
227
|
-
this.#repaint.
|
|
228
|
-
this.#beforeCache.deactivate();
|
|
504
|
+
this.#repaint.disconnect();
|
|
229
505
|
this.#releaseReadonly();
|
|
230
506
|
}
|
|
231
|
-
/** Removes a runtime-added symbol's authored Tab stop before the batch repaint. */
|
|
232
507
|
symbolTargetConnected(symbol) {
|
|
233
508
|
if (this.#connected === false) return;
|
|
234
509
|
symbol.tabIndex = -1;
|
|
235
510
|
this.#repaint.schedule();
|
|
236
511
|
}
|
|
237
|
-
/** Releases readonly ownership and reconciles the remaining DOM-ordered scale. */
|
|
238
512
|
symbolTargetDisconnected(symbol) {
|
|
239
513
|
this.#symbolRole.return(symbol);
|
|
240
514
|
this.#symbolAriaHidden.return(symbol);
|
|
241
515
|
this.#repaint.schedule();
|
|
242
516
|
}
|
|
243
|
-
/** Reflects into a hidden field added or replaced after connection. */
|
|
244
517
|
fieldTargetConnected() {
|
|
245
518
|
this.#repaint.schedule();
|
|
246
519
|
}
|
|
247
|
-
/** Reconciles after a hidden field is removed or replaced. */
|
|
248
520
|
fieldTargetDisconnected() {
|
|
249
521
|
this.#repaint.schedule();
|
|
250
522
|
}
|
|
251
|
-
/** Repaints when application code or a Turbo morph changes `value`. */
|
|
252
523
|
valueValueChanged() {
|
|
253
524
|
this.#repaint.schedule();
|
|
254
525
|
}
|
|
255
|
-
/** Repaints when application code changes whether value 0 is permitted. */
|
|
256
526
|
clearableValueChanged() {
|
|
257
527
|
this.#repaint.schedule();
|
|
258
528
|
}
|
|
259
|
-
/** Repaints when application code enters or leaves the readonly snapshot. */
|
|
260
529
|
readonlyValueChanged() {
|
|
261
530
|
this.#repaint.schedule();
|
|
262
531
|
}
|
|
263
|
-
|
|
264
|
-
select(event) {
|
|
532
|
+
select(source) {
|
|
265
533
|
if (this.readonlyValue) return;
|
|
266
|
-
const
|
|
534
|
+
const { event, host, origin, reason } = actionSource(source);
|
|
535
|
+
const symbol = host?.closest(targetSelector(this.identifier, "symbol"));
|
|
536
|
+
if (!symbol || !this.symbolTargets.includes(symbol)) return;
|
|
537
|
+
if (origin && origin.closest(`[data-controller~="${this.identifier}"]`) !== this.element)
|
|
538
|
+
return;
|
|
539
|
+
const moveFocus = event !== null || this.element.contains(document.activeElement);
|
|
540
|
+
const ordinal = this.#symbolOrdinal(symbol);
|
|
267
541
|
if (ordinal === null) return;
|
|
268
|
-
const current = this.#normalize(this
|
|
269
|
-
this.#commit(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
542
|
+
const current = this.#normalize(this.#safeValue);
|
|
543
|
+
this.#commit(
|
|
544
|
+
this.clearableValue && ordinal === current ? 0 : ordinal,
|
|
545
|
+
{
|
|
546
|
+
focus: ordinal === current && moveFocus
|
|
547
|
+
},
|
|
548
|
+
reason
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
preview(source) {
|
|
275
552
|
if (this.readonlyValue) return;
|
|
276
|
-
const
|
|
553
|
+
const { host, origin } = actionSource(source);
|
|
554
|
+
const symbol = host?.closest(targetSelector(this.identifier, "symbol"));
|
|
555
|
+
if (!symbol || !this.symbolTargets.includes(symbol)) return;
|
|
556
|
+
if (origin && origin.closest(`[data-controller~="${this.identifier}"]`) !== this.element)
|
|
557
|
+
return;
|
|
558
|
+
const ordinal = this.#symbolOrdinal(symbol);
|
|
277
559
|
if (ordinal !== null) this.#setFillRange(ordinal);
|
|
278
560
|
}
|
|
279
|
-
/** Restores the fill range after hover or focus leaves a symbol. */
|
|
280
561
|
endPreview() {
|
|
281
562
|
if (this.readonlyValue) return;
|
|
282
|
-
this.#setFillRange(this.#normalize(this
|
|
563
|
+
this.#setFillRange(this.#normalize(this.#safeValue));
|
|
283
564
|
}
|
|
284
|
-
/** Arrow/Home/End/Space/Delete keyboard control, clamped without wrapping. */
|
|
285
565
|
onKeydown(event) {
|
|
286
566
|
if (event.defaultPrevented || isReservedArrowChord(event) || this.readonlyValue) return;
|
|
287
|
-
|
|
567
|
+
if ((event.key === "Home" || event.key === "End") && hasModifierChord(event)) return;
|
|
568
|
+
const current = this.#normalize(this.#safeValue);
|
|
288
569
|
let next = null;
|
|
289
570
|
const rtl = isRtl(this.element);
|
|
290
571
|
switch (event.key) {
|
|
@@ -318,69 +599,54 @@ var RatingController = class extends Controller {
|
|
|
318
599
|
event.preventDefault();
|
|
319
600
|
this.#commit(next, { focus: true });
|
|
320
601
|
}
|
|
321
|
-
/**
|
|
322
|
-
* Repaints one settled target/Value mutation batch and reports a rating shown
|
|
323
|
-
* that moved from the one shown before it.
|
|
324
|
-
*
|
|
325
|
-
* @stimeoRenderRoot
|
|
326
|
-
*/
|
|
327
602
|
#reconcileScale() {
|
|
328
|
-
const value = this.#normalize(this
|
|
603
|
+
const value = this.#normalize(this.#safeValue);
|
|
329
604
|
const previous = this.#shown;
|
|
330
605
|
this.#shown = value;
|
|
606
|
+
const move = this.#move;
|
|
331
607
|
this.#apply(value, { focus: false });
|
|
608
|
+
if (!this.#moves.isLatest(move)) return;
|
|
332
609
|
if (value !== previous) this.dispatch("reconcile", { detail: { value } });
|
|
333
610
|
}
|
|
334
|
-
|
|
335
|
-
* Applies one user operation and emits only when the rating shown changes.
|
|
336
|
-
*
|
|
337
|
-
* The user's value is written into `value` before anything reports it, so a
|
|
338
|
-
* listener of the field's native `change` already reads it there, and the pass
|
|
339
|
-
* that the write starts finds nothing left to report.
|
|
340
|
-
*/
|
|
341
|
-
#commit(raw, { focus }) {
|
|
611
|
+
#commit(raw, { focus }, reason = "user") {
|
|
342
612
|
const previous = this.#shown;
|
|
343
613
|
const value = this.#normalize(raw);
|
|
344
614
|
if (!Object.is(this.valueValue, value)) this.valueValue = value;
|
|
345
615
|
this.#shown = value;
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
616
|
+
if (value !== previous) this.#move = this.#moves.record();
|
|
617
|
+
const move = this.#move;
|
|
618
|
+
const field = this.#apply(value, { focus });
|
|
619
|
+
if (!this.#moves.isLatest(move)) return;
|
|
620
|
+
if (field) commitField(field);
|
|
621
|
+
if (!this.#moves.isLatest(move)) return;
|
|
622
|
+
if (value !== previous) this.dispatch("change", { detail: { value, reason } });
|
|
623
|
+
}
|
|
624
|
+
#apply(value, { focus }) {
|
|
625
|
+
const move = this.#move;
|
|
351
626
|
this.symbolTargets.forEach((symbol, index) => {
|
|
352
627
|
symbol.setAttribute("aria-checked", value > 0 && index + 1 === value ? "true" : "false");
|
|
353
628
|
});
|
|
629
|
+
const field = this.hasFieldTarget ? this.fieldTarget : null;
|
|
630
|
+
const moved = field && writeField(field, String(value));
|
|
631
|
+
this.#setFillRange(value);
|
|
354
632
|
if (this.readonlyValue) {
|
|
355
633
|
this.#applyReadonly();
|
|
356
634
|
} else {
|
|
357
635
|
const returning = this.#releaseReadonly();
|
|
358
636
|
this.#roving.setActive(value > 0 ? value - 1 : 0, { focus: focus || returning });
|
|
359
637
|
}
|
|
360
|
-
this.#
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
/** Mirrors `value` into the optional form field, reporting only a user's move. */
|
|
364
|
-
#mirrorField(value, notify) {
|
|
365
|
-
if (!this.hasFieldTarget) return;
|
|
366
|
-
if (writeField(this.fieldTarget, String(value)) && notify) commitField(this.fieldTarget);
|
|
638
|
+
if (this.#moves.isLatest(move)) this.#setFillRange(value);
|
|
639
|
+
return moved ? field : null;
|
|
367
640
|
}
|
|
368
|
-
/** Marks the first `range` symbols with the consumer-owned fill hook. */
|
|
369
641
|
#setFillRange(range) {
|
|
370
642
|
this.symbolTargets.forEach((symbol, index) => {
|
|
371
643
|
symbol.toggleAttribute("data-rating-hover", range > 0 && index < range);
|
|
372
644
|
});
|
|
373
645
|
}
|
|
374
|
-
/**
|
|
375
|
-
* Temporarily turns the radiogroup into a non-interactive image snapshot.
|
|
376
|
-
*
|
|
377
|
-
* Each lease is returned before it is taken again, so a value the consumer
|
|
378
|
-
* wrote while readonly becomes the value the lease restores on release. The
|
|
379
|
-
* return is a no-op on an attribute still holding this controller's own
|
|
380
|
-
* write, which is the ordinary case.
|
|
381
|
-
*/
|
|
382
646
|
#applyReadonly() {
|
|
647
|
+
const move = this.#move;
|
|
383
648
|
this.#rescueFocus();
|
|
649
|
+
if (!this.#moves.isLatest(move)) return;
|
|
384
650
|
this.#rootRole.return(this.element);
|
|
385
651
|
this.#rootRole.write(this.element, "img");
|
|
386
652
|
for (const symbol of this.symbolTargets) {
|
|
@@ -391,69 +657,50 @@ var RatingController = class extends Controller {
|
|
|
391
657
|
}
|
|
392
658
|
this.#roving.setActive(-1);
|
|
393
659
|
}
|
|
394
|
-
/**
|
|
395
|
-
* Hands every readonly borrowing back before Turbo clones the page.
|
|
396
|
-
*
|
|
397
|
-
* The snapshot is taken while the controller is still connected, so an
|
|
398
|
-
* element left as `role="img"` with hidden symbols is what a restored page
|
|
399
|
-
* connects against — and that markup would be read as the authored one,
|
|
400
|
-
* leaving no way back to the radiogroup. Rewinding first keeps the cached
|
|
401
|
-
* copy identical to what the consumer wrote.
|
|
402
|
-
*/
|
|
403
|
-
#rewindForCache() {
|
|
404
|
-
this.#releaseReadonly();
|
|
405
|
-
const value = this.#normalize(this.valueValue);
|
|
406
|
-
this.#roving.setActive(value > 0 ? value - 1 : 0);
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Lands focus on the root before the symbols leave the accessibility tree.
|
|
410
|
-
*
|
|
411
|
-
* A symbol holding focus when readonly begins would keep it while losing its
|
|
412
|
-
* role and gaining `aria-hidden`, stranding the user on a node no longer in
|
|
413
|
-
* the tree. The root is the one element that survives the transition named:
|
|
414
|
-
* it carries the consumer's accessible name under `role="img"`.
|
|
415
|
-
*/
|
|
416
660
|
#rescueFocus() {
|
|
417
661
|
const active = document.activeElement;
|
|
418
662
|
if (!(active instanceof HTMLElement) || active === this.element) return;
|
|
419
663
|
if (!this.element.contains(active)) return;
|
|
420
664
|
this.#rootTabindex.lend(this.element);
|
|
421
|
-
this.element.focus();
|
|
422
665
|
this.#rescuedFocus = true;
|
|
666
|
+
this.element.focus();
|
|
423
667
|
}
|
|
424
|
-
/**
|
|
425
|
-
* Restores authored roles and visibility after leaving readonly mode.
|
|
426
|
-
*
|
|
427
|
-
* @returns whether focus is standing on the root because {@link #rescueFocus}
|
|
428
|
-
* put it there, and therefore belongs back on the Tab stop.
|
|
429
|
-
*/
|
|
430
668
|
#releaseReadonly() {
|
|
431
669
|
const returning = this.#rescuedFocus && document.activeElement === this.element;
|
|
432
670
|
this.#rescuedFocus = false;
|
|
433
671
|
this.#rootRole.return(this.element);
|
|
672
|
+
for (const symbol of this.symbolTargets) {
|
|
673
|
+
this.#symbolRole.return(symbol);
|
|
674
|
+
this.#symbolAriaHidden.return(symbol);
|
|
675
|
+
}
|
|
434
676
|
this.#symbolRole.returnAll();
|
|
435
677
|
this.#symbolAriaHidden.returnAll();
|
|
436
678
|
this.#rootTabindex.returnAll();
|
|
437
679
|
return returning;
|
|
438
680
|
}
|
|
439
|
-
/** Normalizes a raw value to an integer ordinal in the live DOM range. */
|
|
440
681
|
#normalize(raw) {
|
|
441
682
|
const maximum = this.symbolTargets.length;
|
|
442
|
-
const ordinal =
|
|
683
|
+
const ordinal = Math.round(raw);
|
|
443
684
|
return Math.min(maximum, Math.max(this.#minValue, ordinal));
|
|
444
685
|
}
|
|
445
|
-
/** Lowest selectable value: 0 when clearable, otherwise 1. */
|
|
446
686
|
get #minValue() {
|
|
447
687
|
return this.clearableValue ? 0 : 1;
|
|
448
688
|
}
|
|
449
|
-
/** Returns a target's 1-based position, or null when the action host is invalid. */
|
|
450
689
|
#symbolOrdinal(target) {
|
|
451
690
|
const targets = this.symbolTargets;
|
|
452
691
|
const index = targets.indexOf(target);
|
|
453
692
|
return index < 0 ? null : index + 1;
|
|
454
693
|
}
|
|
694
|
+
get #safeValue() {
|
|
695
|
+
return this.#numbers.read(
|
|
696
|
+
this,
|
|
697
|
+
"value",
|
|
698
|
+
this.valueValue,
|
|
699
|
+
_RatingController.values.value.default,
|
|
700
|
+
_RatingController.valueConstraints.value
|
|
701
|
+
);
|
|
702
|
+
}
|
|
455
703
|
};
|
|
456
704
|
|
|
457
705
|
export { RatingController };
|
|
458
|
-
//# sourceMappingURL=rating_controller.js.map
|
|
459
706
|
//# sourceMappingURL=rating_controller.js.map
|