stimeo-ui 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/README.md +27 -11
- package/dist/cable/index.d.ts +88 -31
- package/dist/cable/index.js +384 -449
- package/dist/cable/index.js.map +1 -1
- package/dist/coerce-JtZVNG5h.d.ts +20 -0
- package/dist/controllers/accordion_controller.d.ts +4 -2
- package/dist/controllers/accordion_controller.js +174 -55
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.d.ts +12 -2
- package/dist/controllers/alert_dialog_controller.js +903 -235
- package/dist/controllers/alert_dialog_controller.js.map +1 -1
- package/dist/controllers/announcer_controller.d.ts +37 -5
- package/dist/controllers/announcer_controller.js +238 -205
- package/dist/controllers/announcer_controller.js.map +1 -1
- package/dist/controllers/aspect_ratio_controller.js +0 -10
- package/dist/controllers/aspect_ratio_controller.js.map +1 -1
- package/dist/controllers/auto_submit_controller.d.ts +30 -6
- package/dist/controllers/auto_submit_controller.js +414 -145
- package/dist/controllers/auto_submit_controller.js.map +1 -1
- package/dist/controllers/avatar_controller.js +185 -107
- package/dist/controllers/avatar_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.js +0 -130
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/bulk_select_controller.d.ts +21 -3
- package/dist/controllers/bulk_select_controller.js +282 -58
- package/dist/controllers/bulk_select_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +38 -16
- package/dist/controllers/calendar_controller.js +228 -260
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +43 -12
- package/dist/controllers/carousel_controller.js +536 -436
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/character_counter_controller.d.ts +44 -7
- package/dist/controllers/character_counter_controller.js +493 -207
- package/dist/controllers/character_counter_controller.js.map +1 -1
- package/dist/controllers/checkbox_controller.d.ts +7 -2
- package/dist/controllers/checkbox_controller.js +38 -74
- package/dist/controllers/checkbox_controller.js.map +1 -1
- package/dist/controllers/clipboard_controller.d.ts +16 -5
- package/dist/controllers/clipboard_controller.js +261 -149
- package/dist/controllers/clipboard_controller.js.map +1 -1
- package/dist/controllers/collapsible_controller.d.ts +17 -5
- package/dist/controllers/collapsible_controller.js +304 -120
- package/dist/controllers/collapsible_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.d.ts +18 -6
- package/dist/controllers/color_picker_controller.js +178 -146
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.d.ts +24 -6
- package/dist/controllers/combobox_controller.js +522 -156
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +51 -20
- package/dist/controllers/command_palette_controller.js +1156 -395
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/conditional_fields_controller.d.ts +15 -2
- package/dist/controllers/conditional_fields_controller.js +300 -171
- package/dist/controllers/conditional_fields_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.d.ts +49 -12
- package/dist/controllers/confirm_controller.js +980 -262
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +80 -18
- package/dist/controllers/context_menu_controller.js +346 -153
- package/dist/controllers/context_menu_controller.js.map +1 -1
- package/dist/controllers/count_up_controller.d.ts +13 -1
- package/dist/controllers/count_up_controller.js +73 -21
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/countdown_controller.d.ts +47 -3
- package/dist/controllers/countdown_controller.js +281 -158
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +93 -10
- package/dist/controllers/currency_input_controller.js +575 -225
- package/dist/controllers/currency_input_controller.js.map +1 -1
- package/dist/controllers/data_grid_controller.d.ts +25 -12
- package/dist/controllers/data_grid_controller.js +248 -214
- package/dist/controllers/data_grid_controller.js.map +1 -1
- package/dist/controllers/date_range_picker_controller.d.ts +42 -14
- package/dist/controllers/date_range_picker_controller.js +338 -235
- package/dist/controllers/date_range_picker_controller.js.map +1 -1
- package/dist/controllers/dialog_controller.d.ts +17 -6
- package/dist/controllers/dialog_controller.js +899 -237
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.d.ts +25 -8
- package/dist/controllers/direct_upload_controller.js +97 -167
- package/dist/controllers/direct_upload_controller.js.map +1 -1
- package/dist/controllers/dirty_form_controller.d.ts +6 -1
- package/dist/controllers/dirty_form_controller.js +72 -69
- package/dist/controllers/dirty_form_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.d.ts +19 -0
- package/dist/controllers/dismissible_controller.js +196 -24
- package/dist/controllers/dismissible_controller.js.map +1 -1
- package/dist/controllers/drawer_controller.d.ts +39 -11
- package/dist/controllers/drawer_controller.js +974 -355
- package/dist/controllers/drawer_controller.js.map +1 -1
- package/dist/controllers/dropdown_controller.d.ts +31 -1
- package/dist/controllers/dropdown_controller.js +339 -96
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.d.ts +12 -1
- package/dist/controllers/editable_controller.js +315 -88
- package/dist/controllers/editable_controller.js.map +1 -1
- package/dist/controllers/empty_state_controller.js +79 -58
- package/dist/controllers/empty_state_controller.js.map +1 -1
- package/dist/controllers/file_dropzone_controller.d.ts +63 -18
- package/dist/controllers/file_dropzone_controller.js +322 -211
- package/dist/controllers/file_dropzone_controller.js.map +1 -1
- package/dist/controllers/filter_controller.js +77 -42
- package/dist/controllers/filter_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +35 -12
- package/dist/controllers/flash_controller.js +238 -347
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +15 -6
- package/dist/controllers/focus_controller.js +679 -240
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.js +156 -132
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.d.ts +3 -3
- package/dist/controllers/form_validation_controller.js +31 -97
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.d.ts +47 -14
- package/dist/controllers/frame_loading_controller.js +275 -217
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.d.ts +27 -6
- package/dist/controllers/highlight_controller.js +107 -75
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +60 -4
- package/dist/controllers/hover_card_controller.js +327 -130
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +48 -6
- package/dist/controllers/idle_controller.js +271 -101
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/input_mask_controller.d.ts +30 -13
- package/dist/controllers/input_mask_controller.js +483 -97
- package/dist/controllers/input_mask_controller.js.map +1 -1
- package/dist/controllers/intersection_controller.d.ts +32 -13
- package/dist/controllers/intersection_controller.js +150 -106
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.d.ts +19 -2
- package/dist/controllers/lazy_frame_controller.js +24 -68
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +44 -9
- package/dist/controllers/listbox_controller.js +523 -240
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.d.ts +9 -7
- package/dist/controllers/local_time_controller.js +102 -77
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.d.ts +11 -3
- package/dist/controllers/masonry_controller.js +80 -96
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/menu_controller.d.ts +55 -11
- package/dist/controllers/menu_controller.js +302 -188
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +51 -9
- package/dist/controllers/menubar_controller.js +232 -345
- package/dist/controllers/menubar_controller.js.map +1 -1
- package/dist/controllers/meter_controller.d.ts +33 -20
- package/dist/controllers/meter_controller.js +417 -87
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +48 -18
- package/dist/controllers/multi_select_controller.js +785 -393
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/navigation_menu_controller.d.ts +27 -6
- package/dist/controllers/navigation_menu_controller.js +190 -250
- package/dist/controllers/navigation_menu_controller.js.map +1 -1
- package/dist/controllers/nested_form_controller.d.ts +10 -0
- package/dist/controllers/nested_form_controller.js +396 -192
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/network_status_controller.d.ts +23 -0
- package/dist/controllers/network_status_controller.js +268 -62
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +50 -8
- package/dist/controllers/number_input_controller.js +610 -303
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/optimistic_controller.d.ts +8 -5
- package/dist/controllers/optimistic_controller.js +45 -87
- package/dist/controllers/optimistic_controller.js.map +1 -1
- package/dist/controllers/otp_controller.d.ts +55 -8
- package/dist/controllers/otp_controller.js +658 -255
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.d.ts +5 -0
- package/dist/controllers/overflow_indicator_controller.js +122 -113
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +58 -20
- package/dist/controllers/overflow_menu_controller.js +470 -295
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +37 -7
- package/dist/controllers/pagination_controller.js +332 -123
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +46 -8
- package/dist/controllers/password_reveal_controller.js +392 -121
- package/dist/controllers/password_reveal_controller.js.map +1 -1
- package/dist/controllers/password_strength_controller.d.ts +15 -6
- package/dist/controllers/password_strength_controller.js +111 -158
- package/dist/controllers/password_strength_controller.js.map +1 -1
- package/dist/controllers/persist_controller.d.ts +11 -4
- package/dist/controllers/persist_controller.js +165 -111
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +35 -12
- package/dist/controllers/pointer_drag_controller.js +434 -188
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +41 -5
- package/dist/controllers/popover_controller.js +269 -113
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +44 -4
- package/dist/controllers/portal_controller.js +215 -76
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/preview_guard_controller.d.ts +10 -4
- package/dist/controllers/preview_guard_controller.js +243 -116
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/progress_controller.d.ts +20 -19
- package/dist/controllers/progress_controller.js +391 -78
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.d.ts +21 -9
- package/dist/controllers/radio_group_controller.js +278 -211
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +47 -6
- package/dist/controllers/range_slider_controller.js +220 -113
- package/dist/controllers/range_slider_controller.js.map +1 -1
- package/dist/controllers/rating_controller.d.ts +20 -4
- package/dist/controllers/rating_controller.js +458 -211
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.d.ts +2 -0
- package/dist/controllers/read_more_controller.js +138 -63
- package/dist/controllers/read_more_controller.js.map +1 -1
- package/dist/controllers/reading_progress_controller.d.ts +1 -1
- package/dist/controllers/reading_progress_controller.js +166 -137
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/relative_time_controller.d.ts +20 -6
- package/dist/controllers/relative_time_controller.js +211 -112
- package/dist/controllers/relative_time_controller.js.map +1 -1
- package/dist/controllers/reset_on_restore_controller.d.ts +85 -0
- package/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +103 -38
- package/dist/controllers/reset_on_restore_controller.js.map +1 -0
- package/dist/controllers/resizable_controller.d.ts +31 -2
- package/dist/controllers/resizable_controller.js +299 -150
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.d.ts +3 -3
- package/dist/controllers/roving_controller.js +49 -88
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.d.ts +7 -3
- package/dist/controllers/scroll_area_controller.js +490 -246
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_restore_controller.d.ts +3 -3
- package/dist/controllers/scroll_restore_controller.js +14 -55
- package/dist/controllers/scroll_restore_controller.js.map +1 -1
- package/dist/controllers/scroll_visibility_controller.d.ts +28 -12
- package/dist/controllers/scroll_visibility_controller.js +432 -149
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.d.ts +6 -1
- package/dist/controllers/scrollspy_controller.js +193 -248
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +20 -5
- package/dist/controllers/separator_controller.js +285 -142
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/sidebar_controller.d.ts +65 -8
- package/dist/controllers/sidebar_controller.js +1069 -404
- package/dist/controllers/sidebar_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.d.ts +23 -0
- package/dist/controllers/skeleton_controller.js +259 -101
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +29 -2
- package/dist/controllers/slider_controller.js +187 -86
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.d.ts +22 -4
- package/dist/controllers/smart_sticky_header_controller.js +173 -66
- package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.d.ts +4 -4
- package/dist/controllers/sortable_controller.js +26 -125
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.d.ts +39 -4
- package/dist/controllers/spinner_controller.js +288 -173
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +9 -4
- package/dist/controllers/step_indicator_controller.js +105 -46
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +14 -6
- package/dist/controllers/stepper_controller.js +120 -73
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +9 -1
- package/dist/controllers/stick_to_bottom_controller.js +275 -140
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.d.ts +11 -0
- package/dist/controllers/sticky_observer_controller.js +220 -49
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +24 -8
- package/dist/controllers/submit_once_controller.js +376 -227
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +18 -4
- package/dist/controllers/switch_controller.js +201 -84
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +9 -6
- package/dist/controllers/tabs_controller.js +41 -30
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +16 -3
- package/dist/controllers/tags_input_controller.js +293 -173
- package/dist/controllers/tags_input_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.d.ts +11 -1
- package/dist/controllers/textarea_autosize_controller.js +108 -74
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/theme_controller.d.ts +24 -11
- package/dist/controllers/theme_controller.js +140 -116
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +55 -5
- package/dist/controllers/time_picker_controller.js +331 -127
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/toast_controller.d.ts +40 -16
- package/dist/controllers/toast_controller.js +244 -324
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.d.ts +14 -6
- package/dist/controllers/toggle_group_controller.js +252 -191
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.d.ts +8 -6
- package/dist/controllers/toolbar_controller.js +219 -120
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +49 -4
- package/dist/controllers/tooltip_controller.js +158 -124
- package/dist/controllers/tooltip_controller.js.map +1 -1
- package/dist/controllers/transition_controller.d.ts +22 -4
- package/dist/controllers/transition_controller.js +123 -119
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +22 -12
- package/dist/controllers/tree_view_controller.js +283 -369
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.js +8573 -10410
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +38 -14
- package/dist/inspector/cli.js +108 -40
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +145 -64
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +20 -20
- package/dist/inspector/manifest.json +802 -101
- package/dist/positioning/index.d.ts +15 -7
- package/dist/positioning/index.js +154 -47
- package/dist/positioning/index.js.map +1 -1
- package/package.json +11 -10
- package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
- package/dist/controllers/reset_before_cache_controller.js.map +0 -1
|
@@ -1,14 +1,207 @@
|
|
|
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
|
+
}
|
|
24
|
+
|
|
25
|
+
function isAriaDisabled(element) {
|
|
26
|
+
for (let current = element; current; current = current.parentElement) {
|
|
27
|
+
if (current.getAttribute("aria-disabled") === "true") return true;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
4
31
|
|
|
5
|
-
// src/utils/arrow_step.ts
|
|
6
32
|
function isReservedArrowChord(event, allow = []) {
|
|
7
33
|
if (!event.key.startsWith("Arrow")) return false;
|
|
8
34
|
return event.altKey && !allow.includes("alt") || event.ctrlKey && !allow.includes("ctrl") || event.metaKey && !allow.includes("meta") || event.shiftKey && !allow.includes("shift");
|
|
9
35
|
}
|
|
36
|
+
function hasModifierChord(event) {
|
|
37
|
+
return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function setAttributeIfChanged(element, name, value, beforeWrite) {
|
|
41
|
+
if (element.getAttribute(name) === value) return false;
|
|
42
|
+
if (value === null) element.removeAttribute(name);
|
|
43
|
+
else element.setAttribute(name, value);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function sharedRegistry(key, create) {
|
|
48
|
+
const symbol = Symbol.for(key);
|
|
49
|
+
const scope = globalThis;
|
|
50
|
+
const existing = scope[symbol];
|
|
51
|
+
if (existing !== void 0) return existing;
|
|
52
|
+
const registry2 = create();
|
|
53
|
+
Object.defineProperty(globalThis, symbol, { value: registry2 });
|
|
54
|
+
return registry2;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var registry = sharedRegistry(
|
|
58
|
+
"stimeo-ui.attribute-lease.registry.v1",
|
|
59
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
|
|
60
|
+
);
|
|
61
|
+
function isAttributeValue(value) {
|
|
62
|
+
return value === null || typeof value === "string";
|
|
63
|
+
}
|
|
64
|
+
function readLeaseRecord(element, record) {
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(element.getAttribute(record) ?? "null");
|
|
67
|
+
if (!Array.isArray(parsed)) return void 0;
|
|
68
|
+
const [original, written, ...rest] = parsed;
|
|
69
|
+
const linked = rest[0] !== false;
|
|
70
|
+
const beneath = linked ? rest : rest.slice(1);
|
|
71
|
+
if (!beneath.every((under) => typeof under === "string")) return void 0;
|
|
72
|
+
return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
|
|
73
|
+
} catch {
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function attributeStack(element, attribute) {
|
|
78
|
+
const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
79
|
+
registry.stacks.set(element, byAttribute);
|
|
80
|
+
const known = byAttribute.get(attribute);
|
|
81
|
+
if (known) return known;
|
|
82
|
+
const found = [];
|
|
83
|
+
for (const record of registry.names.get(attribute) ?? []) {
|
|
84
|
+
const read = readLeaseRecord(element, record);
|
|
85
|
+
if (read) found.push({ ...read, record });
|
|
86
|
+
}
|
|
87
|
+
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
88
|
+
const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
|
|
89
|
+
lease: null,
|
|
90
|
+
record,
|
|
91
|
+
written,
|
|
92
|
+
original,
|
|
93
|
+
linked: linked && index > 0
|
|
94
|
+
}));
|
|
95
|
+
byAttribute.set(attribute, stack);
|
|
96
|
+
return stack;
|
|
97
|
+
}
|
|
98
|
+
function findHold(stack, lease, record) {
|
|
99
|
+
return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
|
|
100
|
+
}
|
|
101
|
+
var AttributeLease = class {
|
|
102
|
+
#attribute;
|
|
103
|
+
#record;
|
|
104
|
+
#base;
|
|
105
|
+
#preserveAuthor;
|
|
106
|
+
#held = /* @__PURE__ */ new Set();
|
|
107
|
+
constructor(attribute, owner, options = {}) {
|
|
108
|
+
this.#attribute = attribute;
|
|
109
|
+
this.#record = `data-${owner}-${attribute}-lease`;
|
|
110
|
+
this.#base = options.base === true;
|
|
111
|
+
this.#preserveAuthor = options.preserveAuthor === true;
|
|
112
|
+
const names = registry.names;
|
|
113
|
+
names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
|
|
114
|
+
}
|
|
115
|
+
write(element, value) {
|
|
116
|
+
const stack = attributeStack(element, this.#attribute);
|
|
117
|
+
const hold = this.#take(stack) ?? this.#acquire(element, stack);
|
|
118
|
+
this.#held.add(element);
|
|
119
|
+
const shows = !this.#covered(element, stack, hold);
|
|
120
|
+
hold.written = value;
|
|
121
|
+
this.#mark(element, stack);
|
|
122
|
+
if (shows) this.#reflect(element, value);
|
|
123
|
+
}
|
|
124
|
+
return(element) {
|
|
125
|
+
const held = this.#held.delete(element);
|
|
126
|
+
const known = registry.stacks.get(element)?.has(this.#attribute);
|
|
127
|
+
const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
|
|
128
|
+
const hold = this.#take(stack);
|
|
129
|
+
if (!hold) return false;
|
|
130
|
+
const carries = element.getAttribute(this.#attribute) === hold.written;
|
|
131
|
+
const owns = carries && !this.#covered(element, stack, hold);
|
|
132
|
+
const index = stack.indexOf(hold);
|
|
133
|
+
stack.splice(index, 1);
|
|
134
|
+
const above = stack[index];
|
|
135
|
+
if (above) above.linked &&= hold.linked;
|
|
136
|
+
this.#mark(element, stack);
|
|
137
|
+
if (!owns) return true;
|
|
138
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
139
|
+
this.#reflect(element, below ? below.written : hold.original);
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
returnAll() {
|
|
143
|
+
for (const element of Array.from(this.#held)) this.return(element);
|
|
144
|
+
}
|
|
145
|
+
#take(stack) {
|
|
146
|
+
const hold = findHold(stack, this, this.#record);
|
|
147
|
+
if (hold) hold.lease = this;
|
|
148
|
+
return hold;
|
|
149
|
+
}
|
|
150
|
+
#acquire(element, stack) {
|
|
151
|
+
const current = element.getAttribute(this.#attribute);
|
|
152
|
+
const top = stack.at(-1);
|
|
153
|
+
const bottom = stack[0];
|
|
154
|
+
const over = top?.written === current ? top : void 0;
|
|
155
|
+
const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
|
|
156
|
+
const hold = {
|
|
157
|
+
lease: this,
|
|
158
|
+
record: this.#record,
|
|
159
|
+
written: current,
|
|
160
|
+
original: from ? from.original : current,
|
|
161
|
+
linked: !this.#base && over !== void 0
|
|
162
|
+
};
|
|
163
|
+
if (this.#base && bottom) {
|
|
164
|
+
bottom.linked = true;
|
|
165
|
+
stack.unshift(hold);
|
|
166
|
+
} else stack.push(hold);
|
|
167
|
+
return hold;
|
|
168
|
+
}
|
|
169
|
+
#covered(element, stack, hold) {
|
|
170
|
+
const current = element.getAttribute(this.#attribute);
|
|
171
|
+
return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
|
|
172
|
+
}
|
|
173
|
+
#mark(element, stack) {
|
|
174
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
175
|
+
stack.forEach((hold, index) => {
|
|
176
|
+
const names = stack.slice(0, index).map((under) => under.record);
|
|
177
|
+
const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
|
|
178
|
+
const marker = hold.linked || beneath.length === 0 ? [] : [false];
|
|
179
|
+
records.set(
|
|
180
|
+
hold.record,
|
|
181
|
+
hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
|
|
182
|
+
);
|
|
183
|
+
});
|
|
184
|
+
for (const [name, recorded] of records) {
|
|
185
|
+
setAttributeIfChanged(element, name, recorded);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
#reflect(element, value) {
|
|
189
|
+
setAttributeIfChanged(element, this.#attribute, value);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
var ClickVerdicts = class {
|
|
194
|
+
#verdicts = /* @__PURE__ */ new WeakMap();
|
|
195
|
+
record(event, entries, refused) {
|
|
196
|
+
this.#verdicts.set(event, { entries, refused });
|
|
197
|
+
}
|
|
198
|
+
for(event, entry) {
|
|
199
|
+
const verdict = event && this.#verdicts.get(event);
|
|
200
|
+
if (!verdict?.entries.includes(entry)) return void 0;
|
|
201
|
+
return verdict.refused;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
10
204
|
|
|
11
|
-
// src/utils/escape_layer.ts
|
|
12
205
|
function claimsWhileFocusWithin(element) {
|
|
13
206
|
return () => {
|
|
14
207
|
const active = element.ownerDocument.activeElement;
|
|
@@ -16,125 +209,109 @@ function claimsWhileFocusWithin(element) {
|
|
|
16
209
|
};
|
|
17
210
|
}
|
|
18
211
|
var EscapeLayer = class _EscapeLayer {
|
|
19
|
-
static #registries =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
#claims = null;
|
|
25
|
-
/**
|
|
26
|
-
* Activates this layer at the top of its document's Escape stack, installing
|
|
27
|
-
* the document's shared resolver listener if this is its first layer.
|
|
28
|
-
* Re-activating an already-active layer moves it to the top.
|
|
29
|
-
*/
|
|
212
|
+
static #registries = sharedRegistry(
|
|
213
|
+
"stimeo-ui.escape-layer.registry.v1",
|
|
214
|
+
() => /* @__PURE__ */ new WeakMap()
|
|
215
|
+
);
|
|
216
|
+
#active = null;
|
|
30
217
|
activate(ownerDocument = document, options) {
|
|
31
218
|
this.deactivate();
|
|
32
|
-
let
|
|
33
|
-
if (!
|
|
34
|
-
|
|
35
|
-
_EscapeLayer.#registries.set(ownerDocument,
|
|
36
|
-
ownerDocument.addEventListener("keydown",
|
|
219
|
+
let registry2 = _EscapeLayer.#registries.get(ownerDocument);
|
|
220
|
+
if (!registry2) {
|
|
221
|
+
registry2 = _EscapeLayer.#createRegistry();
|
|
222
|
+
_EscapeLayer.#registries.set(ownerDocument, registry2);
|
|
223
|
+
ownerDocument.addEventListener("keydown", registry2.onKeydown);
|
|
37
224
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
this.#
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Removes this layer from its document's Escape stack, uninstalling the
|
|
45
|
-
* shared listener when the stack empties. Safe to call when inactive.
|
|
46
|
-
*/
|
|
225
|
+
const entry = { onDismiss: options.onDismiss, claims: options.claims ?? null };
|
|
226
|
+
registry2.stack.push(entry);
|
|
227
|
+
this.#active = { document: ownerDocument, entry };
|
|
228
|
+
}
|
|
47
229
|
deactivate() {
|
|
48
|
-
const
|
|
49
|
-
if (!
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
const index =
|
|
53
|
-
if (index >= 0)
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
_EscapeLayer.#registries.delete(
|
|
230
|
+
const active = this.#active;
|
|
231
|
+
if (!active) return;
|
|
232
|
+
const registry2 = _EscapeLayer.#registries.get(active.document);
|
|
233
|
+
if (registry2) {
|
|
234
|
+
const index = registry2.stack.lastIndexOf(active.entry);
|
|
235
|
+
if (index >= 0) registry2.stack.splice(index, 1);
|
|
236
|
+
if (registry2.stack.length === 0) {
|
|
237
|
+
active.document.removeEventListener("keydown", registry2.onKeydown);
|
|
238
|
+
_EscapeLayer.#registries.delete(active.document);
|
|
57
239
|
}
|
|
58
240
|
}
|
|
59
|
-
this.#
|
|
60
|
-
|
|
61
|
-
this.#claims = null;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Whether this active layer would own a press right now: it is the topmost
|
|
65
|
-
* layer whose {@link EscapeLayerOptions.claims} passes. Exposed for tests
|
|
66
|
-
* and diagnostics — production dismissal goes through the shared listener.
|
|
67
|
-
*/
|
|
241
|
+
this.#active = null;
|
|
242
|
+
}
|
|
68
243
|
get ownsEscape() {
|
|
69
|
-
const
|
|
70
|
-
if (!
|
|
71
|
-
const
|
|
72
|
-
if (!
|
|
73
|
-
return _EscapeLayer.#resolveOwner(
|
|
244
|
+
const active = this.#active;
|
|
245
|
+
if (!active) return false;
|
|
246
|
+
const registry2 = _EscapeLayer.#registries.get(active.document);
|
|
247
|
+
if (!registry2) return false;
|
|
248
|
+
return _EscapeLayer.#resolveOwner(registry2.stack) === active.entry;
|
|
74
249
|
}
|
|
75
|
-
/** Builds a document's registry with its shared resolver listener. */
|
|
76
250
|
static #createRegistry() {
|
|
77
|
-
const
|
|
251
|
+
const registry2 = {
|
|
78
252
|
stack: [],
|
|
79
253
|
onKeydown: (event) => {
|
|
80
254
|
if (event.key !== "Escape" || event.defaultPrevented || event.isComposing) return;
|
|
81
|
-
const owner = _EscapeLayer.#resolveOwner(
|
|
255
|
+
const owner = _EscapeLayer.#resolveOwner(registry2.stack);
|
|
82
256
|
if (!owner) return;
|
|
83
257
|
event.preventDefault();
|
|
84
|
-
owner
|
|
258
|
+
owner.onDismiss();
|
|
85
259
|
}
|
|
86
260
|
};
|
|
87
|
-
return
|
|
261
|
+
return registry2;
|
|
88
262
|
}
|
|
89
|
-
/** The topmost stack layer whose claims predicate passes, or `null`. */
|
|
90
263
|
static #resolveOwner(stack) {
|
|
91
264
|
for (let index = stack.length - 1; index >= 0; index--) {
|
|
92
265
|
const layer = stack[index];
|
|
93
266
|
if (!layer) continue;
|
|
94
|
-
if (layer
|
|
267
|
+
if (layer.claims && !layer.claims()) continue;
|
|
95
268
|
return layer;
|
|
96
269
|
}
|
|
97
270
|
return null;
|
|
98
271
|
}
|
|
99
272
|
};
|
|
100
273
|
|
|
101
|
-
|
|
274
|
+
function ownerIndex(candidates, node) {
|
|
275
|
+
if (!(node instanceof Node)) return -1;
|
|
276
|
+
return candidates.findIndex((candidate) => candidate.contains(node));
|
|
277
|
+
}
|
|
278
|
+
function ownerOf(candidates, node) {
|
|
279
|
+
return candidates[ownerIndex(candidates, node)] ?? null;
|
|
280
|
+
}
|
|
281
|
+
function ownersOf(candidates, node) {
|
|
282
|
+
if (!(node instanceof Node)) return [];
|
|
283
|
+
return candidates.filter((candidate) => candidate.contains(node));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
var ListenerSet = class {
|
|
287
|
+
#abort = new AbortController();
|
|
288
|
+
add(target, type, handler, options) {
|
|
289
|
+
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
290
|
+
}
|
|
291
|
+
dispose() {
|
|
292
|
+
this.#abort.abort();
|
|
293
|
+
this.#abort = new AbortController();
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
102
297
|
var TimerRegistry = class {
|
|
103
|
-
/** Live timer ids that have not yet been cleared (or, for timeouts, fired). */
|
|
104
298
|
ids = /* @__PURE__ */ new Set();
|
|
105
|
-
/**
|
|
106
|
-
* Cancels a single tracked timer.
|
|
107
|
-
*
|
|
108
|
-
* No-ops if the id is unknown (already cleared, fired, or never owned by this
|
|
109
|
-
* registry), so callers can clear defensively without guarding.
|
|
110
|
-
*/
|
|
111
299
|
clear(id) {
|
|
112
300
|
if (this.ids.delete(id)) {
|
|
113
301
|
this.cancel(id);
|
|
114
302
|
}
|
|
115
303
|
}
|
|
116
|
-
/**
|
|
117
|
-
* Cancels every tracked timer. Call this from a controller's `disconnect()`
|
|
118
|
-
* to guarantee no timer outlives the element.
|
|
119
|
-
*/
|
|
120
304
|
clearAll() {
|
|
121
305
|
for (const id of this.ids) {
|
|
122
306
|
this.cancel(id);
|
|
123
307
|
}
|
|
124
308
|
this.ids.clear();
|
|
125
309
|
}
|
|
126
|
-
/** Number of timers currently tracked (pending). */
|
|
127
310
|
get size() {
|
|
128
311
|
return this.ids.size;
|
|
129
312
|
}
|
|
130
313
|
};
|
|
131
314
|
var SafeTimeout = class extends TimerRegistry {
|
|
132
|
-
/**
|
|
133
|
-
* Schedules `callback` after `delay` ms and returns the timer id.
|
|
134
|
-
*
|
|
135
|
-
* The id is removed from the registry automatically when the timeout fires,
|
|
136
|
-
* so {@link TimerRegistry.size | size} reflects only still-pending timers.
|
|
137
|
-
*/
|
|
138
315
|
set(callback, delay) {
|
|
139
316
|
const id = this.schedule(() => {
|
|
140
317
|
this.ids.delete(id);
|
|
@@ -151,52 +328,60 @@ var SafeTimeout = class extends TimerRegistry {
|
|
|
151
328
|
}
|
|
152
329
|
};
|
|
153
330
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
var POINTER_EVENTS = /* @__PURE__ */ new Set(["mouseenter", "mouseleave", "pointerenter", "pointerleave"]);
|
|
157
|
-
function stateReasonFor(event) {
|
|
158
|
-
if (!event) return "api";
|
|
159
|
-
if (FOCUS_EVENTS.has(event.type)) return "focus";
|
|
160
|
-
if (POINTER_EVENTS.has(event.type)) return "pointer";
|
|
161
|
-
return "user";
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// src/controllers/context_menu_controller.ts
|
|
165
|
-
var ContextMenuController = class extends Controller {
|
|
331
|
+
var ContextMenuController = class _ContextMenuController extends Controller {
|
|
332
|
+
static #COORDINATE = ["--stimeo--context-menu-x", "--stimeo--context-menu-y"];
|
|
166
333
|
static targets = ["region", "menu", "item"];
|
|
167
334
|
static actions = ["activate", "onItemKeydown", "onRegionKeydown", "open"];
|
|
168
335
|
static events = ["close", "open"];
|
|
169
336
|
#timers = new SafeTimeout();
|
|
170
|
-
/** Escape-stack membership while open; the shared resolver dismisses via it. */
|
|
171
337
|
#escapeLayer = new EscapeLayer();
|
|
172
|
-
|
|
338
|
+
#menuHidden = new AttributeLease("hidden", this.identifier);
|
|
339
|
+
#regionState = new AttributeLease("data-state", this.identifier);
|
|
340
|
+
#menu = null;
|
|
341
|
+
#connected = false;
|
|
173
342
|
#reporting = false;
|
|
174
|
-
|
|
343
|
+
#clickVerdicts = new ClickVerdicts();
|
|
344
|
+
#listeners = new ListenerSet();
|
|
175
345
|
connect() {
|
|
176
346
|
this.#closeMenu("api");
|
|
177
|
-
this.element
|
|
178
|
-
|
|
179
|
-
|
|
347
|
+
this.#listeners.add(this.element, "click", this.#onItemClickCapture, { capture: true });
|
|
348
|
+
this.#listeners.add(document, "click", this.#onOutsidePointer, { capture: true });
|
|
349
|
+
this.#listeners.add(document, "contextmenu", this.#onOutsidePointer, { capture: true });
|
|
350
|
+
this.#connected = true;
|
|
180
351
|
this.#reporting = true;
|
|
181
352
|
}
|
|
182
|
-
/** Releases the listeners, stack membership, and pending Tab-close task. */
|
|
183
353
|
disconnect() {
|
|
354
|
+
this.#connected = false;
|
|
184
355
|
this.#reporting = false;
|
|
185
356
|
this.#timers.clearAll();
|
|
186
357
|
this.#escapeLayer.deactivate();
|
|
187
|
-
this.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
this.#
|
|
358
|
+
this.#listeners.dispose();
|
|
359
|
+
}
|
|
360
|
+
regionTargetConnected() {
|
|
361
|
+
if (this.#connected) this.#reflectRegion();
|
|
362
|
+
}
|
|
363
|
+
regionTargetDisconnected(region) {
|
|
364
|
+
if (!this.regionTargets.includes(region)) this.#regionState.return(region);
|
|
365
|
+
if (this.#connected) this.#reflectRegion();
|
|
366
|
+
}
|
|
367
|
+
menuTargetConnected() {
|
|
368
|
+
this.#adoptMenu();
|
|
369
|
+
}
|
|
370
|
+
menuTargetDisconnected(menu) {
|
|
371
|
+
this.#adoptMenu();
|
|
372
|
+
if (!this.menuTargets.includes(menu)) this.#menuHidden.return(menu);
|
|
373
|
+
}
|
|
374
|
+
open(input) {
|
|
375
|
+
const source = actionSource(input);
|
|
376
|
+
source.event?.preventDefault();
|
|
377
|
+
if (source.event instanceof MouseEvent) {
|
|
378
|
+
this.#openAt(source.event.clientX, source.event.clientY, source.reason);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const anchor = source.host ?? (this.hasRegionTarget ? this.regionTarget : null);
|
|
382
|
+
const rect = anchor?.getBoundingClientRect() ?? { left: 0, top: 0, width: 0, height: 0 };
|
|
383
|
+
this.#openAt(rect.left + rect.width / 2, rect.top + rect.height / 2, source.reason);
|
|
198
384
|
}
|
|
199
|
-
/** Keyboard entry on the region: `Shift+F10` / `ContextMenu` open at center. */
|
|
200
385
|
onRegionKeydown(event) {
|
|
201
386
|
if (event.defaultPrevented) return;
|
|
202
387
|
const isContextKey = event.key === "ContextMenu" || event.key === "F10" && event.shiftKey;
|
|
@@ -205,10 +390,10 @@ var ContextMenuController = class extends Controller {
|
|
|
205
390
|
const rect = this.hasRegionTarget ? this.regionTarget.getBoundingClientRect() : { left: 0, top: 0, width: 0, height: 0 };
|
|
206
391
|
this.#openAt(rect.left + rect.width / 2, rect.top + rect.height / 2, stateReasonFor(event));
|
|
207
392
|
}
|
|
208
|
-
/** Roving focus and closing keys inside the menu. */
|
|
209
393
|
onItemKeydown(event) {
|
|
210
394
|
if (event.defaultPrevented) return;
|
|
211
395
|
if (isReservedArrowChord(event)) return;
|
|
396
|
+
if ((event.key === "Home" || event.key === "End") && hasModifierChord(event)) return;
|
|
212
397
|
const items = this.#navigableItems;
|
|
213
398
|
const currentIndex = items.indexOf(event.currentTarget);
|
|
214
399
|
switch (event.key) {
|
|
@@ -240,93 +425,101 @@ var ContextMenuController = class extends Controller {
|
|
|
240
425
|
break;
|
|
241
426
|
}
|
|
242
427
|
}
|
|
243
|
-
|
|
244
|
-
|
|
428
|
+
activate(event) {
|
|
429
|
+
const item = ownerOf(this.itemTargets, event?.target);
|
|
430
|
+
if (item !== null && this.#refuses(item, event)) return;
|
|
245
431
|
this.#closeAndRestore("select");
|
|
246
432
|
}
|
|
247
|
-
|
|
433
|
+
#refuses(item, event) {
|
|
434
|
+
const recorded = this.#clickVerdicts.for(event, item);
|
|
435
|
+
if (recorded !== void 0) return recorded;
|
|
436
|
+
return ownersOf(this.itemTargets, event?.target).some(
|
|
437
|
+
(owner) => this.#isActivationDisabled(owner)
|
|
438
|
+
);
|
|
439
|
+
}
|
|
248
440
|
#openAt(x, y, reason) {
|
|
249
441
|
if (!this.hasMenuTarget) return;
|
|
250
442
|
this.#timers.clearAll();
|
|
443
|
+
const menu = this.menuTarget;
|
|
251
444
|
const was = this.#isOpen;
|
|
252
445
|
this.#escapeLayer.activate(document, {
|
|
253
446
|
onDismiss: () => this.#closeAndRestore("escape"),
|
|
254
447
|
claims: claimsWhileFocusWithin(this.element)
|
|
255
448
|
});
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
this.
|
|
259
|
-
|
|
449
|
+
menu.style.setProperty(_ContextMenuController.#COORDINATE[0], `${x}px`);
|
|
450
|
+
menu.style.setProperty(_ContextMenuController.#COORDINATE[1], `${y}px`);
|
|
451
|
+
this.#menuHidden.write(menu, null);
|
|
452
|
+
this.#menu = menu;
|
|
453
|
+
if (this.hasRegionTarget) this.#regionState.write(this.regionTarget, "open");
|
|
260
454
|
if (!was && this.#reporting) this.dispatch("open", { detail: { reason }, cancelable: false });
|
|
261
455
|
if (!this.#isOpen) return;
|
|
262
456
|
this.#navigableItems[0]?.focus();
|
|
263
457
|
}
|
|
264
|
-
/** Hides the menu, reflects the collapsed state on the region, and reports a move. */
|
|
265
458
|
#closeMenu(reason) {
|
|
266
459
|
this.#timers.clearAll();
|
|
267
460
|
this.#escapeLayer.deactivate();
|
|
268
|
-
|
|
461
|
+
const menu = this.hasMenuTarget ? this.menuTarget : null;
|
|
462
|
+
this.#menu = menu;
|
|
463
|
+
if (!menu) return;
|
|
269
464
|
const was = this.#isOpen;
|
|
270
|
-
this.
|
|
271
|
-
if (this.hasRegionTarget) this.regionTarget
|
|
465
|
+
this.#menuHidden.write(menu, "");
|
|
466
|
+
if (this.hasRegionTarget) this.#regionState.write(this.regionTarget, "closed");
|
|
272
467
|
if (was && this.#reporting) this.dispatch("close", { detail: { reason }, cancelable: false });
|
|
273
468
|
}
|
|
274
|
-
|
|
469
|
+
#adoptMenu() {
|
|
470
|
+
if (!this.#connected) return;
|
|
471
|
+
const menu = this.hasMenuTarget ? this.menuTarget : null;
|
|
472
|
+
const previous = this.#menu;
|
|
473
|
+
this.#menu = menu;
|
|
474
|
+
if (!menu) {
|
|
475
|
+
this.#escapeLayer.deactivate();
|
|
476
|
+
} else if (menu !== previous) {
|
|
477
|
+
const open = previous !== null && !previous.hidden;
|
|
478
|
+
if (open) {
|
|
479
|
+
for (const property of _ContextMenuController.#COORDINATE) {
|
|
480
|
+
menu.style.setProperty(property, previous.style.getPropertyValue(property));
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
this.#menuHidden.write(menu, open ? null : "");
|
|
484
|
+
}
|
|
485
|
+
this.#reflectRegion();
|
|
486
|
+
}
|
|
487
|
+
#reflectRegion() {
|
|
488
|
+
if (!this.hasRegionTarget) return;
|
|
489
|
+
this.#regionState.write(this.regionTarget, this.#isOpen ? "open" : "closed");
|
|
490
|
+
}
|
|
275
491
|
#closeAndRestore(reason) {
|
|
276
492
|
this.#closeMenu(reason);
|
|
277
493
|
if (this.hasRegionTarget) this.regionTarget.focus();
|
|
278
494
|
}
|
|
279
|
-
/**
|
|
280
|
-
* Closes when a click or context-menu invocation lands outside this instance.
|
|
281
|
-
* Both subscriptions observe in the capture phase, so the target is judged
|
|
282
|
-
* against the tree the user actually pressed even when a consumer handler
|
|
283
|
-
* detaches it, and application code that stops bubbling cannot leave the menu
|
|
284
|
-
* open.
|
|
285
|
-
*/
|
|
286
495
|
#onOutsidePointer = (event) => {
|
|
287
496
|
if (this.#isOpen && !this.element.contains(event.target)) this.#closeMenu("outside");
|
|
288
497
|
};
|
|
289
|
-
/**
|
|
290
|
-
* Captures clicks so `aria-disabled` commands cannot reach consumer handlers.
|
|
291
|
-
* Native Enter/Space activation also synthesizes a click and is blocked here.
|
|
292
|
-
*/
|
|
293
498
|
#onItemClickCapture = (event) => {
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
499
|
+
const items = ownersOf(this.itemTargets, event.target);
|
|
500
|
+
this.#clickVerdicts.record(
|
|
501
|
+
event,
|
|
502
|
+
items,
|
|
503
|
+
items.some((item) => this.#isActivationDisabled(item))
|
|
298
504
|
);
|
|
299
|
-
if (!
|
|
505
|
+
if (!items.some((item) => isAriaDisabled(item))) return;
|
|
300
506
|
event.preventDefault();
|
|
301
507
|
event.stopImmediatePropagation();
|
|
302
508
|
};
|
|
303
|
-
/** Menu items eligible for roving focus (excludes hidden / natively disabled). */
|
|
304
509
|
get #navigableItems() {
|
|
305
510
|
return this.itemTargets.filter((item) => this.#isNavigable(item));
|
|
306
511
|
}
|
|
307
|
-
/**
|
|
308
|
-
* An item can take roving focus unless it is `hidden` or a natively `disabled`
|
|
309
|
-
* form control. CSS-only visibility is not detectable here and is the
|
|
310
|
-
* consumer's responsibility.
|
|
311
|
-
*
|
|
312
|
-
* **`aria-disabled="true"` stays reachable.** APG separates the two attributes
|
|
313
|
-
* by intent: `disabled` is for controls whose existence can be inferred from a
|
|
314
|
-
* neighbour (a greyed Next next to a Prev), while `aria-disabled` marks a
|
|
315
|
-
* control that must stay *discoverable* — and it names menu items as the
|
|
316
|
-
* example. Skipping it would hide the command's existence from a keyboard user
|
|
317
|
-
* entirely. Activation is suppressed separately, so the item announces itself
|
|
318
|
-
* and does nothing.
|
|
319
|
-
*/
|
|
320
512
|
#isNavigable(item) {
|
|
321
513
|
if (item.hasAttribute("hidden")) return false;
|
|
322
514
|
return !item.disabled;
|
|
323
515
|
}
|
|
324
|
-
|
|
516
|
+
#isActivationDisabled(item) {
|
|
517
|
+
return !this.#isNavigable(item) || isAriaDisabled(item);
|
|
518
|
+
}
|
|
325
519
|
get #isOpen() {
|
|
326
520
|
return this.hasMenuTarget && !this.menuTarget.hidden;
|
|
327
521
|
}
|
|
328
522
|
};
|
|
329
523
|
|
|
330
524
|
export { ContextMenuController };
|
|
331
|
-
//# sourceMappingURL=context_menu_controller.js.map
|
|
332
525
|
//# sourceMappingURL=context_menu_controller.js.map
|