stimeo-ui 0.17.0 → 0.18.1
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 -2
- package/README.md +19 -10
- package/dist/cable/index.d.ts +11 -9
- package/dist/cable/index.js +22 -14
- package/dist/cable/index.js.map +1 -1
- package/dist/coerce-JtZVNG5h.d.ts +20 -0
- package/dist/controllers/accordion_controller.js +14 -6
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.js +145 -118
- package/dist/controllers/alert_dialog_controller.js.map +1 -1
- package/dist/controllers/announcer_controller.d.ts +5 -3
- package/dist/controllers/announcer_controller.js +113 -17
- package/dist/controllers/announcer_controller.js.map +1 -1
- package/dist/controllers/auto_submit_controller.js +185 -60
- package/dist/controllers/auto_submit_controller.js.map +1 -1
- package/dist/controllers/avatar_controller.js +55 -43
- package/dist/controllers/avatar_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/bulk_select_controller.d.ts +3 -3
- package/dist/controllers/bulk_select_controller.js +64 -50
- package/dist/controllers/bulk_select_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +15 -12
- package/dist/controllers/calendar_controller.js +55 -53
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +9 -5
- package/dist/controllers/carousel_controller.js +124 -86
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/character_counter_controller.d.ts +27 -6
- package/dist/controllers/character_counter_controller.js +291 -95
- package/dist/controllers/character_counter_controller.js.map +1 -1
- package/dist/controllers/checkbox_controller.js +6 -0
- package/dist/controllers/checkbox_controller.js.map +1 -1
- package/dist/controllers/clipboard_controller.js +118 -27
- package/dist/controllers/clipboard_controller.js.map +1 -1
- package/dist/controllers/collapsible_controller.d.ts +1 -1
- package/dist/controllers/collapsible_controller.js +52 -49
- package/dist/controllers/collapsible_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.js +29 -7
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.d.ts +1 -1
- package/dist/controllers/combobox_controller.js +210 -71
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +9 -9
- package/dist/controllers/command_palette_controller.js +290 -140
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/conditional_fields_controller.js +145 -58
- package/dist/controllers/conditional_fields_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.js +145 -118
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +49 -14
- package/dist/controllers/context_menu_controller.js +138 -73
- package/dist/controllers/context_menu_controller.js.map +1 -1
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/countdown_controller.d.ts +2 -2
- package/dist/controllers/countdown_controller.js +109 -21
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +75 -11
- package/dist/controllers/currency_input_controller.js +446 -72
- package/dist/controllers/currency_input_controller.js.map +1 -1
- package/dist/controllers/data_grid_controller.d.ts +10 -8
- package/dist/controllers/data_grid_controller.js +134 -28
- package/dist/controllers/data_grid_controller.js.map +1 -1
- package/dist/controllers/date_range_picker_controller.d.ts +12 -9
- package/dist/controllers/date_range_picker_controller.js +93 -72
- package/dist/controllers/date_range_picker_controller.js.map +1 -1
- package/dist/controllers/dialog_controller.d.ts +4 -5
- package/dist/controllers/dialog_controller.js +145 -118
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.d.ts +1 -1
- package/dist/controllers/direct_upload_controller.js +24 -14
- 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 +68 -31
- package/dist/controllers/dirty_form_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.js +66 -46
- package/dist/controllers/dismissible_controller.js.map +1 -1
- package/dist/controllers/drawer_controller.js +145 -118
- package/dist/controllers/drawer_controller.js.map +1 -1
- package/dist/controllers/dropdown_controller.js +76 -63
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.js +200 -62
- package/dist/controllers/editable_controller.js.map +1 -1
- package/dist/controllers/empty_state_controller.js +13 -6
- package/dist/controllers/empty_state_controller.js.map +1 -1
- package/dist/controllers/file_dropzone_controller.d.ts +3 -0
- package/dist/controllers/file_dropzone_controller.js +55 -48
- package/dist/controllers/file_dropzone_controller.js.map +1 -1
- package/dist/controllers/filter_controller.js +9 -2
- package/dist/controllers/filter_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +4 -4
- package/dist/controllers/flash_controller.js +66 -33
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +3 -3
- package/dist/controllers/focus_controller.js +39 -14
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.d.ts +2 -1
- package/dist/controllers/form_field_controller.js +52 -43
- 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 +18 -11
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.d.ts +13 -12
- package/dist/controllers/frame_loading_controller.js +55 -48
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.d.ts +5 -4
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +4 -1
- package/dist/controllers/hover_card_controller.js +67 -61
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +6 -5
- package/dist/controllers/idle_controller.js +10 -6
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/input_mask_controller.d.ts +31 -13
- package/dist/controllers/input_mask_controller.js +434 -24
- package/dist/controllers/input_mask_controller.js.map +1 -1
- package/dist/controllers/intersection_controller.js +3 -0
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.d.ts +3 -2
- package/dist/controllers/lazy_frame_controller.js +15 -3
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +10 -7
- package/dist/controllers/listbox_controller.js +260 -79
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.d.ts +8 -6
- package/dist/controllers/local_time_controller.js +48 -13
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.js +11 -4
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/menu_controller.d.ts +24 -5
- package/dist/controllers/menu_controller.js +138 -82
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +49 -7
- package/dist/controllers/menubar_controller.js +65 -19
- package/dist/controllers/menubar_controller.js.map +1 -1
- package/dist/controllers/meter_controller.d.ts +13 -20
- package/dist/controllers/meter_controller.js +270 -24
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +19 -16
- package/dist/controllers/multi_select_controller.js +272 -95
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/navigation_menu_controller.d.ts +19 -5
- package/dist/controllers/navigation_menu_controller.js +67 -19
- package/dist/controllers/navigation_menu_controller.js.map +1 -1
- package/dist/controllers/nested_form_controller.js +98 -64
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/network_status_controller.js +70 -52
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +24 -6
- package/dist/controllers/number_input_controller.js +344 -94
- 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 +29 -11
- package/dist/controllers/optimistic_controller.js.map +1 -1
- package/dist/controllers/otp_controller.d.ts +35 -4
- package/dist/controllers/otp_controller.js +502 -104
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.js +6 -0
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +10 -9
- package/dist/controllers/overflow_menu_controller.js +136 -21
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +3 -2
- package/dist/controllers/pagination_controller.js +47 -14
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +5 -4
- package/dist/controllers/password_reveal_controller.js +52 -49
- package/dist/controllers/password_reveal_controller.js.map +1 -1
- package/dist/controllers/password_strength_controller.d.ts +1 -1
- package/dist/controllers/password_strength_controller.js +13 -6
- package/dist/controllers/password_strength_controller.js.map +1 -1
- package/dist/controllers/persist_controller.js +48 -128
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +20 -8
- package/dist/controllers/pointer_drag_controller.js +255 -24
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +9 -5
- package/dist/controllers/popover_controller.js +91 -65
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.js +6 -0
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/preview_guard_controller.js +14 -3
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/progress_controller.d.ts +9 -19
- package/dist/controllers/progress_controller.js +271 -27
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.d.ts +11 -8
- package/dist/controllers/radio_group_controller.js +167 -80
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +4 -3
- package/dist/controllers/range_slider_controller.js +27 -7
- package/dist/controllers/range_slider_controller.js.map +1 -1
- package/dist/controllers/rating_controller.js +93 -57
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.js +10 -6
- package/dist/controllers/read_more_controller.js.map +1 -1
- package/dist/controllers/reading_progress_controller.js +22 -5
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/relative_time_controller.d.ts +4 -4
- package/dist/controllers/relative_time_controller.js +75 -11
- package/dist/controllers/relative_time_controller.js.map +1 -1
- package/dist/controllers/reset_on_restore_controller.d.ts +3 -3
- package/dist/controllers/reset_on_restore_controller.js +6 -0
- package/dist/controllers/reset_on_restore_controller.js.map +1 -1
- package/dist/controllers/resizable_controller.d.ts +3 -0
- package/dist/controllers/resizable_controller.js +55 -22
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.d.ts +3 -3
- package/dist/controllers/roving_controller.js +10 -4
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.js +129 -88
- 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 -2
- package/dist/controllers/scroll_restore_controller.js.map +1 -1
- package/dist/controllers/scroll_visibility_controller.js +93 -60
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.js +11 -5
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +1 -1
- package/dist/controllers/separator_controller.js +59 -43
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/sidebar_controller.d.ts +1 -1
- package/dist/controllers/sidebar_controller.js +150 -122
- package/dist/controllers/sidebar_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.js +55 -48
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +2 -1
- package/dist/controllers/slider_controller.js +27 -6
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.d.ts +1 -1
- package/dist/controllers/smart_sticky_header_controller.js +13 -5
- 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 +27 -14
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.js +55 -48
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +4 -4
- package/dist/controllers/step_indicator_controller.js +6 -0
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +2 -3
- package/dist/controllers/stepper_controller.js +6 -0
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +3 -1
- package/dist/controllers/stick_to_bottom_controller.js +19 -8
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.js +49 -43
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +2 -1
- package/dist/controllers/submit_once_controller.js +145 -85
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +7 -4
- package/dist/controllers/switch_controller.js +172 -28
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +7 -4
- package/dist/controllers/tabs_controller.js +6 -1
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +4 -3
- package/dist/controllers/tags_input_controller.js +157 -28
- package/dist/controllers/tags_input_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.d.ts +1 -1
- package/dist/controllers/textarea_autosize_controller.js +40 -19
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/theme_controller.d.ts +3 -2
- package/dist/controllers/theme_controller.js +10 -4
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +38 -5
- package/dist/controllers/time_picker_controller.js +192 -54
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/toast_controller.d.ts +4 -5
- package/dist/controllers/toast_controller.js +58 -27
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.d.ts +2 -3
- package/dist/controllers/toggle_group_controller.js +158 -56
- 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 +150 -21
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +4 -1
- package/dist/controllers/tooltip_controller.js.map +1 -1
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +1 -1
- package/dist/controllers/tree_view_controller.js +134 -25
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2515 -1315
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +25 -12
- package/dist/inspector/cli.js +21 -3
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.d.ts +1 -1
- package/dist/inspector/cli_bin.js +62 -8
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +13 -13
- package/dist/inspector/manifest.json +19 -5
- package/dist/positioning/index.d.ts +9 -8
- package/dist/positioning/index.js +6 -0
- package/dist/positioning/index.js.map +1 -1
- package/package.json +11 -10
|
@@ -5,9 +5,9 @@ function sharedRegistry(key, create) {
|
|
|
5
5
|
const scope = globalThis;
|
|
6
6
|
const existing = scope[symbol];
|
|
7
7
|
if (existing !== void 0) return existing;
|
|
8
|
-
const
|
|
9
|
-
Object.defineProperty(globalThis, symbol, { value:
|
|
10
|
-
return
|
|
8
|
+
const registry2 = create();
|
|
9
|
+
Object.defineProperty(globalThis, symbol, { value: registry2 });
|
|
10
|
+
return registry2;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
var ids = sharedRegistry("stimeo-ui.aria-ids.registry.v1", () => ({ counter: 0 }));
|
|
@@ -39,7 +39,21 @@ function isReservedArrowChord(event, allow = []) {
|
|
|
39
39
|
if (!event.key.startsWith("Arrow")) return false;
|
|
40
40
|
return event.altKey && !allow.includes("alt") || event.ctrlKey && !allow.includes("ctrl") || event.metaKey && !allow.includes("meta") || event.shiftKey && !allow.includes("shift");
|
|
41
41
|
}
|
|
42
|
+
function hasModifierChord(event) {
|
|
43
|
+
return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function setAttributeIfChanged(element, name, value, beforeWrite) {
|
|
47
|
+
if (element.getAttribute(name) === value) return false;
|
|
48
|
+
if (value === null) element.removeAttribute(name);
|
|
49
|
+
else element.setAttribute(name, value);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
42
52
|
|
|
53
|
+
var registry = sharedRegistry(
|
|
54
|
+
"stimeo-ui.attribute-lease.registry.v1",
|
|
55
|
+
() => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
|
|
56
|
+
);
|
|
43
57
|
function isAttributeValue(value) {
|
|
44
58
|
return value === null || typeof value === "string";
|
|
45
59
|
}
|
|
@@ -56,24 +70,46 @@ function readLeaseRecord(element, record) {
|
|
|
56
70
|
return void 0;
|
|
57
71
|
}
|
|
58
72
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
);
|
|
73
|
+
function attributeStack(element, attribute) {
|
|
74
|
+
const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
75
|
+
registry.stacks.set(element, byAttribute);
|
|
76
|
+
const known = byAttribute.get(attribute);
|
|
77
|
+
if (known) return known;
|
|
78
|
+
const found = [];
|
|
79
|
+
for (const record of registry.names.get(attribute) ?? []) {
|
|
80
|
+
const read = readLeaseRecord(element, record);
|
|
81
|
+
if (read) found.push({ ...read, record });
|
|
82
|
+
}
|
|
83
|
+
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
84
|
+
const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
|
|
85
|
+
lease: null,
|
|
86
|
+
record,
|
|
87
|
+
written,
|
|
88
|
+
original,
|
|
89
|
+
linked: linked && index > 0
|
|
90
|
+
}));
|
|
91
|
+
byAttribute.set(attribute, stack);
|
|
92
|
+
return stack;
|
|
93
|
+
}
|
|
94
|
+
function findHold(stack, lease, record) {
|
|
95
|
+
return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
|
|
96
|
+
}
|
|
97
|
+
var AttributeLease = class {
|
|
64
98
|
#attribute;
|
|
65
99
|
#record;
|
|
66
100
|
#base;
|
|
101
|
+
#preserveAuthor;
|
|
67
102
|
#held = /* @__PURE__ */ new Set();
|
|
68
103
|
constructor(attribute, owner, options = {}) {
|
|
69
104
|
this.#attribute = attribute;
|
|
70
105
|
this.#record = `data-${owner}-${attribute}-lease`;
|
|
71
106
|
this.#base = options.base === true;
|
|
72
|
-
|
|
107
|
+
this.#preserveAuthor = options.preserveAuthor === true;
|
|
108
|
+
const names = registry.names;
|
|
73
109
|
names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
|
|
74
110
|
}
|
|
75
111
|
write(element, value) {
|
|
76
|
-
const stack = this.#
|
|
112
|
+
const stack = attributeStack(element, this.#attribute);
|
|
77
113
|
const hold = this.#take(stack) ?? this.#acquire(element, stack);
|
|
78
114
|
this.#held.add(element);
|
|
79
115
|
const shows = !this.#covered(element, stack, hold);
|
|
@@ -83,8 +119,8 @@ var AttributeLease = class _AttributeLease {
|
|
|
83
119
|
}
|
|
84
120
|
return(element) {
|
|
85
121
|
const held = this.#held.delete(element);
|
|
86
|
-
const known =
|
|
87
|
-
const stack = held || known || element.hasAttribute(this.#record) ? this.#
|
|
122
|
+
const known = registry.stacks.get(element)?.has(this.#attribute);
|
|
123
|
+
const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
|
|
88
124
|
const hold = this.#take(stack);
|
|
89
125
|
if (!hold) return false;
|
|
90
126
|
const carries = element.getAttribute(this.#attribute) === hold.written;
|
|
@@ -102,31 +138,8 @@ var AttributeLease = class _AttributeLease {
|
|
|
102
138
|
returnAll() {
|
|
103
139
|
for (const element of Array.from(this.#held)) this.return(element);
|
|
104
140
|
}
|
|
105
|
-
#stack(element) {
|
|
106
|
-
const stacks = _AttributeLease.#registry.stacks;
|
|
107
|
-
const byAttribute = stacks.get(element) ?? /* @__PURE__ */ new Map();
|
|
108
|
-
stacks.set(element, byAttribute);
|
|
109
|
-
const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);
|
|
110
|
-
byAttribute.set(this.#attribute, stack);
|
|
111
|
-
return stack;
|
|
112
|
-
}
|
|
113
|
-
#seed(element) {
|
|
114
|
-
const found = [];
|
|
115
|
-
for (const record of _AttributeLease.#registry.names.get(this.#attribute) ?? []) {
|
|
116
|
-
const read = readLeaseRecord(element, record);
|
|
117
|
-
if (read) found.push({ ...read, record });
|
|
118
|
-
}
|
|
119
|
-
const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
|
|
120
|
-
return found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
|
|
121
|
-
lease: null,
|
|
122
|
-
record,
|
|
123
|
-
written,
|
|
124
|
-
original,
|
|
125
|
-
linked: linked && index > 0
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
141
|
#take(stack) {
|
|
129
|
-
const hold = stack
|
|
142
|
+
const hold = findHold(stack, this, this.#record);
|
|
130
143
|
if (hold) hold.lease = this;
|
|
131
144
|
return hold;
|
|
132
145
|
}
|
|
@@ -135,7 +148,7 @@ var AttributeLease = class _AttributeLease {
|
|
|
135
148
|
const top = stack.at(-1);
|
|
136
149
|
const bottom = stack[0];
|
|
137
150
|
const over = top?.written === current ? top : void 0;
|
|
138
|
-
const from = this.#base ? bottom : over;
|
|
151
|
+
const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
|
|
139
152
|
const hold = {
|
|
140
153
|
lease: this,
|
|
141
154
|
record: this.#record,
|
|
@@ -165,15 +178,11 @@ var AttributeLease = class _AttributeLease {
|
|
|
165
178
|
);
|
|
166
179
|
});
|
|
167
180
|
for (const [name, recorded] of records) {
|
|
168
|
-
|
|
169
|
-
if (recorded === null) element.removeAttribute(name);
|
|
170
|
-
else element.setAttribute(name, recorded);
|
|
181
|
+
setAttributeIfChanged(element, name, recorded);
|
|
171
182
|
}
|
|
172
183
|
}
|
|
173
184
|
#reflect(element, value) {
|
|
174
|
-
|
|
175
|
-
if (value === null) element.removeAttribute(this.#attribute);
|
|
176
|
-
else element.setAttribute(this.#attribute, value);
|
|
185
|
+
setAttributeIfChanged(element, this.#attribute, value);
|
|
177
186
|
}
|
|
178
187
|
};
|
|
179
188
|
|
|
@@ -183,63 +192,182 @@ var COMPOSITION_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
|
183
192
|
"deleteCompositionText",
|
|
184
193
|
"deleteByComposition"
|
|
185
194
|
]);
|
|
195
|
+
function isCompositionInputType(inputType) {
|
|
196
|
+
return inputType !== void 0 && COMPOSITION_INPUT_TYPES.has(inputType);
|
|
197
|
+
}
|
|
198
|
+
var BEFORE_MORPH_ATTRIBUTE = "turbo:before-morph-attribute";
|
|
199
|
+
var textOf = (element) => element.value;
|
|
200
|
+
var holdsFocus = (element) => element instanceof Node && element.getRootNode().activeElement === element;
|
|
186
201
|
var CompositionTracker = class {
|
|
187
202
|
#observedTargets = /* @__PURE__ */ new Set();
|
|
188
|
-
#
|
|
203
|
+
#composition = null;
|
|
189
204
|
#onStart;
|
|
190
205
|
#onEnd;
|
|
206
|
+
#onAbandon;
|
|
191
207
|
#confirmedTarget = null;
|
|
208
|
+
#keyComposing = false;
|
|
209
|
+
#connected = false;
|
|
210
|
+
#abandoned = null;
|
|
192
211
|
constructor(options = {}) {
|
|
193
212
|
this.#onStart = options.onStart;
|
|
194
213
|
this.#onEnd = options.onEnd;
|
|
214
|
+
this.#onAbandon = options.onAbandon;
|
|
195
215
|
}
|
|
196
216
|
observe(target) {
|
|
217
|
+
this.#connected = true;
|
|
197
218
|
if (this.#observedTargets.has(target)) return;
|
|
198
219
|
target.addEventListener("compositionstart", this.#handleStart);
|
|
199
220
|
target.addEventListener("compositionend", this.#handleEnd);
|
|
200
|
-
target.addEventListener("keydown", this.#handleKeydown);
|
|
221
|
+
target.addEventListener("keydown", this.#handleKeydown, true);
|
|
222
|
+
target.addEventListener("beforeinput", this.#handleBeforeInput, true);
|
|
223
|
+
target.addEventListener("input", this.#handleInput, true);
|
|
224
|
+
target.addEventListener("blur", this.#handleBlur, true);
|
|
225
|
+
target.addEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
|
|
201
226
|
this.#observedTargets.add(target);
|
|
202
227
|
}
|
|
203
228
|
unobserve(target) {
|
|
204
229
|
if (!this.#observedTargets.delete(target)) return;
|
|
205
|
-
|
|
206
|
-
target
|
|
207
|
-
target.removeEventListener("keydown", this.#handleKeydown);
|
|
208
|
-
this.#activeTargets.delete(target);
|
|
230
|
+
this.#release(target);
|
|
231
|
+
if (this.#composition?.target === target) this.#letGo();
|
|
209
232
|
if (this.#confirmedTarget === target) this.#confirmedTarget = null;
|
|
210
233
|
}
|
|
211
234
|
disconnect() {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
target.removeEventListener("compositionend", this.#handleEnd);
|
|
215
|
-
target.removeEventListener("keydown", this.#handleKeydown);
|
|
216
|
-
}
|
|
235
|
+
this.#connected = false;
|
|
236
|
+
for (const target of this.#observedTargets) this.#release(target);
|
|
217
237
|
this.#observedTargets.clear();
|
|
218
|
-
this.#
|
|
238
|
+
this.#letGo();
|
|
219
239
|
this.#confirmedTarget = null;
|
|
240
|
+
this.#keyComposing = false;
|
|
241
|
+
this.#abandoned = null;
|
|
220
242
|
}
|
|
221
243
|
isComposing(event) {
|
|
222
|
-
|
|
244
|
+
this.#settle();
|
|
245
|
+
return event?.isComposing === true || this.#composition !== null;
|
|
246
|
+
}
|
|
247
|
+
composingElement() {
|
|
248
|
+
this.#settle();
|
|
249
|
+
return this.#composition?.element ?? null;
|
|
250
|
+
}
|
|
251
|
+
owns(event) {
|
|
252
|
+
const element = this.composingElement();
|
|
253
|
+
return event.isComposing === true || element !== null && element === event.target;
|
|
223
254
|
}
|
|
224
255
|
consumesConfirmedInput(event) {
|
|
225
256
|
const confirmed = this.#confirmedTarget;
|
|
226
257
|
this.#confirmedTarget = null;
|
|
227
258
|
if (confirmed === null || confirmed !== event.target) return false;
|
|
228
259
|
const inputType = event.inputType;
|
|
229
|
-
return !inputType ||
|
|
260
|
+
return !inputType || isCompositionInputType(inputType);
|
|
261
|
+
}
|
|
262
|
+
#release(target) {
|
|
263
|
+
target.removeEventListener("compositionstart", this.#handleStart);
|
|
264
|
+
target.removeEventListener("compositionend", this.#handleEnd);
|
|
265
|
+
target.removeEventListener("keydown", this.#handleKeydown, true);
|
|
266
|
+
target.removeEventListener("beforeinput", this.#handleBeforeInput, true);
|
|
267
|
+
target.removeEventListener("input", this.#handleInput, true);
|
|
268
|
+
target.removeEventListener("blur", this.#handleBlur, true);
|
|
269
|
+
target.removeEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
|
|
270
|
+
}
|
|
271
|
+
#letGo() {
|
|
272
|
+
const composition = this.#composition;
|
|
273
|
+
if (composition === null) return;
|
|
274
|
+
if (!holdsFocus(composition.element)) {
|
|
275
|
+
this.#composition = null;
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
queueMicrotask(() => {
|
|
279
|
+
if (this.#composition !== composition || this.#observedTargets.has(composition.target)) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
this.#composition = null;
|
|
283
|
+
if (!this.#connected) return;
|
|
284
|
+
this.#abandoned = { element: composition.element, inPlace: true };
|
|
285
|
+
this.#runAbandon();
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
#settle() {
|
|
289
|
+
const composition = this.#composition;
|
|
290
|
+
if (composition === null) return;
|
|
291
|
+
const { target, element, text } = composition;
|
|
292
|
+
if (target instanceof Node && element instanceof Node && !target.contains(element)) {
|
|
293
|
+
this.#composition = null;
|
|
294
|
+
} else if (textOf(element) !== text) {
|
|
295
|
+
this.#abandon(false);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
#abandon(inPlace) {
|
|
299
|
+
this.#owe(inPlace);
|
|
300
|
+
this.#composition = null;
|
|
301
|
+
queueMicrotask(this.#runAbandon);
|
|
230
302
|
}
|
|
303
|
+
#owe(inPlace) {
|
|
304
|
+
const composition = this.#composition;
|
|
305
|
+
if (composition !== null) this.#abandoned = { element: composition.element, inPlace };
|
|
306
|
+
}
|
|
307
|
+
#runAbandon = () => {
|
|
308
|
+
const abandoned = this.#abandoned;
|
|
309
|
+
if (abandoned === null) return;
|
|
310
|
+
this.#abandoned = null;
|
|
311
|
+
this.#onAbandon?.(abandoned.element, abandoned.inPlace);
|
|
312
|
+
};
|
|
231
313
|
#handleStart = (event) => {
|
|
232
314
|
this.#confirmedTarget = null;
|
|
233
|
-
|
|
315
|
+
this.#settle();
|
|
316
|
+
this.#owe(true);
|
|
317
|
+
const target = event.currentTarget;
|
|
318
|
+
const element = event.target;
|
|
319
|
+
this.#composition = { target, element, text: textOf(element) };
|
|
320
|
+
this.#runAbandon();
|
|
234
321
|
this.#onStart?.(event);
|
|
235
322
|
};
|
|
236
323
|
#handleEnd = (event) => {
|
|
237
|
-
|
|
324
|
+
this.#runAbandon();
|
|
325
|
+
if (this.#composition?.target === event.currentTarget) this.#composition = null;
|
|
238
326
|
this.#confirmedTarget = event.target;
|
|
239
327
|
this.#onEnd?.(event);
|
|
240
328
|
};
|
|
241
|
-
#handleKeydown = () => {
|
|
329
|
+
#handleKeydown = (event) => {
|
|
330
|
+
this.#settle();
|
|
331
|
+
this.#runAbandon();
|
|
242
332
|
this.#confirmedTarget = null;
|
|
333
|
+
this.#keyComposing = event.isComposing === true;
|
|
334
|
+
};
|
|
335
|
+
#handleBeforeInput = (event) => {
|
|
336
|
+
const keyComposing = this.#keyComposing;
|
|
337
|
+
this.#keyComposing = false;
|
|
338
|
+
this.#settle();
|
|
339
|
+
const { isComposing, inputType } = event;
|
|
340
|
+
if (this.#composition !== null && !keyComposing && !isComposing && inputType && !isCompositionInputType(inputType)) {
|
|
341
|
+
this.#abandon(true);
|
|
342
|
+
}
|
|
343
|
+
this.#runAbandon();
|
|
344
|
+
};
|
|
345
|
+
#handleInput = (event) => {
|
|
346
|
+
const composition = this.#composition;
|
|
347
|
+
const { isTrusted, isComposing, inputType } = event;
|
|
348
|
+
if (composition !== null && event.target === composition.element && (isTrusted || isComposing || isCompositionInputType(inputType))) {
|
|
349
|
+
composition.text = textOf(composition.element);
|
|
350
|
+
} else {
|
|
351
|
+
this.#settle();
|
|
352
|
+
}
|
|
353
|
+
this.#runAbandon();
|
|
354
|
+
};
|
|
355
|
+
#handleBlur = (event) => {
|
|
356
|
+
this.#settle();
|
|
357
|
+
this.#runAbandon();
|
|
358
|
+
const composition = this.#composition;
|
|
359
|
+
if (composition === null || composition.target === composition.element) return;
|
|
360
|
+
const { element } = composition;
|
|
361
|
+
if (!(element instanceof Node) || event.target !== element) return;
|
|
362
|
+
const root = element.getRootNode();
|
|
363
|
+
if (root.activeElement !== element) this.#composition = null;
|
|
364
|
+
};
|
|
365
|
+
#handleBeforeMorphAttribute = (event) => {
|
|
366
|
+
this.#settle();
|
|
367
|
+
const composition = this.#composition;
|
|
368
|
+
if (composition?.target !== event.currentTarget || event.target !== composition.element) return;
|
|
369
|
+
const detail = event.detail;
|
|
370
|
+
if (detail?.attributeName === "value") event.preventDefault();
|
|
243
371
|
};
|
|
244
372
|
};
|
|
245
373
|
|
|
@@ -314,6 +442,75 @@ function toHalfWidth(text) {
|
|
|
314
442
|
return out;
|
|
315
443
|
}
|
|
316
444
|
|
|
445
|
+
var TimerRegistry = class {
|
|
446
|
+
ids = /* @__PURE__ */ new Set();
|
|
447
|
+
clear(id) {
|
|
448
|
+
if (this.ids.delete(id)) {
|
|
449
|
+
this.cancel(id);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
clearAll() {
|
|
453
|
+
for (const id of this.ids) {
|
|
454
|
+
this.cancel(id);
|
|
455
|
+
}
|
|
456
|
+
this.ids.clear();
|
|
457
|
+
}
|
|
458
|
+
get size() {
|
|
459
|
+
return this.ids.size;
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
var SafeTimeout = class extends TimerRegistry {
|
|
463
|
+
set(callback, delay) {
|
|
464
|
+
const id = this.schedule(() => {
|
|
465
|
+
this.ids.delete(id);
|
|
466
|
+
callback();
|
|
467
|
+
}, delay);
|
|
468
|
+
this.ids.add(id);
|
|
469
|
+
return id;
|
|
470
|
+
}
|
|
471
|
+
schedule(callback, delay) {
|
|
472
|
+
return window.setTimeout(callback, delay);
|
|
473
|
+
}
|
|
474
|
+
cancel(id) {
|
|
475
|
+
window.clearTimeout(id);
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
var KeyedTimers = class {
|
|
480
|
+
#timers = new SafeTimeout();
|
|
481
|
+
#pending = /* @__PURE__ */ new Map();
|
|
482
|
+
set(key, callback, delay) {
|
|
483
|
+
this.clear(key);
|
|
484
|
+
const id = this.#timers.set(() => {
|
|
485
|
+
this.#pending.delete(key);
|
|
486
|
+
callback();
|
|
487
|
+
}, delay);
|
|
488
|
+
this.#pending.set(key, id);
|
|
489
|
+
}
|
|
490
|
+
clear(key) {
|
|
491
|
+
this.#timers.clear(this.#pending.get(key) ?? -1);
|
|
492
|
+
this.#pending.delete(key);
|
|
493
|
+
}
|
|
494
|
+
clearAll() {
|
|
495
|
+
this.#timers.clearAll();
|
|
496
|
+
this.#pending.clear();
|
|
497
|
+
}
|
|
498
|
+
has(key) {
|
|
499
|
+
return this.#pending.has(key);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
var ListenerSet = class {
|
|
504
|
+
#abort = new AbortController();
|
|
505
|
+
add(target, type, handler, options) {
|
|
506
|
+
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
507
|
+
}
|
|
508
|
+
dispose() {
|
|
509
|
+
this.#abort.abort();
|
|
510
|
+
this.#abort = new AbortController();
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
317
514
|
var MicrotaskCoalescer = class {
|
|
318
515
|
#run;
|
|
319
516
|
#queued = false;
|
|
@@ -330,6 +527,9 @@ var MicrotaskCoalescer = class {
|
|
|
330
527
|
this.#queued = false;
|
|
331
528
|
this.#generation += 1;
|
|
332
529
|
}
|
|
530
|
+
get pending() {
|
|
531
|
+
return this.#queued;
|
|
532
|
+
}
|
|
333
533
|
schedule() {
|
|
334
534
|
if (!this.#active || this.#queued) return;
|
|
335
535
|
this.#queued = true;
|
|
@@ -342,6 +542,34 @@ var MicrotaskCoalescer = class {
|
|
|
342
542
|
}
|
|
343
543
|
};
|
|
344
544
|
|
|
545
|
+
var MorphRenderWatcher = class {
|
|
546
|
+
#listeners = new ListenerSet();
|
|
547
|
+
#pass;
|
|
548
|
+
#element = null;
|
|
549
|
+
#onMorph = () => this.#pass.schedule();
|
|
550
|
+
constructor(run) {
|
|
551
|
+
this.#pass = new MicrotaskCoalescer(run);
|
|
552
|
+
}
|
|
553
|
+
observe(element) {
|
|
554
|
+
if (this.#element === element) return;
|
|
555
|
+
this.disconnect();
|
|
556
|
+
this.#element = element;
|
|
557
|
+
this.#pass.activate();
|
|
558
|
+
this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
|
|
559
|
+
}
|
|
560
|
+
schedule() {
|
|
561
|
+
this.#pass.schedule();
|
|
562
|
+
}
|
|
563
|
+
get pending() {
|
|
564
|
+
return this.#pass.pending;
|
|
565
|
+
}
|
|
566
|
+
disconnect() {
|
|
567
|
+
this.#listeners.dispose();
|
|
568
|
+
this.#pass.cancel();
|
|
569
|
+
this.#element = null;
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
|
|
345
573
|
var MoveCounter = class {
|
|
346
574
|
#sequence = 0;
|
|
347
575
|
record() {
|
|
@@ -376,9 +604,6 @@ function describedByWith(described, errorId, earlier) {
|
|
|
376
604
|
}
|
|
377
605
|
var DEFAULT_PATTERN = "[0-9]";
|
|
378
606
|
var DEFAULT_MATCHER = new RegExp(`^(?:${DEFAULT_PATTERN})$`);
|
|
379
|
-
function hasModifier(event) {
|
|
380
|
-
return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
381
|
-
}
|
|
382
607
|
function statesDiffer(left, right) {
|
|
383
608
|
return left.value !== right.value || left.state !== right.state;
|
|
384
609
|
}
|
|
@@ -395,9 +620,15 @@ var OtpController = class extends Controller {
|
|
|
395
620
|
#published = null;
|
|
396
621
|
#connected = false;
|
|
397
622
|
#committed = /* @__PURE__ */ new WeakMap();
|
|
623
|
+
#retained = /* @__PURE__ */ new WeakMap();
|
|
624
|
+
#inputBaselines = /* @__PURE__ */ new Map();
|
|
625
|
+
#inputExpiry = new KeyedTimers();
|
|
626
|
+
#endBaselines = /* @__PURE__ */ new Map();
|
|
627
|
+
#away = /* @__PURE__ */ new Set();
|
|
398
628
|
#composing = null;
|
|
399
629
|
#dropHeld = false;
|
|
400
|
-
#
|
|
630
|
+
#judgedBy = null;
|
|
631
|
+
#reconcile = new MorphRenderWatcher(() => this.#reconcileFields());
|
|
401
632
|
#errorHidden = new AttributeLease("hidden", this.identifier);
|
|
402
633
|
#state = new AttributeLease("data-state", this.identifier);
|
|
403
634
|
#formReset = new FormResetWatcher(
|
|
@@ -410,36 +641,68 @@ var OtpController = class extends Controller {
|
|
|
410
641
|
#composition = new CompositionTracker({
|
|
411
642
|
onStart: (event) => {
|
|
412
643
|
const field = this.#fieldFrom(event);
|
|
413
|
-
|
|
644
|
+
this.#clearInputBaseline();
|
|
645
|
+
if (field) this.#endBaselines.delete(field);
|
|
646
|
+
if (field && this.#composition.composingElement() === field) {
|
|
647
|
+
this.#composing = { field, before: field.value };
|
|
648
|
+
}
|
|
414
649
|
},
|
|
415
650
|
onEnd: (event) => {
|
|
416
|
-
const composing = this.#composing;
|
|
417
|
-
this.#composing = null;
|
|
418
651
|
const input = this.#fieldFrom(event);
|
|
652
|
+
if (!input) return;
|
|
653
|
+
const baseline = this.#inputBaselines.get(input) ?? this.#endBaselines.get(input)?.baseline;
|
|
654
|
+
this.#clearEdits(input);
|
|
655
|
+
const composing = this.#composing;
|
|
656
|
+
if (!this.#composition.isComposing()) this.#composing = null;
|
|
419
657
|
const data = event.data ?? "";
|
|
420
|
-
const text =
|
|
421
|
-
const commit =
|
|
422
|
-
if (this.#
|
|
423
|
-
|
|
658
|
+
const text = data.length <= input.value.length ? input.value : data;
|
|
659
|
+
const commit = composing?.field !== input || text !== composing.before;
|
|
660
|
+
if (commit) this.#accept(input, text, baseline?.interrupted ? baseline : void 0);
|
|
661
|
+
else {
|
|
662
|
+
this.#restoreRetained(input);
|
|
663
|
+
if (this.#dropHeld) this.#reconcileFields();
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
onAbandon: (element, inPlace) => {
|
|
667
|
+
this.#composing = null;
|
|
668
|
+
if (inPlace && element instanceof HTMLInputElement && this.fieldTargets.includes(element)) {
|
|
669
|
+
const baseline = this.#inputBaselines.get(element) ?? {
|
|
670
|
+
field: element,
|
|
671
|
+
before: this.#committed.get(element) ?? "",
|
|
672
|
+
dropHeld: this.#dropHeld,
|
|
673
|
+
interrupted: true
|
|
674
|
+
};
|
|
675
|
+
baseline.interrupted = true;
|
|
676
|
+
this.#settleResidual(element);
|
|
677
|
+
this.#endBaselines.set(element, { text: element.value, baseline });
|
|
424
678
|
this.#reconcileFields();
|
|
679
|
+
} else if (this.#dropHeld) {
|
|
680
|
+
this.#reconcile.schedule();
|
|
425
681
|
}
|
|
426
|
-
if (input && commit) this.#accept(input, text);
|
|
427
682
|
}
|
|
428
683
|
});
|
|
429
684
|
connect() {
|
|
430
685
|
this.#connected = true;
|
|
431
686
|
for (const field of this.fieldTargets) this.#bind(field);
|
|
432
687
|
this.#formReset.observe();
|
|
433
|
-
this.#reconcile.
|
|
688
|
+
this.#reconcile.observe(this.element);
|
|
434
689
|
this.#adopt();
|
|
435
690
|
this.#sync();
|
|
691
|
+
this.#judgedBy ??= this.#patternSource;
|
|
692
|
+
if (this.#judgedBy !== this.#patternSource) {
|
|
693
|
+
if (this.#composition.isComposing()) this.#dropHeld = true;
|
|
694
|
+
else if (this.#dropRejected()) this.#reconcile.schedule();
|
|
695
|
+
}
|
|
436
696
|
}
|
|
437
697
|
disconnect() {
|
|
438
698
|
this.#connected = false;
|
|
439
699
|
for (const field of this.fieldTargets) this.#unbind(field);
|
|
440
700
|
this.#composition.disconnect();
|
|
701
|
+
this.#clearInputBaseline();
|
|
702
|
+
for (const field of this.#endBaselines.keys())
|
|
703
|
+
if (!this.#away.has(field)) this.#endBaselines.delete(field);
|
|
441
704
|
this.#formReset.disconnect();
|
|
442
|
-
this.#reconcile.
|
|
705
|
+
this.#reconcile.disconnect();
|
|
443
706
|
this.#dropHeld = false;
|
|
444
707
|
this.#clearError();
|
|
445
708
|
this.#state.return(this.element);
|
|
@@ -451,7 +714,7 @@ var OtpController = class extends Controller {
|
|
|
451
714
|
}
|
|
452
715
|
fieldTargetDisconnected(element) {
|
|
453
716
|
this.#unbind(element);
|
|
454
|
-
this.#returnLeases(element);
|
|
717
|
+
if (!this.fieldTargets.includes(element)) this.#returnLeases(element);
|
|
455
718
|
this.#reconcile.schedule();
|
|
456
719
|
}
|
|
457
720
|
valueTargetConnected() {
|
|
@@ -472,18 +735,28 @@ var OtpController = class extends Controller {
|
|
|
472
735
|
this.#patternSource = compiled ? this.patternValue : DEFAULT_PATTERN;
|
|
473
736
|
this.#pattern = compiled ?? DEFAULT_MATCHER;
|
|
474
737
|
if (!this.#connected) return;
|
|
475
|
-
if (this.#
|
|
738
|
+
if (this.#composition.isComposing()) {
|
|
476
739
|
this.#dropHeld = true;
|
|
477
740
|
return;
|
|
478
741
|
}
|
|
479
742
|
if (this.#dropRejected()) this.#reconcile.schedule();
|
|
480
743
|
}
|
|
481
|
-
#dropRejected() {
|
|
744
|
+
#dropRejected(composing = null) {
|
|
745
|
+
if (composing === null) this.#judgedBy = this.#patternSource;
|
|
482
746
|
let dropped = false;
|
|
483
747
|
for (const field of this.fieldTargets) {
|
|
484
|
-
if (field
|
|
485
|
-
|
|
486
|
-
|
|
748
|
+
if (field === composing) {
|
|
749
|
+
const committed = this.#committed.get(field) ?? "";
|
|
750
|
+
if (committed === "" || !this.#isWritable(field) || this.#pattern.test(committed)) continue;
|
|
751
|
+
this.#committed.set(field, "");
|
|
752
|
+
dropped = true;
|
|
753
|
+
continue;
|
|
754
|
+
}
|
|
755
|
+
const value = this.#settledText(field);
|
|
756
|
+
if (value === "" || !this.#isWritable(field)) continue;
|
|
757
|
+
if (this.#pattern.test(value)) continue;
|
|
758
|
+
if (this.#retained.has(field)) this.#holdText(field, "");
|
|
759
|
+
else this.#writeField(field, "");
|
|
487
760
|
dropped = true;
|
|
488
761
|
}
|
|
489
762
|
return dropped;
|
|
@@ -491,20 +764,24 @@ var OtpController = class extends Controller {
|
|
|
491
764
|
onInput(event) {
|
|
492
765
|
const input = this.#fieldFrom(event);
|
|
493
766
|
if (!input) return;
|
|
767
|
+
const baseline = this.#inputBaselines.get(input);
|
|
768
|
+
this.#clearEdits(input);
|
|
494
769
|
if (this.#composition.consumesConfirmedInput(event)) return;
|
|
495
|
-
if (this.#composition.
|
|
496
|
-
this.#accept(input);
|
|
770
|
+
if (this.#composition.owns(event)) return;
|
|
771
|
+
this.#accept(input, input.value, baseline?.interrupted ? baseline : void 0);
|
|
497
772
|
}
|
|
498
773
|
onKeydown(event) {
|
|
774
|
+
this.#clearInputBaseline();
|
|
499
775
|
if (isReservedArrowChord(event)) return;
|
|
500
776
|
const input = this.#fieldFrom(event);
|
|
501
777
|
if (!input) return;
|
|
502
|
-
if (this.#composition.
|
|
778
|
+
if (this.#composition.owns(event)) return;
|
|
779
|
+
if (!this.#prepareEdit(input)) return;
|
|
503
780
|
const index = this.fieldTargets.indexOf(input);
|
|
504
781
|
const fields = this.fieldTargets;
|
|
505
782
|
switch (logicalArrowKey(event.key, this.element)) {
|
|
506
783
|
case "Backspace":
|
|
507
|
-
if (
|
|
784
|
+
if (hasModifierChord(event)) break;
|
|
508
785
|
if (input.value && this.#isWritable(input)) {
|
|
509
786
|
event.preventDefault();
|
|
510
787
|
this.#writeField(input, "");
|
|
@@ -538,7 +815,7 @@ var OtpController = class extends Controller {
|
|
|
538
815
|
break;
|
|
539
816
|
}
|
|
540
817
|
case "Home": {
|
|
541
|
-
if (
|
|
818
|
+
if (hasModifierChord(event)) break;
|
|
542
819
|
const first = fields.find((field) => this.#isFocusable(field));
|
|
543
820
|
if (first) {
|
|
544
821
|
event.preventDefault();
|
|
@@ -547,7 +824,7 @@ var OtpController = class extends Controller {
|
|
|
547
824
|
break;
|
|
548
825
|
}
|
|
549
826
|
case "End": {
|
|
550
|
-
if (
|
|
827
|
+
if (hasModifierChord(event)) break;
|
|
551
828
|
const last = fields.slice().reverse().find((field) => this.#isFocusable(field));
|
|
552
829
|
if (last) {
|
|
553
830
|
event.preventDefault();
|
|
@@ -561,7 +838,8 @@ var OtpController = class extends Controller {
|
|
|
561
838
|
const input = this.#fieldFrom(event);
|
|
562
839
|
if (!input) return;
|
|
563
840
|
event.preventDefault();
|
|
564
|
-
this.#
|
|
841
|
+
if (this.#prepareEdit(input))
|
|
842
|
+
this.#distribute(input, toHalfWidth(event.clipboardData?.getData("text") ?? ""), false);
|
|
565
843
|
}
|
|
566
844
|
onPointerDown(event) {
|
|
567
845
|
const input = this.#fieldFrom(event);
|
|
@@ -579,6 +857,31 @@ var OtpController = class extends Controller {
|
|
|
579
857
|
this.fieldTargets.find((field) => this.#isWritable(field))?.focus();
|
|
580
858
|
this.#syncAndDispatch();
|
|
581
859
|
}
|
|
860
|
+
#onBeforeInput = (event) => {
|
|
861
|
+
const field = event.currentTarget;
|
|
862
|
+
this.#clearEdits(field);
|
|
863
|
+
if (event.isComposing || !event.inputType || isCompositionInputType(event.inputType)) return;
|
|
864
|
+
this.#inputBaselines.set(field, {
|
|
865
|
+
field,
|
|
866
|
+
before: this.#committed.get(field) ?? "",
|
|
867
|
+
dropHeld: this.#dropHeld,
|
|
868
|
+
interrupted: false
|
|
869
|
+
});
|
|
870
|
+
this.#inputExpiry.set(field, () => this.#clearInputBaseline(field), 0);
|
|
871
|
+
};
|
|
872
|
+
#clearInputBaseline(field) {
|
|
873
|
+
if (field) {
|
|
874
|
+
this.#inputBaselines.delete(field);
|
|
875
|
+
this.#inputExpiry.clear(field);
|
|
876
|
+
} else {
|
|
877
|
+
this.#inputBaselines.clear();
|
|
878
|
+
this.#inputExpiry.clearAll();
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
#clearEdits(field) {
|
|
882
|
+
this.#clearInputBaseline(field);
|
|
883
|
+
this.#endBaselines.delete(field);
|
|
884
|
+
}
|
|
582
885
|
#onFieldFocus = (event) => {
|
|
583
886
|
const input = event.currentTarget;
|
|
584
887
|
if (input) {
|
|
@@ -591,12 +894,24 @@ var OtpController = class extends Controller {
|
|
|
591
894
|
}
|
|
592
895
|
#bind(field) {
|
|
593
896
|
field.addEventListener("focus", this.#onFieldFocus);
|
|
897
|
+
field.addEventListener("beforeinput", this.#onBeforeInput, true);
|
|
898
|
+
if (this.#away.delete(field) && document.activeElement !== field)
|
|
899
|
+
this.#endBaselines.delete(field);
|
|
594
900
|
this.#composition.observe(field);
|
|
595
901
|
}
|
|
596
902
|
#unbind(field) {
|
|
597
903
|
field.removeEventListener("focus", this.#onFieldFocus);
|
|
904
|
+
field.removeEventListener("beforeinput", this.#onBeforeInput, true);
|
|
905
|
+
this.#clearInputBaseline(field);
|
|
906
|
+
if (document.activeElement === field) this.#holdAway(field);
|
|
907
|
+
else this.#endBaselines.delete(field);
|
|
598
908
|
this.#composition.unobserve(field);
|
|
599
|
-
|
|
909
|
+
}
|
|
910
|
+
#holdAway(field) {
|
|
911
|
+
this.#away.add(field);
|
|
912
|
+
queueMicrotask(() => {
|
|
913
|
+
if (this.#away.delete(field)) this.#endBaselines.delete(field);
|
|
914
|
+
});
|
|
600
915
|
}
|
|
601
916
|
#adopt() {
|
|
602
917
|
for (const field of this.fieldTargets) this.#adoptField(field);
|
|
@@ -620,36 +935,49 @@ var OtpController = class extends Controller {
|
|
|
620
935
|
}
|
|
621
936
|
}
|
|
622
937
|
#adoptField(field) {
|
|
623
|
-
this.#
|
|
624
|
-
this.#
|
|
938
|
+
if (this.#composition.composingElement() === field) return;
|
|
939
|
+
const value = this.#settledText(field);
|
|
940
|
+
this.#committed.set(field, value);
|
|
941
|
+
this.#markFilled(field, value);
|
|
625
942
|
}
|
|
626
943
|
#reconcileFields() {
|
|
627
|
-
|
|
944
|
+
const composing = this.#composition.composingElement();
|
|
945
|
+
if (this.#dropHeld && composing === null) {
|
|
628
946
|
this.#dropHeld = false;
|
|
629
947
|
this.#dropRejected();
|
|
630
948
|
}
|
|
949
|
+
for (const field of this.fieldTargets) {
|
|
950
|
+
if (field === composing) this.#markFilled(field, this.#publishedText(field));
|
|
951
|
+
else this.#adoptField(field);
|
|
952
|
+
}
|
|
631
953
|
const previous = this.#published;
|
|
632
954
|
const current = this.#sync();
|
|
633
|
-
if (previous && !statesDiffer(previous, current)) return;
|
|
634
|
-
this.#moves.record();
|
|
955
|
+
if (previous && !statesDiffer(previous, current)) return true;
|
|
956
|
+
const token = this.#moves.record();
|
|
635
957
|
this.dispatch("reconcile", { detail: { value: current.value } });
|
|
958
|
+
return this.#moves.isLatest(token);
|
|
636
959
|
}
|
|
637
|
-
#accept(input, text = input.value) {
|
|
960
|
+
#accept(input, text = input.value, baseline) {
|
|
961
|
+
if (!this.#prepareEdit(input, true)) return;
|
|
962
|
+
const before = baseline ? this.fieldTargets.map(
|
|
963
|
+
(field) => field === input ? baseline.dropHeld && !this.#pattern.test(baseline.before) ? "" : baseline.before : this.#publishedText(field)
|
|
964
|
+
).join("") : void 0;
|
|
638
965
|
const raw = toHalfWidth(text);
|
|
639
966
|
if (raw === "") {
|
|
640
967
|
this.#writeField(input, "");
|
|
641
968
|
this.#clearError();
|
|
642
|
-
this.#syncAndDispatch();
|
|
969
|
+
this.#syncAndDispatch(before);
|
|
643
970
|
return;
|
|
644
971
|
}
|
|
645
|
-
this.#distribute(input, raw);
|
|
972
|
+
this.#distribute(input, raw, true, before);
|
|
646
973
|
}
|
|
647
|
-
#distribute(from, text) {
|
|
974
|
+
#distribute(from, text, spare = true, before) {
|
|
648
975
|
const accepted = Array.from(text).filter((char) => this.#pattern.test(char));
|
|
649
976
|
let reached = false;
|
|
977
|
+
const composing = spare ? this.#composition.composingElement() : null;
|
|
650
978
|
const slots = this.fieldTargets.filter((field) => {
|
|
651
979
|
reached ||= field === from;
|
|
652
|
-
return reached && this.#isWritable(field);
|
|
980
|
+
return reached && field !== composing && this.#isWritable(field);
|
|
653
981
|
});
|
|
654
982
|
const filled = Math.min(accepted.length, slots.length);
|
|
655
983
|
if (filled === 0) {
|
|
@@ -664,14 +992,76 @@ var OtpController = class extends Controller {
|
|
|
664
992
|
if (field && char) this.#writeField(field, char);
|
|
665
993
|
}
|
|
666
994
|
const last = slots[filled - 1];
|
|
667
|
-
if (last) (this.#writableAfter(last) ?? last).focus();
|
|
995
|
+
if (last && composing === null) (this.#writableAfter(last) ?? last).focus();
|
|
668
996
|
this.#clearError();
|
|
669
|
-
this.#syncAndDispatch();
|
|
997
|
+
this.#syncAndDispatch(before);
|
|
998
|
+
}
|
|
999
|
+
#prepareEdit(input, edit = false) {
|
|
1000
|
+
if (!this.#dropHeld) return true;
|
|
1001
|
+
if (edit) this.#holdText(input, this.#committed.get(input) ?? "");
|
|
1002
|
+
const composing = this.#composition.composingElement();
|
|
1003
|
+
if (composing !== null) this.#dropRejected(composing);
|
|
1004
|
+
return this.#reconcileFields() && this.#connected && this.fieldTargets.includes(input) && this.#composition.composingElement() === composing;
|
|
1005
|
+
}
|
|
1006
|
+
#settleResidual(field) {
|
|
1007
|
+
const raw = toHalfWidth(field.value);
|
|
1008
|
+
const previous = this.#committed.get(field) ?? "";
|
|
1009
|
+
const accepts = (text) => Array.from(text).length === 1 && this.#pattern.test(text);
|
|
1010
|
+
const value = raw === "" || accepts(raw) ? raw : accepts(previous) ? previous : "";
|
|
1011
|
+
if (this.#isWritable(field) && this.#composition.composingElement() !== field) {
|
|
1012
|
+
const { selectionStart, selectionEnd } = field;
|
|
1013
|
+
this.#writeField(field, value);
|
|
1014
|
+
if (selectionStart !== null && selectionEnd !== null)
|
|
1015
|
+
field.setSelectionRange(selectionStart, selectionEnd);
|
|
1016
|
+
} else this.#holdText(field, value);
|
|
1017
|
+
}
|
|
1018
|
+
#holdText(field, value) {
|
|
1019
|
+
const retained = { text: field.value, value };
|
|
1020
|
+
this.#retained.set(field, retained);
|
|
1021
|
+
field.setAttribute(this.#retainedMarker, JSON.stringify(retained));
|
|
1022
|
+
this.#committed.set(field, value);
|
|
1023
|
+
}
|
|
1024
|
+
#settledText(field) {
|
|
1025
|
+
const ending = this.#endBaselines.get(field);
|
|
1026
|
+
if (ending && ending.text !== field.value) this.#clearEdits(field);
|
|
1027
|
+
const retained = this.#retained.get(field) ?? this.#readRetained(field);
|
|
1028
|
+
if (retained?.text === field.value) {
|
|
1029
|
+
this.#retained.set(field, retained);
|
|
1030
|
+
const marker = JSON.stringify(retained);
|
|
1031
|
+
if (field.getAttribute(this.#retainedMarker) !== marker)
|
|
1032
|
+
field.setAttribute(this.#retainedMarker, marker);
|
|
1033
|
+
return retained.value;
|
|
1034
|
+
}
|
|
1035
|
+
this.#retained.delete(field);
|
|
1036
|
+
field.removeAttribute(this.#retainedMarker);
|
|
1037
|
+
return field.value;
|
|
1038
|
+
}
|
|
1039
|
+
get #retainedMarker() {
|
|
1040
|
+
return `data-${this.identifier}-interrupted`;
|
|
1041
|
+
}
|
|
1042
|
+
#readRetained(field) {
|
|
1043
|
+
try {
|
|
1044
|
+
const record = JSON.parse(field.getAttribute(this.#retainedMarker) ?? "null");
|
|
1045
|
+
if (typeof record === "object" && record !== null && "text" in record && "value" in record && typeof record.text === "string" && typeof record.value === "string") {
|
|
1046
|
+
return { text: record.text, value: record.value };
|
|
1047
|
+
}
|
|
1048
|
+
} catch {
|
|
1049
|
+
return null;
|
|
1050
|
+
}
|
|
1051
|
+
return null;
|
|
1052
|
+
}
|
|
1053
|
+
#restoreRetained(field) {
|
|
1054
|
+
const retained = this.#retained.get(field);
|
|
1055
|
+
if (retained?.text === field.value && this.#isWritable(field))
|
|
1056
|
+
this.#writeField(field, retained.value);
|
|
670
1057
|
}
|
|
671
1058
|
#restore(field) {
|
|
672
1059
|
this.#writeField(field, this.#committed.get(field) ?? "");
|
|
673
1060
|
}
|
|
674
1061
|
#writeField(field, value) {
|
|
1062
|
+
this.#retained.delete(field);
|
|
1063
|
+
this.#endBaselines.delete(field);
|
|
1064
|
+
field.removeAttribute(this.#retainedMarker);
|
|
675
1065
|
field.value = value;
|
|
676
1066
|
this.#committed.set(field, value);
|
|
677
1067
|
this.#markFilled(field, value);
|
|
@@ -714,7 +1104,7 @@ var OtpController = class extends Controller {
|
|
|
714
1104
|
return fields.length > 0 && fields.every((field) => this.#publishedText(field).length > 0);
|
|
715
1105
|
}
|
|
716
1106
|
#publishedText(field) {
|
|
717
|
-
return field === this.#
|
|
1107
|
+
return field === this.#composition.composingElement() ? this.#committed.get(field) ?? "" : this.#settledText(field);
|
|
718
1108
|
}
|
|
719
1109
|
#sync() {
|
|
720
1110
|
const combined = this.#combinedValue();
|
|
@@ -731,11 +1121,19 @@ var OtpController = class extends Controller {
|
|
|
731
1121
|
if (combined.length === 0) return "empty";
|
|
732
1122
|
return this.#isComplete() ? "complete" : "partial";
|
|
733
1123
|
}
|
|
734
|
-
#syncAndDispatch() {
|
|
1124
|
+
#syncAndDispatch(before) {
|
|
735
1125
|
const previous = this.#published;
|
|
736
|
-
const
|
|
737
|
-
|
|
1126
|
+
const current = this.#sync();
|
|
1127
|
+
const combined = current.value;
|
|
1128
|
+
if ((before ?? previous?.value) === combined) {
|
|
1129
|
+
if (previous && statesDiffer(previous, current)) {
|
|
1130
|
+
this.#moves.record();
|
|
1131
|
+
this.dispatch("reconcile", { detail: { value: combined } });
|
|
1132
|
+
}
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
738
1135
|
const token = this.#moves.record();
|
|
1136
|
+
this.#endBaselines.clear();
|
|
739
1137
|
this.dispatch("change", { detail: { value: combined } });
|
|
740
1138
|
if (!this.#moves.isLatest(token)) return;
|
|
741
1139
|
if (this.#isComplete()) {
|