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,8 +1,5 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
// src/controllers/auto_submit_controller.ts
|
|
4
|
-
|
|
5
|
-
// src/utils/announce.ts
|
|
6
3
|
function announce(message, options = {}) {
|
|
7
4
|
const text = message.trim();
|
|
8
5
|
if (text.length === 0) return;
|
|
@@ -13,175 +10,456 @@ function announce(message, options = {}) {
|
|
|
13
10
|
);
|
|
14
11
|
}
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
function setAttributeIfChanged(element, name, value, beforeWrite) {
|
|
14
|
+
if (element.getAttribute(name) === value) return false;
|
|
15
|
+
if (value === null) element.removeAttribute(name);
|
|
16
|
+
else element.setAttribute(name, value);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function sharedRegistry(key, create) {
|
|
21
|
+
const symbol = Symbol.for(key);
|
|
22
|
+
const scope = globalThis;
|
|
23
|
+
const existing = scope[symbol];
|
|
24
|
+
if (existing !== void 0) return existing;
|
|
25
|
+
const registry2 = create();
|
|
26
|
+
Object.defineProperty(globalThis, symbol, { value: registry2 });
|
|
27
|
+
return registry2;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var registry = sharedRegistry(
|
|
31
|
+
"stimeo-ui.attribute-lease.registry.v1",
|
|
32
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
|
|
33
|
+
);
|
|
34
|
+
function isAttributeValue(value) {
|
|
35
|
+
return value === null || typeof value === "string";
|
|
36
|
+
}
|
|
37
|
+
function readLeaseRecord(element, record) {
|
|
38
|
+
try {
|
|
39
|
+
const parsed = JSON.parse(element.getAttribute(record) ?? "null");
|
|
40
|
+
if (!Array.isArray(parsed)) return void 0;
|
|
41
|
+
const [original, written, ...rest] = parsed;
|
|
42
|
+
const linked = rest[0] !== false;
|
|
43
|
+
const beneath = linked ? rest : rest.slice(1);
|
|
44
|
+
if (!beneath.every((under) => typeof under === "string")) return void 0;
|
|
45
|
+
return isAttributeValue(original) && isAttributeValue(written) ? { original, written, linked, beneath } : void 0;
|
|
46
|
+
} catch {
|
|
47
|
+
return void 0;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function attributeStack(element, attribute) {
|
|
51
|
+
const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
52
|
+
registry.stacks.set(element, byAttribute);
|
|
53
|
+
const known = byAttribute.get(attribute);
|
|
54
|
+
if (known) return known;
|
|
55
|
+
const found = [];
|
|
56
|
+
for (const record of registry.names.get(attribute) ?? []) {
|
|
57
|
+
const read = readLeaseRecord(element, record);
|
|
58
|
+
if (read) found.push({ ...read, record });
|
|
59
|
+
}
|
|
60
|
+
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
61
|
+
const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
|
|
62
|
+
lease: null,
|
|
63
|
+
record,
|
|
64
|
+
written,
|
|
65
|
+
original,
|
|
66
|
+
linked: linked && index > 0
|
|
67
|
+
}));
|
|
68
|
+
byAttribute.set(attribute, stack);
|
|
69
|
+
return stack;
|
|
70
|
+
}
|
|
71
|
+
function findHold(stack, lease, record) {
|
|
72
|
+
return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
|
|
73
|
+
}
|
|
74
|
+
var AttributeLease = class {
|
|
75
|
+
#attribute;
|
|
76
|
+
#record;
|
|
77
|
+
#base;
|
|
78
|
+
#preserveAuthor;
|
|
79
|
+
#held = /* @__PURE__ */ new Set();
|
|
80
|
+
constructor(attribute, owner, options = {}) {
|
|
81
|
+
this.#attribute = attribute;
|
|
82
|
+
this.#record = `data-${owner}-${attribute}-lease`;
|
|
83
|
+
this.#base = options.base === true;
|
|
84
|
+
this.#preserveAuthor = options.preserveAuthor === true;
|
|
85
|
+
const names = registry.names;
|
|
86
|
+
names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
|
|
87
|
+
}
|
|
88
|
+
write(element, value) {
|
|
89
|
+
const stack = attributeStack(element, this.#attribute);
|
|
90
|
+
const hold = this.#take(stack) ?? this.#acquire(element, stack);
|
|
91
|
+
this.#held.add(element);
|
|
92
|
+
const shows = !this.#covered(element, stack, hold);
|
|
93
|
+
hold.written = value;
|
|
94
|
+
this.#mark(element, stack);
|
|
95
|
+
if (shows) this.#reflect(element, value);
|
|
96
|
+
}
|
|
97
|
+
return(element) {
|
|
98
|
+
const held = this.#held.delete(element);
|
|
99
|
+
const known = registry.stacks.get(element)?.has(this.#attribute);
|
|
100
|
+
const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
|
|
101
|
+
const hold = this.#take(stack);
|
|
102
|
+
if (!hold) return false;
|
|
103
|
+
const carries = element.getAttribute(this.#attribute) === hold.written;
|
|
104
|
+
const owns = carries && !this.#covered(element, stack, hold);
|
|
105
|
+
const index = stack.indexOf(hold);
|
|
106
|
+
stack.splice(index, 1);
|
|
107
|
+
const above = stack[index];
|
|
108
|
+
if (above) above.linked &&= hold.linked;
|
|
109
|
+
this.#mark(element, stack);
|
|
110
|
+
if (!owns) return true;
|
|
111
|
+
const below = hold.linked ? stack[index - 1] : void 0;
|
|
112
|
+
this.#reflect(element, below ? below.written : hold.original);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
returnAll() {
|
|
116
|
+
for (const element of Array.from(this.#held)) this.return(element);
|
|
117
|
+
}
|
|
118
|
+
#take(stack) {
|
|
119
|
+
const hold = findHold(stack, this, this.#record);
|
|
120
|
+
if (hold) hold.lease = this;
|
|
121
|
+
return hold;
|
|
122
|
+
}
|
|
123
|
+
#acquire(element, stack) {
|
|
124
|
+
const current = element.getAttribute(this.#attribute);
|
|
125
|
+
const top = stack.at(-1);
|
|
126
|
+
const bottom = stack[0];
|
|
127
|
+
const over = top?.written === current ? top : void 0;
|
|
128
|
+
const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
|
|
129
|
+
const hold = {
|
|
130
|
+
lease: this,
|
|
131
|
+
record: this.#record,
|
|
132
|
+
written: current,
|
|
133
|
+
original: from ? from.original : current,
|
|
134
|
+
linked: !this.#base && over !== void 0
|
|
135
|
+
};
|
|
136
|
+
if (this.#base && bottom) {
|
|
137
|
+
bottom.linked = true;
|
|
138
|
+
stack.unshift(hold);
|
|
139
|
+
} else stack.push(hold);
|
|
140
|
+
return hold;
|
|
141
|
+
}
|
|
142
|
+
#covered(element, stack, hold) {
|
|
143
|
+
const current = element.getAttribute(this.#attribute);
|
|
144
|
+
return stack.slice(stack.indexOf(hold) + 1).some((above) => above.written === current);
|
|
145
|
+
}
|
|
146
|
+
#mark(element, stack) {
|
|
147
|
+
const records = /* @__PURE__ */ new Map([[this.#record, null]]);
|
|
148
|
+
stack.forEach((hold, index) => {
|
|
149
|
+
const names = stack.slice(0, index).map((under) => under.record);
|
|
150
|
+
const beneath = [...new Set(names.reverse())].filter((name) => name !== hold.record);
|
|
151
|
+
const marker = hold.linked || beneath.length === 0 ? [] : [false];
|
|
152
|
+
records.set(
|
|
153
|
+
hold.record,
|
|
154
|
+
hold.written === hold.original && beneath.length === 0 && index === stack.length - 1 ? null : JSON.stringify([hold.original, hold.written, ...marker, ...beneath])
|
|
155
|
+
);
|
|
156
|
+
});
|
|
157
|
+
for (const [name, recorded] of records) {
|
|
158
|
+
setAttributeIfChanged(element, name, recorded);
|
|
35
159
|
}
|
|
36
160
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
_BeforeCacheReset.#subscribers.delete(this);
|
|
40
|
-
if (_BeforeCacheReset.#subscribers.size > 0) return;
|
|
41
|
-
document.removeEventListener("turbo:before-cache", _BeforeCacheReset.#onBeforeCache);
|
|
161
|
+
#reflect(element, value) {
|
|
162
|
+
setAttributeIfChanged(element, this.#attribute, value);
|
|
42
163
|
}
|
|
43
164
|
};
|
|
44
165
|
|
|
45
|
-
// src/utils/composition_tracker.ts
|
|
46
166
|
var COMPOSITION_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
47
167
|
"insertCompositionText",
|
|
48
168
|
"insertFromComposition",
|
|
49
169
|
"deleteCompositionText",
|
|
50
170
|
"deleteByComposition"
|
|
51
171
|
]);
|
|
172
|
+
function isCompositionInputType(inputType) {
|
|
173
|
+
return inputType !== void 0 && COMPOSITION_INPUT_TYPES.has(inputType);
|
|
174
|
+
}
|
|
175
|
+
var BEFORE_MORPH_ATTRIBUTE = "turbo:before-morph-attribute";
|
|
176
|
+
var textOf = (element) => element.value;
|
|
177
|
+
var holdsFocus = (element) => element instanceof Node && element.getRootNode().activeElement === element;
|
|
52
178
|
var CompositionTracker = class {
|
|
53
179
|
#observedTargets = /* @__PURE__ */ new Set();
|
|
54
|
-
#
|
|
180
|
+
#composition = null;
|
|
55
181
|
#onStart;
|
|
56
182
|
#onEnd;
|
|
57
|
-
|
|
183
|
+
#onAbandon;
|
|
58
184
|
#confirmedTarget = null;
|
|
185
|
+
#keyComposing = false;
|
|
186
|
+
#connected = false;
|
|
187
|
+
#abandoned = null;
|
|
59
188
|
constructor(options = {}) {
|
|
60
189
|
this.#onStart = options.onStart;
|
|
61
190
|
this.#onEnd = options.onEnd;
|
|
191
|
+
this.#onAbandon = options.onAbandon;
|
|
62
192
|
}
|
|
63
|
-
/** Starts lifecycle tracking for `target`; repeated calls are idempotent. */
|
|
64
193
|
observe(target) {
|
|
194
|
+
this.#connected = true;
|
|
65
195
|
if (this.#observedTargets.has(target)) return;
|
|
66
196
|
target.addEventListener("compositionstart", this.#handleStart);
|
|
67
197
|
target.addEventListener("compositionend", this.#handleEnd);
|
|
68
|
-
target.addEventListener("keydown", this.#handleKeydown);
|
|
198
|
+
target.addEventListener("keydown", this.#handleKeydown, true);
|
|
199
|
+
target.addEventListener("beforeinput", this.#handleBeforeInput, true);
|
|
200
|
+
target.addEventListener("input", this.#handleInput, true);
|
|
201
|
+
target.addEventListener("blur", this.#handleBlur, true);
|
|
202
|
+
target.addEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
|
|
69
203
|
this.#observedTargets.add(target);
|
|
70
204
|
}
|
|
71
|
-
/** Stops tracking one target and clears any active composition it owned. */
|
|
72
205
|
unobserve(target) {
|
|
73
206
|
if (!this.#observedTargets.delete(target)) return;
|
|
74
|
-
|
|
75
|
-
target
|
|
76
|
-
target.removeEventListener("keydown", this.#handleKeydown);
|
|
77
|
-
this.#activeTargets.delete(target);
|
|
207
|
+
this.#release(target);
|
|
208
|
+
if (this.#composition?.target === target) this.#letGo();
|
|
78
209
|
if (this.#confirmedTarget === target) this.#confirmedTarget = null;
|
|
79
210
|
}
|
|
80
|
-
/** Releases every listener and clears state so reconnect starts cleanly. */
|
|
81
211
|
disconnect() {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
target.removeEventListener("compositionend", this.#handleEnd);
|
|
85
|
-
target.removeEventListener("keydown", this.#handleKeydown);
|
|
86
|
-
}
|
|
212
|
+
this.#connected = false;
|
|
213
|
+
for (const target of this.#observedTargets) this.#release(target);
|
|
87
214
|
this.#observedTargets.clear();
|
|
88
|
-
this.#
|
|
215
|
+
this.#letGo();
|
|
89
216
|
this.#confirmedTarget = null;
|
|
217
|
+
this.#keyComposing = false;
|
|
218
|
+
this.#abandoned = null;
|
|
90
219
|
}
|
|
91
|
-
/** True when lifecycle tracking or the current event reports composition. */
|
|
92
220
|
isComposing(event) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
221
|
+
this.#settle();
|
|
222
|
+
return event?.isComposing === true || this.#composition !== null;
|
|
223
|
+
}
|
|
224
|
+
composingElement() {
|
|
225
|
+
this.#settle();
|
|
226
|
+
return this.#composition?.element ?? null;
|
|
227
|
+
}
|
|
228
|
+
owns(event) {
|
|
229
|
+
const element = this.composingElement();
|
|
230
|
+
return event.isComposing === true || element !== null && element === event.target;
|
|
231
|
+
}
|
|
101
232
|
consumesConfirmedInput(event) {
|
|
102
233
|
const confirmed = this.#confirmedTarget;
|
|
103
234
|
this.#confirmedTarget = null;
|
|
104
235
|
if (confirmed === null || confirmed !== event.target) return false;
|
|
105
236
|
const inputType = event.inputType;
|
|
106
|
-
return !inputType ||
|
|
237
|
+
return !inputType || isCompositionInputType(inputType);
|
|
238
|
+
}
|
|
239
|
+
#release(target) {
|
|
240
|
+
target.removeEventListener("compositionstart", this.#handleStart);
|
|
241
|
+
target.removeEventListener("compositionend", this.#handleEnd);
|
|
242
|
+
target.removeEventListener("keydown", this.#handleKeydown, true);
|
|
243
|
+
target.removeEventListener("beforeinput", this.#handleBeforeInput, true);
|
|
244
|
+
target.removeEventListener("input", this.#handleInput, true);
|
|
245
|
+
target.removeEventListener("blur", this.#handleBlur, true);
|
|
246
|
+
target.removeEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
|
|
107
247
|
}
|
|
248
|
+
#letGo() {
|
|
249
|
+
const composition = this.#composition;
|
|
250
|
+
if (composition === null) return;
|
|
251
|
+
if (!holdsFocus(composition.element)) {
|
|
252
|
+
this.#composition = null;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
queueMicrotask(() => {
|
|
256
|
+
if (this.#composition !== composition || this.#observedTargets.has(composition.target)) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
this.#composition = null;
|
|
260
|
+
if (!this.#connected) return;
|
|
261
|
+
this.#abandoned = { element: composition.element, inPlace: true };
|
|
262
|
+
this.#runAbandon();
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
#settle() {
|
|
266
|
+
const composition = this.#composition;
|
|
267
|
+
if (composition === null) return;
|
|
268
|
+
const { target, element, text } = composition;
|
|
269
|
+
if (target instanceof Node && element instanceof Node && !target.contains(element)) {
|
|
270
|
+
this.#composition = null;
|
|
271
|
+
} else if (textOf(element) !== text) {
|
|
272
|
+
this.#abandon(false);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
#abandon(inPlace) {
|
|
276
|
+
this.#owe(inPlace);
|
|
277
|
+
this.#composition = null;
|
|
278
|
+
queueMicrotask(this.#runAbandon);
|
|
279
|
+
}
|
|
280
|
+
#owe(inPlace) {
|
|
281
|
+
const composition = this.#composition;
|
|
282
|
+
if (composition !== null) this.#abandoned = { element: composition.element, inPlace };
|
|
283
|
+
}
|
|
284
|
+
#runAbandon = () => {
|
|
285
|
+
const abandoned = this.#abandoned;
|
|
286
|
+
if (abandoned === null) return;
|
|
287
|
+
this.#abandoned = null;
|
|
288
|
+
this.#onAbandon?.(abandoned.element, abandoned.inPlace);
|
|
289
|
+
};
|
|
108
290
|
#handleStart = (event) => {
|
|
109
291
|
this.#confirmedTarget = null;
|
|
110
|
-
|
|
292
|
+
this.#settle();
|
|
293
|
+
this.#owe(true);
|
|
294
|
+
const target = event.currentTarget;
|
|
295
|
+
const element = event.target;
|
|
296
|
+
this.#composition = { target, element, text: textOf(element) };
|
|
297
|
+
this.#runAbandon();
|
|
111
298
|
this.#onStart?.(event);
|
|
112
299
|
};
|
|
113
300
|
#handleEnd = (event) => {
|
|
114
|
-
|
|
301
|
+
this.#runAbandon();
|
|
302
|
+
if (this.#composition?.target === event.currentTarget) this.#composition = null;
|
|
115
303
|
this.#confirmedTarget = event.target;
|
|
116
304
|
this.#onEnd?.(event);
|
|
117
305
|
};
|
|
118
|
-
|
|
119
|
-
|
|
306
|
+
#handleKeydown = (event) => {
|
|
307
|
+
this.#settle();
|
|
308
|
+
this.#runAbandon();
|
|
120
309
|
this.#confirmedTarget = null;
|
|
310
|
+
this.#keyComposing = event.isComposing === true;
|
|
311
|
+
};
|
|
312
|
+
#handleBeforeInput = (event) => {
|
|
313
|
+
const keyComposing = this.#keyComposing;
|
|
314
|
+
this.#keyComposing = false;
|
|
315
|
+
this.#settle();
|
|
316
|
+
const { isComposing, inputType } = event;
|
|
317
|
+
if (this.#composition !== null && !keyComposing && !isComposing && inputType && !isCompositionInputType(inputType)) {
|
|
318
|
+
this.#abandon(true);
|
|
319
|
+
}
|
|
320
|
+
this.#runAbandon();
|
|
321
|
+
};
|
|
322
|
+
#handleInput = (event) => {
|
|
323
|
+
const composition = this.#composition;
|
|
324
|
+
const { isTrusted, isComposing, inputType } = event;
|
|
325
|
+
if (composition !== null && event.target === composition.element && (isTrusted || isComposing || isCompositionInputType(inputType))) {
|
|
326
|
+
composition.text = textOf(composition.element);
|
|
327
|
+
} else {
|
|
328
|
+
this.#settle();
|
|
329
|
+
}
|
|
330
|
+
this.#runAbandon();
|
|
331
|
+
};
|
|
332
|
+
#handleBlur = (event) => {
|
|
333
|
+
this.#settle();
|
|
334
|
+
this.#runAbandon();
|
|
335
|
+
const composition = this.#composition;
|
|
336
|
+
if (composition === null || composition.target === composition.element) return;
|
|
337
|
+
const { element } = composition;
|
|
338
|
+
if (!(element instanceof Node) || event.target !== element) return;
|
|
339
|
+
const root = element.getRootNode();
|
|
340
|
+
if (root.activeElement !== element) this.#composition = null;
|
|
341
|
+
};
|
|
342
|
+
#handleBeforeMorphAttribute = (event) => {
|
|
343
|
+
this.#settle();
|
|
344
|
+
const composition = this.#composition;
|
|
345
|
+
if (composition?.target !== event.currentTarget || event.target !== composition.element) return;
|
|
346
|
+
const detail = event.detail;
|
|
347
|
+
if (detail?.attributeName === "value") event.preventDefault();
|
|
121
348
|
};
|
|
122
349
|
};
|
|
123
350
|
|
|
124
|
-
|
|
351
|
+
var DetachGate = class _DetachGate {
|
|
352
|
+
#pending = false;
|
|
353
|
+
get pending() {
|
|
354
|
+
return this.#pending;
|
|
355
|
+
}
|
|
356
|
+
static isDetached(host) {
|
|
357
|
+
return !host.element.isConnected || !_DetachGate.#listed(host);
|
|
358
|
+
}
|
|
359
|
+
disconnected(host, teardown) {
|
|
360
|
+
const carried = _DetachGate.#carried(host);
|
|
361
|
+
if (!carried && _DetachGate.isDetached(host)) {
|
|
362
|
+
this.#pending = false;
|
|
363
|
+
teardown();
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
this.#pending = true;
|
|
367
|
+
const probe = () => {
|
|
368
|
+
if (!this.#pending) return;
|
|
369
|
+
this.#pending = false;
|
|
370
|
+
teardown();
|
|
371
|
+
};
|
|
372
|
+
if (carried) setTimeout(probe, 0);
|
|
373
|
+
else queueMicrotask(probe);
|
|
374
|
+
}
|
|
375
|
+
static #carried(host) {
|
|
376
|
+
const element = host.element;
|
|
377
|
+
return !element.isConnected && element.closest("[data-turbo-permanent]") !== null && _DetachGate.#listed(host);
|
|
378
|
+
}
|
|
379
|
+
static #listed(host) {
|
|
380
|
+
const tokens = (host.element.getAttribute("data-controller") ?? "").split(/\s+/);
|
|
381
|
+
return tokens.includes(host.identifier);
|
|
382
|
+
}
|
|
383
|
+
cancel() {
|
|
384
|
+
this.#pending = false;
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
|
|
125
388
|
var ListenerSet = class {
|
|
126
|
-
/** The generation every `add` joins until the next `dispose()`. */
|
|
127
389
|
#abort = new AbortController();
|
|
128
|
-
/**
|
|
129
|
-
* Attaches `handler` to the open generation, exactly as the caller spelled it.
|
|
130
|
-
*
|
|
131
|
-
* The set supplies the signal, so `options` carries everything else the DOM
|
|
132
|
-
* accepts — `capture` included, which has to match at release time and no
|
|
133
|
-
* longer has a second place to drift from.
|
|
134
|
-
*/
|
|
135
390
|
add(target, type, handler, options) {
|
|
136
391
|
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
137
392
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Releases every listener of the open generation, synchronously, and opens the
|
|
140
|
-
* next one. Idempotent, and safe before anything has been added.
|
|
141
|
-
*/
|
|
142
393
|
dispose() {
|
|
143
394
|
this.#abort.abort();
|
|
144
395
|
this.#abort = new AbortController();
|
|
145
396
|
}
|
|
146
397
|
};
|
|
147
398
|
|
|
148
|
-
|
|
399
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
400
|
+
|
|
401
|
+
var NUMBER_BOUNDS = {
|
|
402
|
+
timer: { finite: true, min: 0, max: MAX_TIMER_DELAY_MS }};
|
|
403
|
+
function matchesNumberBounds(value, bounds) {
|
|
404
|
+
if (!Number.isFinite(value)) {
|
|
405
|
+
const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
|
|
406
|
+
if (direction === null) return false;
|
|
407
|
+
if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
|
|
408
|
+
}
|
|
409
|
+
if (bounds.min !== void 0 && value < bounds.min) return false;
|
|
410
|
+
if (bounds.max !== void 0 && value > bounds.max) return false;
|
|
411
|
+
if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
|
|
412
|
+
if (bounds.integer && !Number.isInteger(value)) return false;
|
|
413
|
+
if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function readNumber(raw, fallback, bounds) {
|
|
418
|
+
return matchesNumberBounds(raw, bounds) ? raw : fallback;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
var NumberValueReader = class {
|
|
422
|
+
#lastRejected = /* @__PURE__ */ new Map();
|
|
423
|
+
read(owner, name, raw, fallback, bounds) {
|
|
424
|
+
const resolved = readNumber(raw, fallback, bounds);
|
|
425
|
+
if (matchesNumberBounds(raw, bounds)) {
|
|
426
|
+
this.#lastRejected.delete(name);
|
|
427
|
+
return resolved;
|
|
428
|
+
}
|
|
429
|
+
const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
|
|
430
|
+
const literal = owner.element.getAttribute(attribute);
|
|
431
|
+
if (literal === null) {
|
|
432
|
+
this.#lastRejected.delete(name);
|
|
433
|
+
return resolved;
|
|
434
|
+
}
|
|
435
|
+
if (this.#lastRejected.get(name) !== literal) {
|
|
436
|
+
this.#lastRejected.set(name, literal);
|
|
437
|
+
console.warn(
|
|
438
|
+
`Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
return resolved;
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
149
445
|
var TimerRegistry = class {
|
|
150
|
-
/** Live timer ids that have not yet been cleared (or, for timeouts, fired). */
|
|
151
446
|
ids = /* @__PURE__ */ new Set();
|
|
152
|
-
/**
|
|
153
|
-
* Cancels a single tracked timer.
|
|
154
|
-
*
|
|
155
|
-
* No-ops if the id is unknown (already cleared, fired, or never owned by this
|
|
156
|
-
* registry), so callers can clear defensively without guarding.
|
|
157
|
-
*/
|
|
158
447
|
clear(id) {
|
|
159
448
|
if (this.ids.delete(id)) {
|
|
160
449
|
this.cancel(id);
|
|
161
450
|
}
|
|
162
451
|
}
|
|
163
|
-
/**
|
|
164
|
-
* Cancels every tracked timer. Call this from a controller's `disconnect()`
|
|
165
|
-
* to guarantee no timer outlives the element.
|
|
166
|
-
*/
|
|
167
452
|
clearAll() {
|
|
168
453
|
for (const id of this.ids) {
|
|
169
454
|
this.cancel(id);
|
|
170
455
|
}
|
|
171
456
|
this.ids.clear();
|
|
172
457
|
}
|
|
173
|
-
/** Number of timers currently tracked (pending). */
|
|
174
458
|
get size() {
|
|
175
459
|
return this.ids.size;
|
|
176
460
|
}
|
|
177
461
|
};
|
|
178
462
|
var SafeTimeout = class extends TimerRegistry {
|
|
179
|
-
/**
|
|
180
|
-
* Schedules `callback` after `delay` ms and returns the timer id.
|
|
181
|
-
*
|
|
182
|
-
* The id is removed from the registry automatically when the timeout fires,
|
|
183
|
-
* so {@link TimerRegistry.size | size} reflects only still-pending timers.
|
|
184
|
-
*/
|
|
185
463
|
set(callback, delay) {
|
|
186
464
|
const id = this.schedule(() => {
|
|
187
465
|
this.ids.delete(id);
|
|
@@ -198,8 +476,19 @@ var SafeTimeout = class extends TimerRegistry {
|
|
|
198
476
|
}
|
|
199
477
|
};
|
|
200
478
|
|
|
201
|
-
|
|
202
|
-
|
|
479
|
+
var TransientHooks = class {
|
|
480
|
+
#attributes;
|
|
481
|
+
constructor(options) {
|
|
482
|
+
this.#attributes = options.attributes;
|
|
483
|
+
}
|
|
484
|
+
reset(element) {
|
|
485
|
+
for (const attribute of this.#attributes) element.removeAttribute(attribute);
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
var PENDING = new TransientHooks({ attributes: ["data-auto-submit-pending"] });
|
|
490
|
+
var AutoSubmitController = class _AutoSubmitController extends Controller {
|
|
491
|
+
#numbers = new NumberValueReader();
|
|
203
492
|
static targets = ["form"];
|
|
204
493
|
static values = {
|
|
205
494
|
debounce: { type: Number, default: 300 },
|
|
@@ -207,70 +496,60 @@ var AutoSubmitController = class extends Controller {
|
|
|
207
496
|
announce: { type: Boolean, default: false },
|
|
208
497
|
message: { type: String, default: "" }
|
|
209
498
|
};
|
|
499
|
+
static valueConstraints = {
|
|
500
|
+
debounce: NUMBER_BOUNDS.timer
|
|
501
|
+
};
|
|
210
502
|
static actions = ["submit"];
|
|
211
503
|
static events = ["submit", "done", "reconcile"];
|
|
212
|
-
/** Debounce timer registry; one `clearAll()` in disconnect tears it down. */
|
|
213
504
|
#timers = new SafeTimeout();
|
|
214
|
-
/** Id of the pending debounce timer, so a new keystroke can reset it. */
|
|
215
505
|
#pendingId = 0;
|
|
216
|
-
/** Listeners that live with the bound form rather than with the connection. */
|
|
217
506
|
#formListeners = new ListenerSet();
|
|
218
|
-
/** The form the listeners are attached to; target callbacks rebind it. */
|
|
219
507
|
#boundForm = null;
|
|
220
|
-
|
|
221
|
-
#
|
|
222
|
-
/**
|
|
223
|
-
* Clears `aria-busy` and emits completion once Turbo finishes the submit.
|
|
224
|
-
*
|
|
225
|
-
* @stimeoRuntimeOnly `message` and `announce` shape the event and the announcement of one
|
|
226
|
-
* finished submit; the busy flag it clears does not depend on them.
|
|
227
|
-
*/
|
|
508
|
+
#busy = new AttributeLease("aria-busy", this.identifier);
|
|
509
|
+
#gate = new DetachGate();
|
|
228
510
|
#onSubmitEnd = () => {
|
|
229
|
-
this.#boundForm
|
|
511
|
+
if (this.#boundForm) this.#busy.return(this.#boundForm);
|
|
230
512
|
const message = this.messageValue;
|
|
231
513
|
this.dispatch("done", { detail: { message: message || void 0 } });
|
|
232
514
|
if (this.announceValue) announce(message);
|
|
233
515
|
};
|
|
234
|
-
/** Owns delegated IME lifecycle state and submits confirmed input text. */
|
|
235
516
|
#composition = new CompositionTracker({
|
|
236
517
|
onEnd: (event) => {
|
|
237
518
|
if (this.#triggers("input")) this.#schedule(event.target ?? null);
|
|
238
519
|
}
|
|
239
520
|
});
|
|
240
521
|
connect() {
|
|
241
|
-
this.#
|
|
242
|
-
this.#
|
|
522
|
+
const moved = this.#gate.pending;
|
|
523
|
+
this.#gate.cancel();
|
|
524
|
+
const form = this.#resolveForm();
|
|
525
|
+
if (moved && form && form === this.#boundForm) {
|
|
526
|
+
this.#composition.observe(form);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
const stale = form?.hasAttribute("data-auto-submit-pending") === true;
|
|
530
|
+
if (form) PENDING.reset(form);
|
|
531
|
+
const busy = form !== null && this.#busy.return(form);
|
|
532
|
+
this.#bindForm(form);
|
|
533
|
+
if (stale || busy) this.dispatch("reconcile", { detail: {} });
|
|
243
534
|
}
|
|
244
535
|
disconnect() {
|
|
245
|
-
this.#beforeCache.deactivate();
|
|
246
|
-
this.#bindForm(null);
|
|
247
536
|
this.#composition.disconnect();
|
|
248
|
-
this.#
|
|
249
|
-
|
|
537
|
+
this.#gate.disconnected(this, () => {
|
|
538
|
+
this.#bindForm(null);
|
|
539
|
+
this.#pendingId = 0;
|
|
540
|
+
});
|
|
250
541
|
}
|
|
251
|
-
/** Follows a `form` target added (or swapped in) at runtime. */
|
|
252
542
|
formTargetConnected() {
|
|
253
543
|
this.#bindForm(this.#resolveForm());
|
|
254
544
|
}
|
|
255
|
-
/** Follows a `form` target removed (or swapped out) at runtime. */
|
|
256
545
|
formTargetDisconnected() {
|
|
257
546
|
this.#bindForm(this.#resolveForm());
|
|
258
547
|
}
|
|
259
|
-
/**
|
|
260
|
-
* Schedules a debounced submit. Wired to `input`/`change`; the `on` value is an
|
|
261
|
-
* allowlist so a configured subset (e.g. only `change`) is honored even when both
|
|
262
|
-
* are bound in markup. Coalesces rapid events into a single `requestSubmit`.
|
|
263
|
-
*/
|
|
264
548
|
submit(event) {
|
|
265
549
|
if (!this.#triggers(event.type)) return;
|
|
266
550
|
if (event.type === "input" && this.#composition.isComposing(event)) return;
|
|
267
551
|
this.#schedule(event.target ?? null);
|
|
268
552
|
}
|
|
269
|
-
/**
|
|
270
|
-
* Schedules (and coalesces) the debounced submit for the given trigger.
|
|
271
|
-
*
|
|
272
|
-
* @stimeoRuntimeOnly `debounce` is the delay of the one submit timer this call arms.
|
|
273
|
-
*/
|
|
274
553
|
#schedule(trigger) {
|
|
275
554
|
const form = this.#boundForm;
|
|
276
555
|
if (!form) return;
|
|
@@ -281,23 +560,15 @@ var AutoSubmitController = class extends Controller {
|
|
|
281
560
|
form.removeAttribute("data-auto-submit-pending");
|
|
282
561
|
this.dispatch("submit", { detail: { trigger } });
|
|
283
562
|
if (form.checkValidity()) {
|
|
284
|
-
|
|
563
|
+
this.#busy.write(form, "true");
|
|
285
564
|
}
|
|
286
565
|
form.requestSubmit();
|
|
287
|
-
}, this
|
|
566
|
+
}, this.#safeDebounce);
|
|
288
567
|
}
|
|
289
|
-
/** Cancels the pending debounced submit, if any (`clear` no-ops on unknown ids). */
|
|
290
568
|
#cancelPending() {
|
|
291
569
|
this.#timers.clear(this.#pendingId);
|
|
292
570
|
this.#pendingId = 0;
|
|
293
571
|
}
|
|
294
|
-
/**
|
|
295
|
-
* Replaces the subscribed form symmetrically. The outgoing form loses the
|
|
296
|
-
* `turbo:submit-end`/composition listeners, its pending hook, and any pending
|
|
297
|
-
* debounced submit (which described the outgoing form). An in-flight `aria-busy`
|
|
298
|
-
* is left for `turbo:submit-end` or the pre-cache rewind — removing it here
|
|
299
|
-
* would wipe a legitimately in-progress submission.
|
|
300
|
-
*/
|
|
301
572
|
#bindForm(form) {
|
|
302
573
|
if (form === this.#boundForm) return;
|
|
303
574
|
const previous = this.#boundForm;
|
|
@@ -312,25 +583,23 @@ var AutoSubmitController = class extends Controller {
|
|
|
312
583
|
this.#formListeners.add(form, "turbo:submit-end", this.#onSubmitEnd);
|
|
313
584
|
this.#composition.observe(form);
|
|
314
585
|
}
|
|
315
|
-
/** Resolves the form: the explicit `form` target, else a `<form>` root, else null. */
|
|
316
586
|
#resolveForm() {
|
|
317
587
|
if (this.hasFormTarget) return this.formTarget;
|
|
318
588
|
return this.element instanceof HTMLFormElement ? this.element : null;
|
|
319
589
|
}
|
|
320
|
-
/** Returns the transient state hooks to their initial (absent) state. */
|
|
321
|
-
#rewindForCache() {
|
|
322
|
-
const inProgress = this.#pendingId !== 0 || this.#boundForm?.hasAttribute("aria-busy") === true;
|
|
323
|
-
this.#cancelPending();
|
|
324
|
-
this.#boundForm?.removeAttribute("data-auto-submit-pending");
|
|
325
|
-
this.#boundForm?.removeAttribute("aria-busy");
|
|
326
|
-
if (inProgress) this.dispatch("reconcile", { detail: {} });
|
|
327
|
-
}
|
|
328
|
-
/** Whether `type` is one of the whitespace-separated event types in `on`. */
|
|
329
590
|
#triggers(type) {
|
|
330
591
|
return this.onValue.split(/\s+/).filter(Boolean).includes(type);
|
|
331
592
|
}
|
|
593
|
+
get #safeDebounce() {
|
|
594
|
+
return this.#numbers.read(
|
|
595
|
+
this,
|
|
596
|
+
"debounce",
|
|
597
|
+
this.debounceValue,
|
|
598
|
+
_AutoSubmitController.values.debounce.default,
|
|
599
|
+
_AutoSubmitController.valueConstraints.debounce
|
|
600
|
+
);
|
|
601
|
+
}
|
|
332
602
|
};
|
|
333
603
|
|
|
334
604
|
export { AutoSubmitController };
|
|
335
|
-
//# sourceMappingURL=auto_submit_controller.js.map
|
|
336
605
|
//# sourceMappingURL=auto_submit_controller.js.map
|