stimeo-ui 0.15.0 → 0.17.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 +209 -0
- package/README.md +128 -1
- package/dist/cable/index.d.ts +79 -23
- package/dist/cable/index.js +392 -417
- package/dist/cable/index.js.map +1 -1
- package/dist/controllers/accordion_controller.d.ts +34 -5
- package/dist/controllers/accordion_controller.js +228 -28
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.d.ts +20 -9
- package/dist/controllers/alert_dialog_controller.js +862 -221
- package/dist/controllers/alert_dialog_controller.js.map +1 -1
- package/dist/controllers/announcer_controller.d.ts +38 -7
- package/dist/controllers/announcer_controller.js +135 -191
- 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 +295 -110
- package/dist/controllers/auto_submit_controller.js.map +1 -1
- package/dist/controllers/avatar_controller.js +172 -106
- package/dist/controllers/avatar_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.d.ts +10 -7
- package/dist/controllers/breadcrumb_controller.js +0 -129
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/bulk_select_controller.d.ts +22 -4
- package/dist/controllers/bulk_select_controller.js +264 -53
- package/dist/controllers/bulk_select_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +109 -28
- package/dist/controllers/calendar_controller.js +346 -180
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +99 -27
- package/dist/controllers/carousel_controller.js +587 -300
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/character_counter_controller.d.ts +18 -2
- package/dist/controllers/character_counter_controller.js +271 -143
- 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 +77 -75
- package/dist/controllers/checkbox_controller.js.map +1 -1
- package/dist/controllers/clipboard_controller.d.ts +44 -7
- package/dist/controllers/clipboard_controller.js +187 -108
- package/dist/controllers/clipboard_controller.js.map +1 -1
- package/dist/controllers/collapsible_controller.d.ts +41 -5
- package/dist/controllers/collapsible_controller.js +374 -108
- package/dist/controllers/collapsible_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.d.ts +47 -14
- package/dist/controllers/color_picker_controller.js +183 -127
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.d.ts +33 -6
- package/dist/controllers/combobox_controller.js +426 -109
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +45 -14
- package/dist/controllers/command_palette_controller.js +994 -350
- 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 +212 -125
- 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 +939 -245
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +36 -3
- package/dist/controllers/context_menu_controller.js +275 -127
- 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 +75 -2
- package/dist/controllers/countdown_controller.js +235 -97
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +93 -15
- package/dist/controllers/currency_input_controller.js +241 -118
- package/dist/controllers/currency_input_controller.js.map +1 -1
- package/dist/controllers/data_grid_controller.d.ts +78 -22
- package/dist/controllers/data_grid_controller.js +229 -135
- package/dist/controllers/data_grid_controller.js.map +1 -1
- package/dist/controllers/date_range_picker_controller.d.ts +64 -11
- package/dist/controllers/date_range_picker_controller.js +359 -165
- package/dist/controllers/date_range_picker_controller.js.map +1 -1
- package/dist/controllers/dialog_controller.d.ts +22 -3
- package/dist/controllers/dialog_controller.js +887 -225
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.d.ts +24 -7
- package/dist/controllers/direct_upload_controller.js +80 -142
- package/dist/controllers/direct_upload_controller.js.map +1 -1
- package/dist/controllers/dirty_form_controller.d.ts +2 -2
- package/dist/controllers/dirty_form_controller.js +26 -47
- 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 +175 -20
- package/dist/controllers/dismissible_controller.js.map +1 -1
- package/dist/controllers/drawer_controller.d.ts +52 -16
- package/dist/controllers/drawer_controller.js +963 -336
- package/dist/controllers/drawer_controller.js.map +1 -1
- package/dist/controllers/dropdown_controller.d.ts +39 -3
- package/dist/controllers/dropdown_controller.js +342 -85
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.d.ts +12 -1
- package/dist/controllers/editable_controller.js +182 -58
- package/dist/controllers/editable_controller.js.map +1 -1
- package/dist/controllers/empty_state_controller.js +67 -53
- package/dist/controllers/empty_state_controller.js.map +1 -1
- package/dist/controllers/file_dropzone_controller.d.ts +60 -18
- package/dist/controllers/file_dropzone_controller.js +426 -229
- package/dist/controllers/file_dropzone_controller.js.map +1 -1
- package/dist/controllers/filter_controller.d.ts +10 -4
- package/dist/controllers/filter_controller.js +78 -36
- package/dist/controllers/filter_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +57 -14
- package/dist/controllers/flash_controller.js +328 -211
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +12 -3
- package/dist/controllers/focus_controller.js +654 -239
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.js +153 -136
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.js +29 -96
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.d.ts +41 -9
- package/dist/controllers/frame_loading_controller.js +263 -198
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.d.ts +22 -2
- package/dist/controllers/highlight_controller.js +119 -70
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +65 -4
- package/dist/controllers/hover_card_controller.js +335 -118
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +58 -4
- package/dist/controllers/idle_controller.js +316 -65
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/input_mask_controller.d.ts +5 -2
- package/dist/controllers/input_mask_controller.js +116 -61
- 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 +147 -103
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.d.ts +16 -0
- package/dist/controllers/lazy_frame_controller.js +9 -56
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +84 -10
- package/dist/controllers/listbox_controller.js +413 -153
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.d.ts +1 -1
- package/dist/controllers/local_time_controller.js +54 -64
- 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 +70 -95
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/menu_controller.d.ts +40 -9
- package/dist/controllers/menu_controller.js +254 -167
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +15 -4
- package/dist/controllers/menubar_controller.js +206 -331
- package/dist/controllers/menubar_controller.js.map +1 -1
- package/dist/controllers/meter_controller.d.ts +20 -0
- package/dist/controllers/meter_controller.js +159 -71
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +50 -7
- package/dist/controllers/multi_select_controller.js +797 -388
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/navigation_menu_controller.d.ts +19 -1
- package/dist/controllers/navigation_menu_controller.js +156 -231
- 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 +373 -174
- 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 +241 -45
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +62 -10
- package/dist/controllers/number_input_controller.js +387 -227
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/optimistic_controller.js +28 -75
- package/dist/controllers/optimistic_controller.js.map +1 -1
- package/dist/controllers/otp_controller.d.ts +38 -7
- package/dist/controllers/otp_controller.js +344 -196
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.d.ts +13 -12
- package/dist/controllers/overflow_indicator_controller.js +167 -93
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +66 -9
- package/dist/controllers/overflow_menu_controller.js +408 -277
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +52 -15
- package/dist/controllers/pagination_controller.js +342 -120
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +60 -9
- package/dist/controllers/password_reveal_controller.js +424 -99
- package/dist/controllers/password_reveal_controller.js.map +1 -1
- package/dist/controllers/password_strength_controller.d.ts +14 -5
- package/dist/controllers/password_strength_controller.js +99 -153
- 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 +252 -96
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +19 -7
- package/dist/controllers/pointer_drag_controller.js +263 -164
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +46 -4
- package/dist/controllers/popover_controller.js +267 -94
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +44 -4
- package/dist/controllers/portal_controller.js +209 -72
- 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 -112
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/progress_controller.d.ts +11 -0
- package/dist/controllers/progress_controller.js +132 -59
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.d.ts +19 -8
- package/dist/controllers/radio_group_controller.js +138 -133
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +92 -4
- package/dist/controllers/range_slider_controller.js +245 -112
- package/dist/controllers/range_slider_controller.js.map +1 -1
- package/dist/controllers/rating_controller.d.ts +33 -6
- package/dist/controllers/rating_controller.js +429 -194
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.d.ts +26 -2
- package/dist/controllers/read_more_controller.js +185 -47
- 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 +147 -135
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/relative_time_controller.d.ts +18 -4
- package/dist/controllers/relative_time_controller.js +145 -110
- 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} +97 -38
- package/dist/controllers/reset_on_restore_controller.js.map +1 -0
- package/dist/controllers/resizable_controller.d.ts +44 -4
- package/dist/controllers/resizable_controller.js +294 -118
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.js +39 -84
- 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 +428 -221
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_restore_controller.js +0 -53
- 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 +395 -146
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.d.ts +9 -3
- package/dist/controllers/scrollspy_controller.js +181 -236
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +59 -17
- package/dist/controllers/separator_controller.js +288 -132
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/sidebar_controller.d.ts +81 -7
- package/dist/controllers/sidebar_controller.js +1071 -375
- package/dist/controllers/sidebar_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.d.ts +23 -0
- package/dist/controllers/skeleton_controller.js +248 -92
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +72 -8
- package/dist/controllers/slider_controller.js +211 -96
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.d.ts +21 -3
- package/dist/controllers/smart_sticky_header_controller.js +163 -54
- package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.js +13 -110
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.d.ts +39 -4
- package/dist/controllers/spinner_controller.js +277 -161
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +24 -17
- package/dist/controllers/step_indicator_controller.js +107 -53
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +43 -9
- package/dist/controllers/stepper_controller.js +171 -48
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +25 -0
- package/dist/controllers/stick_to_bottom_controller.js +310 -116
- 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 +214 -49
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +22 -6
- package/dist/controllers/submit_once_controller.js +294 -192
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +40 -7
- package/dist/controllers/switch_controller.js +107 -43
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +13 -1
- package/dist/controllers/tabs_controller.js +50 -25
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +27 -3
- package/dist/controllers/tags_input_controller.js +290 -149
- package/dist/controllers/tags_input_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.d.ts +10 -0
- package/dist/controllers/textarea_autosize_controller.js +71 -58
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/theme_controller.d.ts +37 -8
- package/dist/controllers/theme_controller.js +148 -80
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +18 -1
- package/dist/controllers/time_picker_controller.js +162 -81
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/toast_controller.d.ts +85 -23
- package/dist/controllers/toast_controller.js +365 -193
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.d.ts +60 -9
- package/dist/controllers/toggle_group_controller.js +194 -99
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.js +92 -90
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +52 -2
- package/dist/controllers/tooltip_controller.js +185 -125
- 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 -115
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +59 -18
- package/dist/controllers/tree_view_controller.js +248 -290
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.d.ts +33 -3
- package/dist/index.js +8649 -8572
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +95 -9
- package/dist/inspector/cli.js +343 -77
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +390 -96
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +45 -45
- package/dist/inspector/manifest.json +1308 -155
- package/dist/positioning/index.d.ts +8 -0
- package/dist/positioning/index.js +148 -45
- package/dist/positioning/index.js.map +1 -1
- package/package.json +7 -7
- package/dist/controllers/reset_before_cache_controller.d.ts +0 -76
- package/dist/controllers/reset_before_cache_controller.js.map +0 -1
|
@@ -27,25 +27,61 @@ import { Controller } from '@hotwired/stimulus';
|
|
|
27
27
|
* non-focusable menu content), so a press aimed at another layer never closes
|
|
28
28
|
* the menu or steals focus, and one keypress closes exactly one layer.
|
|
29
29
|
* - A click outside the controller element closes the menu.
|
|
30
|
+
* - A trigger or a menu that takes over — in one task, or after an earlier one leaves
|
|
31
|
+
* in a later task — carries the open state, and an `aria-controls` this controller
|
|
32
|
+
* supplied names the menu that is first. With no menu left the dropdown reads
|
|
33
|
+
* closed and leaves the Escape stack. One that stops resolving as the target gets
|
|
34
|
+
* back what it carried before this controller wrote on it.
|
|
35
|
+
* - A Turbo morph that keeps the elements drops the attributes the server did not
|
|
36
|
+
* send — the menu's `hidden`, the trigger's `aria-expanded` and the
|
|
37
|
+
* `aria-controls` this controller supplied. They are written back from the open
|
|
38
|
+
* state the controller holds, so a closed menu does not show up and an open one
|
|
39
|
+
* stays described.
|
|
40
|
+
* - Each move of the open state is reported: `stimeo--dropdown:open` and
|
|
41
|
+
* `stimeo--dropdown:close` dispatch `{ reason: StateReason }`, after the
|
|
42
|
+
* attributes above are written. Both are informational, so neither is
|
|
43
|
+
* cancelable. A call that leaves the state where it already was, the
|
|
44
|
+
* normalization in {@link connect}, a trigger or a menu that takes over, the
|
|
45
|
+
* repair after a morph, and {@link disconnect} are all silent.
|
|
30
46
|
*/
|
|
31
47
|
declare class DropdownController extends Controller<HTMLElement> {
|
|
32
48
|
#private;
|
|
33
49
|
static targets: string[];
|
|
34
50
|
static actions: readonly ["close", "open", "toggle"];
|
|
51
|
+
static events: readonly ["close", "open"];
|
|
35
52
|
readonly triggerTarget: HTMLButtonElement;
|
|
53
|
+
readonly triggerTargets: HTMLButtonElement[];
|
|
36
54
|
readonly menuTarget: HTMLElement;
|
|
55
|
+
readonly menuTargets: HTMLElement[];
|
|
37
56
|
readonly hasMenuTarget: boolean;
|
|
38
57
|
readonly hasTriggerTarget: boolean;
|
|
39
58
|
/** Starts in the closed state and registers outside-click handling. */
|
|
40
59
|
connect(): void;
|
|
41
60
|
/** Removes the listeners registered in {@link connect}. */
|
|
42
61
|
disconnect(): void;
|
|
62
|
+
/** Brings a trigger that arrives after connect to the open state and names the menu from it. */
|
|
63
|
+
triggerTargetConnected(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Gives a trigger that no longer resolves as one its own `aria-expanded` and `aria-controls`
|
|
66
|
+
* back — after `disconnect()` too, since dropping the identifier leaves the element on the
|
|
67
|
+
* page — and brings the trigger that stays to the open state.
|
|
68
|
+
*/
|
|
69
|
+
triggerTargetDisconnected(trigger: HTMLButtonElement): void;
|
|
70
|
+
/** Applies the open state to a menu that arrives after connect in front of the others. */
|
|
71
|
+
menuTargetConnected(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Applies the open state to the menu left, then gives a menu that no longer resolves as the
|
|
74
|
+
* target its own `hidden` back — after `disconnect()` too, since dropping the identifier
|
|
75
|
+
* leaves the element on the page. The open state is read off the departing menu first,
|
|
76
|
+
* while it still carries it.
|
|
77
|
+
*/
|
|
78
|
+
menuTargetDisconnected(menu: HTMLElement): void;
|
|
43
79
|
/** Toggles the menu between open and closed. Bound via `data-action`. */
|
|
44
|
-
toggle(): void;
|
|
80
|
+
toggle(event?: Event): void;
|
|
45
81
|
/** Reveals the menu and reflects the open state on the trigger. */
|
|
46
|
-
open(): void;
|
|
82
|
+
open(event?: Event): void;
|
|
47
83
|
/** Hides the menu and reflects the closed state on the trigger. */
|
|
48
|
-
close(): void;
|
|
84
|
+
close(event?: Event): void;
|
|
49
85
|
}
|
|
50
86
|
|
|
51
87
|
export { DropdownController };
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
function sharedRegistry(key, create) {
|
|
4
|
+
const symbol = Symbol.for(key);
|
|
5
|
+
const scope = globalThis;
|
|
6
|
+
const existing = scope[symbol];
|
|
7
|
+
if (existing !== void 0) return existing;
|
|
8
|
+
const registry = create();
|
|
9
|
+
Object.defineProperty(globalThis, symbol, { value: registry });
|
|
10
|
+
return registry;
|
|
11
|
+
}
|
|
4
12
|
|
|
5
|
-
|
|
6
|
-
var counter = 0;
|
|
13
|
+
var ids = sharedRegistry("stimeo-ui.aria-ids.registry.v1", () => ({ counter: 0 }));
|
|
7
14
|
function uniqueId(prefix = "stimeo") {
|
|
8
15
|
let candidate;
|
|
9
16
|
do {
|
|
10
|
-
counter += 1;
|
|
11
|
-
candidate = `${prefix}-${counter}`;
|
|
17
|
+
ids.counter += 1;
|
|
18
|
+
candidate = `${prefix}-${ids.counter}`;
|
|
12
19
|
} while (typeof document !== "undefined" && document.getElementById(candidate) !== null);
|
|
13
20
|
return candidate;
|
|
14
21
|
}
|
|
@@ -19,7 +26,143 @@ function ensureId(element, prefix = "stimeo") {
|
|
|
19
26
|
return id;
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
|
|
29
|
+
function isAttributeValue(value) {
|
|
30
|
+
return value === null || typeof value === "string";
|
|
31
|
+
}
|
|
32
|
+
function readLeaseRecord(element, record) {
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(element.getAttribute(record) ?? "null");
|
|
35
|
+
if (!Array.isArray(parsed)) return void 0;
|
|
36
|
+
const [original, written, ...rest] = parsed;
|
|
37
|
+
const linked = rest[0] !== false;
|
|
38
|
+
const beneath = linked ? rest : rest.slice(1);
|
|
39
|
+
if (!beneath.every((under) => typeof under === "string")) return void 0;
|
|
40
|
+
return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
|
|
41
|
+
} catch {
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
var AttributeLease = class _AttributeLease {
|
|
46
|
+
static #registry = sharedRegistry(
|
|
47
|
+
"stimeo-ui.attribute-lease.registry.v1",
|
|
48
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
|
|
49
|
+
);
|
|
50
|
+
#attribute;
|
|
51
|
+
#record;
|
|
52
|
+
#base;
|
|
53
|
+
#held = /* @__PURE__ */ new Set();
|
|
54
|
+
constructor(attribute, owner, options = {}) {
|
|
55
|
+
this.#attribute = attribute;
|
|
56
|
+
this.#record = `data-${owner}-${attribute}-lease`;
|
|
57
|
+
this.#base = options.base === true;
|
|
58
|
+
const names = _AttributeLease.#registry.names;
|
|
59
|
+
names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
|
|
60
|
+
}
|
|
61
|
+
write(element, value) {
|
|
62
|
+
const stack = this.#stack(element);
|
|
63
|
+
const hold = this.#take(stack) ?? this.#acquire(element, stack);
|
|
64
|
+
this.#held.add(element);
|
|
65
|
+
const shows = !this.#covered(element, stack, hold);
|
|
66
|
+
hold.written = value;
|
|
67
|
+
this.#mark(element, stack);
|
|
68
|
+
if (shows) this.#reflect(element, value);
|
|
69
|
+
}
|
|
70
|
+
return(element) {
|
|
71
|
+
const held = this.#held.delete(element);
|
|
72
|
+
const known = _AttributeLease.#registry.stacks.get(element)?.has(this.#attribute);
|
|
73
|
+
const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
|
|
74
|
+
const hold = this.#take(stack);
|
|
75
|
+
if (!hold) return false;
|
|
76
|
+
const carries = element.getAttribute(this.#attribute) === hold.written;
|
|
77
|
+
const owns = carries && !this.#covered(element, stack, hold);
|
|
78
|
+
const index = stack.indexOf(hold);
|
|
79
|
+
stack.splice(index, 1);
|
|
80
|
+
const above = stack[index];
|
|
81
|
+
if (above) above.linked &&= hold.linked;
|
|
82
|
+
this.#mark(element, stack);
|
|
83
|
+
if (!owns) return true;
|
|
84
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
85
|
+
this.#reflect(element, below ? below.written : hold.original);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
returnAll() {
|
|
89
|
+
for (const element of Array.from(this.#held)) this.return(element);
|
|
90
|
+
}
|
|
91
|
+
#stack(element) {
|
|
92
|
+
const stacks = _AttributeLease.#registry.stacks;
|
|
93
|
+
const byAttribute = stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
94
|
+
stacks.set(element, byAttribute);
|
|
95
|
+
const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);
|
|
96
|
+
byAttribute.set(this.#attribute, stack);
|
|
97
|
+
return stack;
|
|
98
|
+
}
|
|
99
|
+
#seed(element) {
|
|
100
|
+
const found = [];
|
|
101
|
+
for (const record of _AttributeLease.#registry.names.get(this.#attribute) ?? []) {
|
|
102
|
+
const read = readLeaseRecord(element, record);
|
|
103
|
+
if (read) found.push({ ...read, record });
|
|
104
|
+
}
|
|
105
|
+
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
106
|
+
return found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
|
|
107
|
+
lease: null,
|
|
108
|
+
record,
|
|
109
|
+
written,
|
|
110
|
+
original,
|
|
111
|
+
linked: linked && index > 0
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
#take(stack) {
|
|
115
|
+
const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
|
|
116
|
+
if (hold) hold.lease = this;
|
|
117
|
+
return hold;
|
|
118
|
+
}
|
|
119
|
+
#acquire(element, stack) {
|
|
120
|
+
const current = element.getAttribute(this.#attribute);
|
|
121
|
+
const top = stack.at(-1);
|
|
122
|
+
const bottom = stack[0];
|
|
123
|
+
const over = top?.written === current ? top : void 0;
|
|
124
|
+
const from = this.#base ? bottom : over;
|
|
125
|
+
const hold = {
|
|
126
|
+
lease: this,
|
|
127
|
+
record: this.#record,
|
|
128
|
+
written: current,
|
|
129
|
+
original: from ? from.original : current,
|
|
130
|
+
linked: !this.#base && over !== void 0
|
|
131
|
+
};
|
|
132
|
+
if (this.#base && bottom) {
|
|
133
|
+
bottom.linked = true;
|
|
134
|
+
stack.unshift(hold);
|
|
135
|
+
} else stack.push(hold);
|
|
136
|
+
return hold;
|
|
137
|
+
}
|
|
138
|
+
#covered(element, stack, hold) {
|
|
139
|
+
const current = element.getAttribute(this.#attribute);
|
|
140
|
+
return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
|
|
141
|
+
}
|
|
142
|
+
#mark(element, stack) {
|
|
143
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
144
|
+
stack.forEach((hold, index) => {
|
|
145
|
+
const names = stack.slice(0, index).map((under) => under.record);
|
|
146
|
+
const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
|
|
147
|
+
const marker = hold.linked || beneath.length === 0 ? [] : [false];
|
|
148
|
+
records.set(
|
|
149
|
+
hold.record,
|
|
150
|
+
hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
for (const [name, recorded] of records) {
|
|
154
|
+
if (element.getAttribute(name) === recorded) continue;
|
|
155
|
+
if (recorded === null) element.removeAttribute(name);
|
|
156
|
+
else element.setAttribute(name, recorded);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
#reflect(element, value) {
|
|
160
|
+
if (element.getAttribute(this.#attribute) === value) return;
|
|
161
|
+
if (value === null) element.removeAttribute(this.#attribute);
|
|
162
|
+
else element.setAttribute(this.#attribute, value);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
23
166
|
function claimsWhileFocusWithin(element) {
|
|
24
167
|
return () => {
|
|
25
168
|
const active = element.ownerDocument.activeElement;
|
|
@@ -27,17 +170,11 @@ function claimsWhileFocusWithin(element) {
|
|
|
27
170
|
};
|
|
28
171
|
}
|
|
29
172
|
var EscapeLayer = class _EscapeLayer {
|
|
30
|
-
static #registries =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
#claims = null;
|
|
36
|
-
/**
|
|
37
|
-
* Activates this layer at the top of its document's Escape stack, installing
|
|
38
|
-
* the document's shared resolver listener if this is its first layer.
|
|
39
|
-
* Re-activating an already-active layer moves it to the top.
|
|
40
|
-
*/
|
|
173
|
+
static #registries = sharedRegistry(
|
|
174
|
+
"stimeo-ui.escape-layer.registry.v1",
|
|
175
|
+
() => /* @__PURE__ */ new WeakMap()
|
|
176
|
+
);
|
|
177
|
+
#active = null;
|
|
41
178
|
activate(ownerDocument = document, options) {
|
|
42
179
|
this.deactivate();
|
|
43
180
|
let registry = _EscapeLayer.#registries.get(ownerDocument);
|
|
@@ -46,44 +183,31 @@ var EscapeLayer = class _EscapeLayer {
|
|
|
46
183
|
_EscapeLayer.#registries.set(ownerDocument, registry);
|
|
47
184
|
ownerDocument.addEventListener("keydown", registry.onKeydown);
|
|
48
185
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.#
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Removes this layer from its document's Escape stack, uninstalling the
|
|
56
|
-
* shared listener when the stack empties. Safe to call when inactive.
|
|
57
|
-
*/
|
|
186
|
+
const entry = { onDismiss: options.onDismiss, claims: options.claims ?? null };
|
|
187
|
+
registry.stack.push(entry);
|
|
188
|
+
this.#active = { document: ownerDocument, entry };
|
|
189
|
+
}
|
|
58
190
|
deactivate() {
|
|
59
|
-
const
|
|
60
|
-
if (!
|
|
61
|
-
const registry = _EscapeLayer.#registries.get(
|
|
191
|
+
const active = this.#active;
|
|
192
|
+
if (!active) return;
|
|
193
|
+
const registry = _EscapeLayer.#registries.get(active.document);
|
|
62
194
|
if (registry) {
|
|
63
|
-
const index = registry.stack.lastIndexOf(
|
|
195
|
+
const index = registry.stack.lastIndexOf(active.entry);
|
|
64
196
|
if (index >= 0) registry.stack.splice(index, 1);
|
|
65
197
|
if (registry.stack.length === 0) {
|
|
66
|
-
|
|
67
|
-
_EscapeLayer.#registries.delete(
|
|
198
|
+
active.document.removeEventListener("keydown", registry.onKeydown);
|
|
199
|
+
_EscapeLayer.#registries.delete(active.document);
|
|
68
200
|
}
|
|
69
201
|
}
|
|
70
|
-
this.#
|
|
71
|
-
|
|
72
|
-
this.#claims = null;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Whether this active layer would own a press right now: it is the topmost
|
|
76
|
-
* layer whose {@link EscapeLayerOptions.claims} passes. Exposed for tests
|
|
77
|
-
* and diagnostics — production dismissal goes through the shared listener.
|
|
78
|
-
*/
|
|
202
|
+
this.#active = null;
|
|
203
|
+
}
|
|
79
204
|
get ownsEscape() {
|
|
80
|
-
const
|
|
81
|
-
if (!
|
|
82
|
-
const registry = _EscapeLayer.#registries.get(
|
|
205
|
+
const active = this.#active;
|
|
206
|
+
if (!active) return false;
|
|
207
|
+
const registry = _EscapeLayer.#registries.get(active.document);
|
|
83
208
|
if (!registry) return false;
|
|
84
|
-
return _EscapeLayer.#resolveOwner(registry.stack) ===
|
|
209
|
+
return _EscapeLayer.#resolveOwner(registry.stack) === active.entry;
|
|
85
210
|
}
|
|
86
|
-
/** Builds a document's registry with its shared resolver listener. */
|
|
87
211
|
static #createRegistry() {
|
|
88
212
|
const registry = {
|
|
89
213
|
stack: [],
|
|
@@ -92,98 +216,231 @@ var EscapeLayer = class _EscapeLayer {
|
|
|
92
216
|
const owner = _EscapeLayer.#resolveOwner(registry.stack);
|
|
93
217
|
if (!owner) return;
|
|
94
218
|
event.preventDefault();
|
|
95
|
-
owner
|
|
219
|
+
owner.onDismiss();
|
|
96
220
|
}
|
|
97
221
|
};
|
|
98
222
|
return registry;
|
|
99
223
|
}
|
|
100
|
-
/** The topmost stack layer whose claims predicate passes, or `null`. */
|
|
101
224
|
static #resolveOwner(stack) {
|
|
102
225
|
for (let index = stack.length - 1; index >= 0; index--) {
|
|
103
226
|
const layer = stack[index];
|
|
104
227
|
if (!layer) continue;
|
|
105
|
-
if (layer
|
|
228
|
+
if (layer.claims && !layer.claims()) continue;
|
|
106
229
|
return layer;
|
|
107
230
|
}
|
|
108
231
|
return null;
|
|
109
232
|
}
|
|
110
233
|
};
|
|
111
234
|
|
|
112
|
-
|
|
235
|
+
var ListenerSet = class {
|
|
236
|
+
#abort = new AbortController();
|
|
237
|
+
add(target, type, handler, options) {
|
|
238
|
+
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
239
|
+
}
|
|
240
|
+
dispose() {
|
|
241
|
+
this.#abort.abort();
|
|
242
|
+
this.#abort = new AbortController();
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
var MicrotaskCoalescer = class {
|
|
247
|
+
#run;
|
|
248
|
+
#queued = false;
|
|
249
|
+
#active = false;
|
|
250
|
+
#generation = 0;
|
|
251
|
+
constructor(run) {
|
|
252
|
+
this.#run = run;
|
|
253
|
+
}
|
|
254
|
+
activate() {
|
|
255
|
+
this.#active = true;
|
|
256
|
+
}
|
|
257
|
+
cancel() {
|
|
258
|
+
this.#active = false;
|
|
259
|
+
this.#queued = false;
|
|
260
|
+
this.#generation += 1;
|
|
261
|
+
}
|
|
262
|
+
schedule() {
|
|
263
|
+
if (!this.#active || this.#queued) return;
|
|
264
|
+
this.#queued = true;
|
|
265
|
+
const generation = this.#generation;
|
|
266
|
+
queueMicrotask(() => {
|
|
267
|
+
if (generation !== this.#generation || !this.#queued || !this.#active) return;
|
|
268
|
+
this.#queued = false;
|
|
269
|
+
this.#run();
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
var MorphRenderWatcher = class {
|
|
275
|
+
#listeners = new ListenerSet();
|
|
276
|
+
#pass;
|
|
277
|
+
#element = null;
|
|
278
|
+
#onMorph = () => this.#pass.schedule();
|
|
279
|
+
constructor(run) {
|
|
280
|
+
this.#pass = new MicrotaskCoalescer(run);
|
|
281
|
+
}
|
|
282
|
+
observe(element) {
|
|
283
|
+
if (this.#element === element) return;
|
|
284
|
+
this.disconnect();
|
|
285
|
+
this.#element = element;
|
|
286
|
+
this.#pass.activate();
|
|
287
|
+
this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
|
|
288
|
+
}
|
|
289
|
+
schedule() {
|
|
290
|
+
this.#pass.schedule();
|
|
291
|
+
}
|
|
292
|
+
disconnect() {
|
|
293
|
+
this.#listeners.dispose();
|
|
294
|
+
this.#pass.cancel();
|
|
295
|
+
this.#element = null;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
var FOCUS_EVENTS = /* @__PURE__ */ new Set(["blur", "focus", "focusin", "focusout"]);
|
|
300
|
+
var POINTER_EVENTS = /* @__PURE__ */ new Set(["mouseenter", "mouseleave", "pointerenter", "pointerleave"]);
|
|
301
|
+
function stateReasonFor(event) {
|
|
302
|
+
if (!event) return "api";
|
|
303
|
+
if (FOCUS_EVENTS.has(event.type)) return "focus";
|
|
304
|
+
if (POINTER_EVENTS.has(event.type)) return "pointer";
|
|
305
|
+
return "user";
|
|
306
|
+
}
|
|
307
|
+
|
|
113
308
|
var DropdownController = class extends Controller {
|
|
114
309
|
static targets = ["trigger", "menu"];
|
|
115
310
|
static actions = ["close", "open", "toggle"];
|
|
116
|
-
|
|
311
|
+
static events = ["close", "open"];
|
|
117
312
|
#escapeLayer = new EscapeLayer();
|
|
118
|
-
|
|
313
|
+
#menuHidden = new AttributeLease("hidden", this.identifier);
|
|
314
|
+
#expanded = new AttributeLease("aria-expanded", this.identifier);
|
|
315
|
+
#suppliedControls = /* @__PURE__ */ new WeakMap();
|
|
316
|
+
#menu = null;
|
|
317
|
+
#connected = false;
|
|
318
|
+
#reporting = false;
|
|
319
|
+
#openState = false;
|
|
320
|
+
#morphRender = new MorphRenderWatcher(() => this.#repair());
|
|
119
321
|
#onOutsideClick = (event) => {
|
|
120
322
|
if (!this.element.contains(event.target)) {
|
|
121
|
-
this
|
|
323
|
+
this.#close("outside");
|
|
122
324
|
}
|
|
123
325
|
};
|
|
124
|
-
/** Starts in the closed state and registers outside-click handling. */
|
|
125
326
|
connect() {
|
|
126
327
|
this.#associateTriggerWithMenu();
|
|
127
|
-
this
|
|
328
|
+
this.#close("api");
|
|
128
329
|
document.addEventListener("click", this.#onOutsideClick, true);
|
|
330
|
+
this.#morphRender.observe(this.element);
|
|
331
|
+
this.#connected = true;
|
|
332
|
+
this.#reporting = true;
|
|
129
333
|
}
|
|
130
|
-
/** Removes the listeners registered in {@link connect}. */
|
|
131
334
|
disconnect() {
|
|
335
|
+
this.#connected = false;
|
|
336
|
+
this.#reporting = false;
|
|
132
337
|
this.#escapeLayer.deactivate();
|
|
133
338
|
document.removeEventListener("click", this.#onOutsideClick, true);
|
|
339
|
+
this.#morphRender.disconnect();
|
|
340
|
+
}
|
|
341
|
+
triggerTargetConnected() {
|
|
342
|
+
if (this.#connected) this.#reflectTrigger();
|
|
134
343
|
}
|
|
135
|
-
|
|
136
|
-
|
|
344
|
+
triggerTargetDisconnected(trigger) {
|
|
345
|
+
if (!this.triggerTargets.includes(trigger)) {
|
|
346
|
+
this.#expanded.return(trigger);
|
|
347
|
+
this.#withdrawControls(trigger);
|
|
348
|
+
}
|
|
349
|
+
if (this.#connected) this.#reflectTrigger();
|
|
350
|
+
}
|
|
351
|
+
menuTargetConnected() {
|
|
352
|
+
this.#adoptMenu();
|
|
353
|
+
}
|
|
354
|
+
menuTargetDisconnected(menu) {
|
|
355
|
+
this.#adoptMenu();
|
|
356
|
+
if (!this.menuTargets.includes(menu)) this.#menuHidden.return(menu);
|
|
357
|
+
}
|
|
358
|
+
toggle(event) {
|
|
137
359
|
if (this.#isOpen) {
|
|
138
|
-
this.close();
|
|
360
|
+
this.close(event);
|
|
139
361
|
} else {
|
|
140
|
-
this.open();
|
|
362
|
+
this.open(event);
|
|
141
363
|
}
|
|
142
364
|
}
|
|
143
|
-
|
|
144
|
-
|
|
365
|
+
open(event) {
|
|
366
|
+
this.#open(stateReasonFor(event));
|
|
367
|
+
}
|
|
368
|
+
close(event) {
|
|
369
|
+
this.#close(stateReasonFor(event));
|
|
370
|
+
}
|
|
371
|
+
#open(reason) {
|
|
145
372
|
if (!this.hasMenuTarget) return;
|
|
373
|
+
const menu = this.menuTarget;
|
|
374
|
+
const was = this.#isOpen;
|
|
146
375
|
this.#escapeLayer.activate(document, {
|
|
147
376
|
onDismiss: () => this.#closeAndRestore(),
|
|
148
377
|
claims: claimsWhileFocusWithin(this.element)
|
|
149
378
|
});
|
|
150
|
-
this.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
379
|
+
this.#menuHidden.write(menu, null);
|
|
380
|
+
this.#menu = menu;
|
|
381
|
+
this.#openState = true;
|
|
382
|
+
if (this.hasTriggerTarget) this.#expanded.write(this.triggerTarget, "true");
|
|
383
|
+
if (!was && this.#reporting) this.dispatch("open", { detail: { reason }, cancelable: false });
|
|
154
384
|
}
|
|
155
|
-
|
|
156
|
-
|
|
385
|
+
#close(reason) {
|
|
386
|
+
const was = this.#isOpen;
|
|
157
387
|
this.#escapeLayer.deactivate();
|
|
158
|
-
|
|
159
|
-
this.menuTarget
|
|
160
|
-
|
|
161
|
-
|
|
388
|
+
this.#openState = false;
|
|
389
|
+
const menu = this.hasMenuTarget ? this.menuTarget : null;
|
|
390
|
+
this.#menu = menu;
|
|
391
|
+
if (!menu) return;
|
|
392
|
+
this.#menuHidden.write(menu, "");
|
|
393
|
+
if (this.hasTriggerTarget) this.#expanded.write(this.triggerTarget, "false");
|
|
394
|
+
if (was && this.#reporting) this.dispatch("close", { detail: { reason }, cancelable: false });
|
|
395
|
+
}
|
|
396
|
+
#adoptMenu() {
|
|
397
|
+
if (!this.#connected) return;
|
|
398
|
+
const menu = this.hasMenuTarget ? this.menuTarget : null;
|
|
399
|
+
const previous = this.#menu;
|
|
400
|
+
this.#menu = menu;
|
|
401
|
+
if (!menu) {
|
|
402
|
+
this.#escapeLayer.deactivate();
|
|
403
|
+
this.#openState = false;
|
|
404
|
+
} else if (menu !== previous) {
|
|
405
|
+
this.#menuHidden.write(menu, previous?.hidden ?? true ? "" : null);
|
|
162
406
|
}
|
|
407
|
+
this.#reflectTrigger();
|
|
408
|
+
}
|
|
409
|
+
#reflectTrigger() {
|
|
410
|
+
if (!this.hasTriggerTarget) return;
|
|
411
|
+
this.#expanded.write(this.triggerTarget, String(this.#isOpen));
|
|
412
|
+
this.#associateTriggerWithMenu();
|
|
413
|
+
}
|
|
414
|
+
#repair() {
|
|
415
|
+
if (!this.hasMenuTarget) return;
|
|
416
|
+
this.#menuHidden.write(this.menuTarget, this.#openState ? null : "");
|
|
417
|
+
this.#reflectTrigger();
|
|
163
418
|
}
|
|
164
|
-
/** Closes and restores focus to the trigger (the keyboard-dismissal path). */
|
|
165
419
|
#closeAndRestore() {
|
|
166
|
-
this
|
|
420
|
+
this.#close("escape");
|
|
167
421
|
if (this.hasTriggerTarget) this.triggerTarget.focus();
|
|
168
422
|
}
|
|
169
|
-
/** Whether the menu is currently visible. */
|
|
170
423
|
get #isOpen() {
|
|
171
424
|
return this.hasMenuTarget && !this.menuTarget.hidden;
|
|
172
425
|
}
|
|
173
|
-
/**
|
|
174
|
-
* Associates the disclosure trigger and controlled region without clobbering
|
|
175
|
-
* authored markup.
|
|
176
|
-
*/
|
|
177
426
|
#associateTriggerWithMenu() {
|
|
178
427
|
if (!this.hasTriggerTarget || !this.hasMenuTarget) return;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
);
|
|
428
|
+
const trigger = this.triggerTarget;
|
|
429
|
+
const controls = trigger.getAttribute("aria-controls");
|
|
430
|
+
if (controls !== null && controls !== this.#suppliedControls.get(trigger)) return;
|
|
431
|
+
const id = ensureId(this.menuTarget, "stimeo--dropdown-menu");
|
|
432
|
+
if (controls === id) return;
|
|
433
|
+
trigger.setAttribute("aria-controls", id);
|
|
434
|
+
this.#suppliedControls.set(trigger, id);
|
|
435
|
+
}
|
|
436
|
+
#withdrawControls(trigger) {
|
|
437
|
+
const supplied = this.#suppliedControls.get(trigger);
|
|
438
|
+
this.#suppliedControls.delete(trigger);
|
|
439
|
+
if (supplied !== void 0 && trigger.getAttribute("aria-controls") === supplied) {
|
|
440
|
+
trigger.removeAttribute("aria-controls");
|
|
441
|
+
}
|
|
184
442
|
}
|
|
185
443
|
};
|
|
186
444
|
|
|
187
445
|
export { DropdownController };
|
|
188
|
-
//# sourceMappingURL=dropdown_controller.js.map
|
|
189
446
|
//# sourceMappingURL=dropdown_controller.js.map
|