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,87 +1,190 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
// src/controllers/currency_input_controller.ts
|
|
4
|
-
|
|
5
|
-
// src/utils/composition_tracker.ts
|
|
6
3
|
var COMPOSITION_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
7
4
|
"insertCompositionText",
|
|
8
5
|
"insertFromComposition",
|
|
9
6
|
"deleteCompositionText",
|
|
10
7
|
"deleteByComposition"
|
|
11
8
|
]);
|
|
9
|
+
function isCompositionInputType(inputType) {
|
|
10
|
+
return inputType !== void 0 && COMPOSITION_INPUT_TYPES.has(inputType);
|
|
11
|
+
}
|
|
12
|
+
var BEFORE_MORPH_ATTRIBUTE = "turbo:before-morph-attribute";
|
|
13
|
+
var textOf = (element) => element.value;
|
|
14
|
+
var holdsFocus = (element) => element instanceof Node && element.getRootNode().activeElement === element;
|
|
12
15
|
var CompositionTracker = class {
|
|
13
16
|
#observedTargets = /* @__PURE__ */ new Set();
|
|
14
|
-
#
|
|
17
|
+
#composition = null;
|
|
15
18
|
#onStart;
|
|
16
19
|
#onEnd;
|
|
17
|
-
|
|
20
|
+
#onAbandon;
|
|
18
21
|
#confirmedTarget = null;
|
|
22
|
+
#keyComposing = false;
|
|
23
|
+
#connected = false;
|
|
24
|
+
#abandoned = null;
|
|
19
25
|
constructor(options = {}) {
|
|
20
26
|
this.#onStart = options.onStart;
|
|
21
27
|
this.#onEnd = options.onEnd;
|
|
28
|
+
this.#onAbandon = options.onAbandon;
|
|
22
29
|
}
|
|
23
|
-
/** Starts lifecycle tracking for `target`; repeated calls are idempotent. */
|
|
24
30
|
observe(target) {
|
|
31
|
+
this.#connected = true;
|
|
25
32
|
if (this.#observedTargets.has(target)) return;
|
|
26
33
|
target.addEventListener("compositionstart", this.#handleStart);
|
|
27
34
|
target.addEventListener("compositionend", this.#handleEnd);
|
|
28
|
-
target.addEventListener("keydown", this.#handleKeydown);
|
|
35
|
+
target.addEventListener("keydown", this.#handleKeydown, true);
|
|
36
|
+
target.addEventListener("beforeinput", this.#handleBeforeInput, true);
|
|
37
|
+
target.addEventListener("input", this.#handleInput, true);
|
|
38
|
+
target.addEventListener("blur", this.#handleBlur, true);
|
|
39
|
+
target.addEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
|
|
29
40
|
this.#observedTargets.add(target);
|
|
30
41
|
}
|
|
31
|
-
/** Stops tracking one target and clears any active composition it owned. */
|
|
32
42
|
unobserve(target) {
|
|
33
43
|
if (!this.#observedTargets.delete(target)) return;
|
|
34
|
-
|
|
35
|
-
target
|
|
36
|
-
target.removeEventListener("keydown", this.#handleKeydown);
|
|
37
|
-
this.#activeTargets.delete(target);
|
|
44
|
+
this.#release(target);
|
|
45
|
+
if (this.#composition?.target === target) this.#letGo();
|
|
38
46
|
if (this.#confirmedTarget === target) this.#confirmedTarget = null;
|
|
39
47
|
}
|
|
40
|
-
/** Releases every listener and clears state so reconnect starts cleanly. */
|
|
41
48
|
disconnect() {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
target.removeEventListener("compositionend", this.#handleEnd);
|
|
45
|
-
target.removeEventListener("keydown", this.#handleKeydown);
|
|
46
|
-
}
|
|
49
|
+
this.#connected = false;
|
|
50
|
+
for (const target of this.#observedTargets) this.#release(target);
|
|
47
51
|
this.#observedTargets.clear();
|
|
48
|
-
this.#
|
|
52
|
+
this.#letGo();
|
|
49
53
|
this.#confirmedTarget = null;
|
|
54
|
+
this.#keyComposing = false;
|
|
55
|
+
this.#abandoned = null;
|
|
50
56
|
}
|
|
51
|
-
/** True when lifecycle tracking or the current event reports composition. */
|
|
52
57
|
isComposing(event) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
this.#settle();
|
|
59
|
+
return event?.isComposing === true || this.#composition !== null;
|
|
60
|
+
}
|
|
61
|
+
composingElement() {
|
|
62
|
+
this.#settle();
|
|
63
|
+
return this.#composition?.element ?? null;
|
|
64
|
+
}
|
|
65
|
+
owns(event) {
|
|
66
|
+
const element = this.composingElement();
|
|
67
|
+
return event.isComposing === true || element !== null && element === event.target;
|
|
68
|
+
}
|
|
61
69
|
consumesConfirmedInput(event) {
|
|
62
70
|
const confirmed = this.#confirmedTarget;
|
|
63
71
|
this.#confirmedTarget = null;
|
|
64
72
|
if (confirmed === null || confirmed !== event.target) return false;
|
|
65
73
|
const inputType = event.inputType;
|
|
66
|
-
return !inputType ||
|
|
74
|
+
return !inputType || isCompositionInputType(inputType);
|
|
75
|
+
}
|
|
76
|
+
#release(target) {
|
|
77
|
+
target.removeEventListener("compositionstart", this.#handleStart);
|
|
78
|
+
target.removeEventListener("compositionend", this.#handleEnd);
|
|
79
|
+
target.removeEventListener("keydown", this.#handleKeydown, true);
|
|
80
|
+
target.removeEventListener("beforeinput", this.#handleBeforeInput, true);
|
|
81
|
+
target.removeEventListener("input", this.#handleInput, true);
|
|
82
|
+
target.removeEventListener("blur", this.#handleBlur, true);
|
|
83
|
+
target.removeEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
|
|
84
|
+
}
|
|
85
|
+
#letGo() {
|
|
86
|
+
const composition = this.#composition;
|
|
87
|
+
if (composition === null) return;
|
|
88
|
+
if (!holdsFocus(composition.element)) {
|
|
89
|
+
this.#composition = null;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
queueMicrotask(() => {
|
|
93
|
+
if (this.#composition !== composition || this.#observedTargets.has(composition.target)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
this.#composition = null;
|
|
97
|
+
if (!this.#connected) return;
|
|
98
|
+
this.#abandoned = { element: composition.element, inPlace: true };
|
|
99
|
+
this.#runAbandon();
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
#settle() {
|
|
103
|
+
const composition = this.#composition;
|
|
104
|
+
if (composition === null) return;
|
|
105
|
+
const { target, element, text } = composition;
|
|
106
|
+
if (target instanceof Node && element instanceof Node && !target.contains(element)) {
|
|
107
|
+
this.#composition = null;
|
|
108
|
+
} else if (textOf(element) !== text) {
|
|
109
|
+
this.#abandon(false);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
#abandon(inPlace) {
|
|
113
|
+
this.#owe(inPlace);
|
|
114
|
+
this.#composition = null;
|
|
115
|
+
queueMicrotask(this.#runAbandon);
|
|
67
116
|
}
|
|
117
|
+
#owe(inPlace) {
|
|
118
|
+
const composition = this.#composition;
|
|
119
|
+
if (composition !== null) this.#abandoned = { element: composition.element, inPlace };
|
|
120
|
+
}
|
|
121
|
+
#runAbandon = () => {
|
|
122
|
+
const abandoned = this.#abandoned;
|
|
123
|
+
if (abandoned === null) return;
|
|
124
|
+
this.#abandoned = null;
|
|
125
|
+
this.#onAbandon?.(abandoned.element, abandoned.inPlace);
|
|
126
|
+
};
|
|
68
127
|
#handleStart = (event) => {
|
|
69
128
|
this.#confirmedTarget = null;
|
|
70
|
-
|
|
129
|
+
this.#settle();
|
|
130
|
+
this.#owe(true);
|
|
131
|
+
const target = event.currentTarget;
|
|
132
|
+
const element = event.target;
|
|
133
|
+
this.#composition = { target, element, text: textOf(element) };
|
|
134
|
+
this.#runAbandon();
|
|
71
135
|
this.#onStart?.(event);
|
|
72
136
|
};
|
|
73
137
|
#handleEnd = (event) => {
|
|
74
|
-
|
|
138
|
+
this.#runAbandon();
|
|
139
|
+
if (this.#composition?.target === event.currentTarget) this.#composition = null;
|
|
75
140
|
this.#confirmedTarget = event.target;
|
|
76
141
|
this.#onEnd?.(event);
|
|
77
142
|
};
|
|
78
|
-
|
|
79
|
-
|
|
143
|
+
#handleKeydown = (event) => {
|
|
144
|
+
this.#settle();
|
|
145
|
+
this.#runAbandon();
|
|
80
146
|
this.#confirmedTarget = null;
|
|
147
|
+
this.#keyComposing = event.isComposing === true;
|
|
148
|
+
};
|
|
149
|
+
#handleBeforeInput = (event) => {
|
|
150
|
+
const keyComposing = this.#keyComposing;
|
|
151
|
+
this.#keyComposing = false;
|
|
152
|
+
this.#settle();
|
|
153
|
+
const { isComposing, inputType } = event;
|
|
154
|
+
if (this.#composition !== null && !keyComposing && !isComposing && inputType && !isCompositionInputType(inputType)) {
|
|
155
|
+
this.#abandon(true);
|
|
156
|
+
}
|
|
157
|
+
this.#runAbandon();
|
|
158
|
+
};
|
|
159
|
+
#handleInput = (event) => {
|
|
160
|
+
const composition = this.#composition;
|
|
161
|
+
const { isTrusted, isComposing, inputType } = event;
|
|
162
|
+
if (composition !== null && event.target === composition.element && (isTrusted || isComposing || isCompositionInputType(inputType))) {
|
|
163
|
+
composition.text = textOf(composition.element);
|
|
164
|
+
} else {
|
|
165
|
+
this.#settle();
|
|
166
|
+
}
|
|
167
|
+
this.#runAbandon();
|
|
168
|
+
};
|
|
169
|
+
#handleBlur = (event) => {
|
|
170
|
+
this.#settle();
|
|
171
|
+
this.#runAbandon();
|
|
172
|
+
const composition = this.#composition;
|
|
173
|
+
if (composition === null || composition.target === composition.element) return;
|
|
174
|
+
const { element } = composition;
|
|
175
|
+
if (!(element instanceof Node) || event.target !== element) return;
|
|
176
|
+
const root = element.getRootNode();
|
|
177
|
+
if (root.activeElement !== element) this.#composition = null;
|
|
178
|
+
};
|
|
179
|
+
#handleBeforeMorphAttribute = (event) => {
|
|
180
|
+
this.#settle();
|
|
181
|
+
const composition = this.#composition;
|
|
182
|
+
if (composition?.target !== event.currentTarget || event.target !== composition.element) return;
|
|
183
|
+
const detail = event.detail;
|
|
184
|
+
if (detail?.attributeName === "value") event.preventDefault();
|
|
81
185
|
};
|
|
82
186
|
};
|
|
83
187
|
|
|
84
|
-
// src/utils/half_width.ts
|
|
85
188
|
var FULL_WIDTH_SHIFT = 65248;
|
|
86
189
|
function halfWidthChar(char) {
|
|
87
190
|
if (char >= "\uFF01" && char <= "\uFF5E") {
|
|
@@ -90,7 +193,6 @@ function halfWidthChar(char) {
|
|
|
90
193
|
return char === "\u3000" ? " " : char;
|
|
91
194
|
}
|
|
92
195
|
|
|
93
|
-
// src/utils/intl_format.ts
|
|
94
196
|
var formatters = /* @__PURE__ */ new WeakMap();
|
|
95
197
|
function intlFormatter(factory, locale, options, fallbackLocale) {
|
|
96
198
|
const cache = cacheFor(factory);
|
|
@@ -120,65 +222,275 @@ function construct(factory, locale, options, fallbackLocale) {
|
|
|
120
222
|
}
|
|
121
223
|
}
|
|
122
224
|
|
|
123
|
-
|
|
225
|
+
var ListenerSet = class {
|
|
226
|
+
#abort = new AbortController();
|
|
227
|
+
add(target, type, handler, options) {
|
|
228
|
+
target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
|
|
229
|
+
}
|
|
230
|
+
dispose() {
|
|
231
|
+
this.#abort.abort();
|
|
232
|
+
this.#abort = new AbortController();
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
124
236
|
function resolveLocale(element, declared = "") {
|
|
125
237
|
return declared || element.closest("[lang]")?.getAttribute("lang") || void 0;
|
|
126
238
|
}
|
|
127
239
|
|
|
128
|
-
|
|
240
|
+
var MicrotaskCoalescer = class {
|
|
241
|
+
#run;
|
|
242
|
+
#queued = false;
|
|
243
|
+
#active = false;
|
|
244
|
+
#generation = 0;
|
|
245
|
+
constructor(run) {
|
|
246
|
+
this.#run = run;
|
|
247
|
+
}
|
|
248
|
+
activate() {
|
|
249
|
+
this.#active = true;
|
|
250
|
+
}
|
|
251
|
+
cancel() {
|
|
252
|
+
this.#active = false;
|
|
253
|
+
this.#queued = false;
|
|
254
|
+
this.#generation += 1;
|
|
255
|
+
}
|
|
256
|
+
get pending() {
|
|
257
|
+
return this.#queued;
|
|
258
|
+
}
|
|
259
|
+
schedule() {
|
|
260
|
+
if (!this.#active || this.#queued) return;
|
|
261
|
+
this.#queued = true;
|
|
262
|
+
const generation = this.#generation;
|
|
263
|
+
queueMicrotask(() => {
|
|
264
|
+
if (generation !== this.#generation || !this.#queued || !this.#active) return;
|
|
265
|
+
this.#queued = false;
|
|
266
|
+
this.#run();
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
var MorphRenderWatcher = class {
|
|
272
|
+
#listeners = new ListenerSet();
|
|
273
|
+
#pass;
|
|
274
|
+
#element = null;
|
|
275
|
+
#onMorph = () => this.#pass.schedule();
|
|
276
|
+
constructor(run) {
|
|
277
|
+
this.#pass = new MicrotaskCoalescer(run);
|
|
278
|
+
}
|
|
279
|
+
observe(element) {
|
|
280
|
+
if (this.#element === element) return;
|
|
281
|
+
this.disconnect();
|
|
282
|
+
this.#element = element;
|
|
283
|
+
this.#pass.activate();
|
|
284
|
+
this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
|
|
285
|
+
}
|
|
286
|
+
schedule() {
|
|
287
|
+
this.#pass.schedule();
|
|
288
|
+
}
|
|
289
|
+
get pending() {
|
|
290
|
+
return this.#pass.pending;
|
|
291
|
+
}
|
|
292
|
+
disconnect() {
|
|
293
|
+
this.#listeners.dispose();
|
|
294
|
+
this.#pass.cancel();
|
|
295
|
+
this.#element = null;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
function matchesNumberBounds(value, bounds) {
|
|
300
|
+
if (!Number.isFinite(value)) {
|
|
301
|
+
const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
|
|
302
|
+
if (direction === null) return false;
|
|
303
|
+
if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
|
|
304
|
+
}
|
|
305
|
+
if (bounds.min !== void 0 && value < bounds.min) return false;
|
|
306
|
+
if (bounds.max !== void 0 && value > bounds.max) return false;
|
|
307
|
+
if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
|
|
308
|
+
if (bounds.integer && !Number.isInteger(value)) return false;
|
|
309
|
+
if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function readNumber(raw, fallback, bounds) {
|
|
314
|
+
return matchesNumberBounds(raw, bounds) ? raw : fallback;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
var NumberValueReader = class {
|
|
318
|
+
#lastRejected = /* @__PURE__ */ new Map();
|
|
319
|
+
read(owner, name, raw, fallback, bounds) {
|
|
320
|
+
const resolved = readNumber(raw, fallback, bounds);
|
|
321
|
+
if (matchesNumberBounds(raw, bounds)) {
|
|
322
|
+
this.#lastRejected.delete(name);
|
|
323
|
+
return resolved;
|
|
324
|
+
}
|
|
325
|
+
const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
|
|
326
|
+
const literal = owner.element.getAttribute(attribute);
|
|
327
|
+
if (literal === null) {
|
|
328
|
+
this.#lastRejected.delete(name);
|
|
329
|
+
return resolved;
|
|
330
|
+
}
|
|
331
|
+
if (this.#lastRejected.get(name) !== literal) {
|
|
332
|
+
this.#lastRejected.set(name, literal);
|
|
333
|
+
console.warn(
|
|
334
|
+
`Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
return resolved;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
function setAttributeIfChanged(element, name, value, beforeWrite) {
|
|
342
|
+
if (element.getAttribute(name) === value) return false;
|
|
343
|
+
if (value === null) element.removeAttribute(name);
|
|
344
|
+
else element.setAttribute(name, value);
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
var OwnedText = class {
|
|
349
|
+
#attribute;
|
|
350
|
+
#channel;
|
|
351
|
+
#guard;
|
|
352
|
+
#writes = /* @__PURE__ */ new WeakMap();
|
|
353
|
+
constructor(attribute, channel = "text", guard = () => true) {
|
|
354
|
+
this.#attribute = attribute;
|
|
355
|
+
this.#channel = channel;
|
|
356
|
+
this.#guard = guard;
|
|
357
|
+
}
|
|
358
|
+
hasRecord(element) {
|
|
359
|
+
return element.hasAttribute(this.#attribute);
|
|
360
|
+
}
|
|
361
|
+
read(element, evidence = {}) {
|
|
362
|
+
if (evidence.source === "live") return this.#writes.get(element) ?? null;
|
|
363
|
+
const raw = element.getAttribute(this.#attribute);
|
|
364
|
+
if (raw === null) return null;
|
|
365
|
+
try {
|
|
366
|
+
const record = JSON.parse(raw);
|
|
367
|
+
if (!Array.isArray(record) || record.length !== 3 || record[0] !== this.#channel || typeof record[1] !== "string" || typeof record[2] !== "string")
|
|
368
|
+
return null;
|
|
369
|
+
return { original: record[1], written: record[2] };
|
|
370
|
+
} catch {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
owns(element, evidence = {}) {
|
|
375
|
+
return this.#ownedRecord(element, evidence) !== null;
|
|
376
|
+
}
|
|
377
|
+
#ownedRecord(element, evidence) {
|
|
378
|
+
const record = this.read(element, evidence);
|
|
379
|
+
if (record === null || !this.#guard(element)) return null;
|
|
380
|
+
if (this.#channel === "text" && element.firstElementChild !== null) return null;
|
|
381
|
+
const current = this.#current(element);
|
|
382
|
+
return current === record.written || evidence.source === "live" && evidence.allowOriginal === true && current === record.original ? record : null;
|
|
383
|
+
}
|
|
384
|
+
write(element, written, original, force = false) {
|
|
385
|
+
const current = this.#current(element);
|
|
386
|
+
if (current === null) return;
|
|
387
|
+
const before = original ?? this.#writes.get(element)?.original ?? this.read(element)?.original ?? current;
|
|
388
|
+
if (force || current !== written) this.#put(element, written);
|
|
389
|
+
this.remember(element, written, before);
|
|
390
|
+
}
|
|
391
|
+
remember(element, written, original) {
|
|
392
|
+
const current = this.#current(element);
|
|
393
|
+
if (current === null) return;
|
|
394
|
+
const before = original ?? this.#writes.get(element)?.original ?? this.read(element)?.original ?? current;
|
|
395
|
+
this.#writes.set(element, { original: before, written });
|
|
396
|
+
setAttributeIfChanged(
|
|
397
|
+
element,
|
|
398
|
+
this.#attribute,
|
|
399
|
+
JSON.stringify([this.#channel, before, written])
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
clear(element, evidence = {}) {
|
|
403
|
+
if (!this.owns(element, evidence)) return false;
|
|
404
|
+
if (this.#current(element) !== "") this.#put(element, "");
|
|
405
|
+
this.forget(element);
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
restore(element, evidence = {}) {
|
|
409
|
+
const record = this.#ownedRecord(element, evidence);
|
|
410
|
+
if (record === null) return false;
|
|
411
|
+
if (this.#current(element) !== record.original) this.#put(element, record.original);
|
|
412
|
+
this.forget(element);
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
forget(element) {
|
|
416
|
+
setAttributeIfChanged(element, this.#attribute, null);
|
|
417
|
+
this.#writes.delete(element);
|
|
418
|
+
}
|
|
419
|
+
#current(element) {
|
|
420
|
+
if (this.#channel === "text") return element.textContent ?? "";
|
|
421
|
+
return element instanceof HTMLInputElement ? element.value : null;
|
|
422
|
+
}
|
|
423
|
+
#put(element, text) {
|
|
424
|
+
if (this.#channel === "text") element.textContent = text;
|
|
425
|
+
else if (element instanceof HTMLInputElement) element.value = text;
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
|
|
129
429
|
var FALLBACK_LOCALE = "en-US";
|
|
130
|
-
var CurrencyInputController = class extends Controller {
|
|
430
|
+
var CurrencyInputController = class _CurrencyInputController extends Controller {
|
|
431
|
+
#numbers = new NumberValueReader();
|
|
131
432
|
static targets = ["display", "field", "srValue"];
|
|
132
433
|
static values = {
|
|
133
434
|
locale: { type: String, default: "" },
|
|
134
435
|
currency: { type: String, default: "" },
|
|
135
436
|
precision: { type: Number, default: 2 }
|
|
136
437
|
};
|
|
438
|
+
static valueConstraints = {
|
|
439
|
+
precision: { finite: true, integer: true, min: 0, max: 100 }
|
|
440
|
+
};
|
|
137
441
|
static actions = ["format", "onInput"];
|
|
138
442
|
static events = ["change", "reconcile"];
|
|
139
|
-
/** The numeric value last committed; both events report only a move away from it. */
|
|
140
443
|
#lastValue = null;
|
|
141
444
|
#started = false;
|
|
142
|
-
|
|
143
|
-
#
|
|
144
|
-
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
#
|
|
151
|
-
|
|
445
|
+
#unsettled = null;
|
|
446
|
+
#configured = false;
|
|
447
|
+
#listeners = new ListenerSet();
|
|
448
|
+
#declarationsHeld = false;
|
|
449
|
+
#displayText = new OwnedText(
|
|
450
|
+
`data-${this.identifier}-display-text`,
|
|
451
|
+
"value"
|
|
452
|
+
);
|
|
453
|
+
#renderedDisplay = null;
|
|
454
|
+
#departed = null;
|
|
455
|
+
#formatHeld = null;
|
|
152
456
|
#locale;
|
|
153
457
|
#currency = "";
|
|
154
458
|
#precision = 2;
|
|
155
|
-
/** Formatters rebuilt when the declarations are taken in, never per keystroke. */
|
|
156
459
|
#grouping;
|
|
157
460
|
#fixed;
|
|
158
461
|
#accessible;
|
|
159
462
|
#group = ",";
|
|
160
463
|
#decimal = ".";
|
|
161
|
-
/** The locale's non-Latin digits mapped back to ASCII (empty for Latin locales). */
|
|
162
464
|
#digits = /* @__PURE__ */ new Map();
|
|
163
|
-
/**
|
|
164
|
-
* Holds mid-composition input so the IME's uncommitted text is never rewritten.
|
|
165
|
-
* The confirmed text is formatted once, and a declaration change the composition
|
|
166
|
-
* held back is applied after it.
|
|
167
|
-
*/
|
|
168
465
|
#composition = new CompositionTracker({
|
|
169
|
-
|
|
170
|
-
|
|
466
|
+
onEnd: (event) => {
|
|
467
|
+
const display = event.currentTarget;
|
|
468
|
+
if (this.#unsettled === display) this.#unsettled = null;
|
|
469
|
+
const round2 = this.#takeFormatHeld(display);
|
|
470
|
+
if (this.#inCharge(display)) this.#reformat(round2, "edit");
|
|
471
|
+
if (this.#owed(display)) this.#applyValueChange();
|
|
472
|
+
if (round2 && !this.#inCharge(display)) this.#reformat(true, "edit");
|
|
473
|
+
},
|
|
474
|
+
onAbandon: (display, inPlace) => {
|
|
475
|
+
const next = this.#composition.composingElement();
|
|
476
|
+
if (inPlace && next !== null && next !== display) {
|
|
477
|
+
this.#endUntrackedComposition(display);
|
|
478
|
+
} else {
|
|
479
|
+
this.#formatHeld = null;
|
|
480
|
+
}
|
|
481
|
+
if (next === display && inPlace || !this.#owed(display)) return;
|
|
482
|
+
if (next !== null) {
|
|
483
|
+
this.#readPageText(next);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
if (inPlace) this.#endUntrackedComposition(display);
|
|
487
|
+
if (this.#owed(display)) this.#applyValueChange();
|
|
171
488
|
},
|
|
172
|
-
|
|
173
|
-
this.#
|
|
174
|
-
this.#
|
|
175
|
-
this.#applyHeldChange();
|
|
489
|
+
onStart: (event) => {
|
|
490
|
+
if (this.#unsettled === event.target) this.#unsettled = null;
|
|
491
|
+
if (this.#formatHeld?.heard === false) this.#formatHeld = null;
|
|
176
492
|
}
|
|
177
493
|
});
|
|
178
|
-
/**
|
|
179
|
-
* Re-validates on declaration changes and re-renders the committed display,
|
|
180
|
-
* reporting a value the re-render moved as `reconcile`.
|
|
181
|
-
*/
|
|
182
494
|
localeValueChanged() {
|
|
183
495
|
this.#applyValueChange();
|
|
184
496
|
}
|
|
@@ -188,73 +500,57 @@ var CurrencyInputController = class extends Controller {
|
|
|
188
500
|
precisionValueChanged() {
|
|
189
501
|
this.#applyValueChange();
|
|
190
502
|
}
|
|
191
|
-
/**
|
|
192
|
-
* Reads the display with the declarations its text was written for, then
|
|
193
|
-
* re-renders it under the new ones — so a locale switch re-interprets the
|
|
194
|
-
* value, never the old text with new separators, and text the page wrote for
|
|
195
|
-
* the declarations it changes is never read with the old ones.
|
|
196
|
-
*
|
|
197
|
-
* While the display is composing, its text is the IME's: the change is held,
|
|
198
|
-
* configuration and all, until the composition ends, so the confirmed text is
|
|
199
|
-
* read with the separators it was typed against before the change applies.
|
|
200
|
-
*
|
|
201
|
-
* @stimeoRenderRoot
|
|
202
|
-
*/
|
|
203
503
|
#applyValueChange() {
|
|
504
|
+
if (!this.#started) return;
|
|
505
|
+
if (this.#holdUnsettled(false)) return;
|
|
204
506
|
if (this.#composition.isComposing()) {
|
|
205
|
-
this.#
|
|
507
|
+
this.#declarationsHeld = this.#declarationsChanged();
|
|
508
|
+
this.#resync();
|
|
206
509
|
return;
|
|
207
510
|
}
|
|
208
|
-
if (!this
|
|
209
|
-
const scan = this.#readDisplay();
|
|
511
|
+
if (!this.hasDisplayTarget) return;
|
|
512
|
+
const { scan, anchor } = this.#readDisplay();
|
|
210
513
|
if (document.activeElement === this.displayTarget) {
|
|
211
514
|
const formatted = this.#render(scan.parts);
|
|
212
|
-
this.#
|
|
515
|
+
this.#showAtCaret(formatted, anchor);
|
|
213
516
|
this.#reflect(scan.value, formatted, "reconcile");
|
|
214
517
|
} else {
|
|
215
518
|
this.#renderFixed(scan.value, "reconcile");
|
|
216
519
|
}
|
|
217
520
|
}
|
|
218
|
-
/** Applies a declaration change a composition held back. */
|
|
219
|
-
#applyHeldChange() {
|
|
220
|
-
if (!this.#changeHeld) return;
|
|
221
|
-
this.#changeHeld = false;
|
|
222
|
-
this.#applyValueChange();
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Reads the display and takes in the declarations the page carries now. This
|
|
226
|
-
* controller's own rendering was written with the separators in force, so it
|
|
227
|
-
* is read before they change; any other text is the page's, written for the
|
|
228
|
-
* declarations it carries, so it is read after.
|
|
229
|
-
*/
|
|
230
521
|
#readDisplay() {
|
|
231
522
|
const text = this.displayTarget.value;
|
|
232
|
-
const own =
|
|
233
|
-
this.#takeInDeclarations();
|
|
234
|
-
return own ?? this.#scan(text);
|
|
235
|
-
}
|
|
236
|
-
/** Takes in the declarations the page carries now, a change a composition held among them. */
|
|
237
|
-
#takeInDeclarations() {
|
|
238
|
-
this.#changeHeld = false;
|
|
523
|
+
const own = this.#showsOwnRendering(this.displayTarget) ? this.#read(text) : null;
|
|
239
524
|
this.#revalidate();
|
|
525
|
+
return own ?? this.#read(text);
|
|
240
526
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
527
|
+
#showsOwnRendering(display) {
|
|
528
|
+
return display === this.#renderedDisplay && this.#displayText.owns(display, { source: "live" });
|
|
529
|
+
}
|
|
530
|
+
#inCharge(source) {
|
|
531
|
+
return source === null || this.hasDisplayTarget && source === this.displayTarget;
|
|
532
|
+
}
|
|
533
|
+
#read(text) {
|
|
534
|
+
return {
|
|
535
|
+
scan: this.#scan(text),
|
|
536
|
+
anchor: this.#significantBefore(text, this.displayTarget.selectionStart)
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
#morph = new MorphRenderWatcher(() => this.#applyValueChange());
|
|
253
540
|
connect() {
|
|
541
|
+
this.#morph.observe(this.element);
|
|
542
|
+
this.#listeners.add(this.element, "turbo:before-morph-attribute", this.#protectUnsettled);
|
|
254
543
|
this.#started = true;
|
|
255
|
-
this.#
|
|
544
|
+
if (!this.#configured) this.#revalidate();
|
|
545
|
+
if (this.#composition.isComposing()) {
|
|
546
|
+
this.#applyValueChange();
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
this.#formatHeld = null;
|
|
550
|
+
if (this.#holdUnsettled(true)) return;
|
|
551
|
+
this.#revalidate();
|
|
256
552
|
if (!this.hasDisplayTarget) return;
|
|
257
|
-
if (this.displayTarget
|
|
553
|
+
if (this.#showsOwnRendering(this.displayTarget)) {
|
|
258
554
|
this.#renderFixed(this.#lastValue, "reconcile");
|
|
259
555
|
return;
|
|
260
556
|
}
|
|
@@ -262,75 +558,112 @@ var CurrencyInputController = class extends Controller {
|
|
|
262
558
|
this.#lastValue = value === null ? null : round(value, this.#precision);
|
|
263
559
|
this.#renderFixed(value, "reconcile");
|
|
264
560
|
}
|
|
265
|
-
/**
|
|
266
|
-
* Releases the composition listeners. A composition still running hears no
|
|
267
|
-
* `compositionend` once they are gone, so it ends here; a change it held is
|
|
268
|
-
* taken in on the next `connect()`.
|
|
269
|
-
*/
|
|
270
561
|
disconnect() {
|
|
271
|
-
this.#
|
|
562
|
+
this.#morph.disconnect();
|
|
563
|
+
this.#listeners.dispose();
|
|
564
|
+
const composing = this.#composition.composingElement();
|
|
272
565
|
this.#composition.disconnect();
|
|
566
|
+
if (this.#composition.composingElement() !== composing) {
|
|
567
|
+
this.#endUntrackedComposition(composing);
|
|
568
|
+
}
|
|
273
569
|
this.#started = false;
|
|
274
570
|
}
|
|
275
|
-
/**
|
|
276
|
-
* Tracks composition on an arriving (or swapped-in) display and normalizes it
|
|
277
|
-
* under the declarations the page carries now, reading this controller's own
|
|
278
|
-
* rendering with the separators it was written under; an amount that differs
|
|
279
|
-
* from the committed one is the page's, so it is reported as `reconcile`.
|
|
280
|
-
*/
|
|
281
571
|
displayTargetConnected(target) {
|
|
282
572
|
this.#composition.observe(target);
|
|
283
|
-
if (!this.#started) return;
|
|
284
|
-
this.#
|
|
573
|
+
if (!this.#started || !this.hasDisplayTarget || this.displayTarget !== target) return;
|
|
574
|
+
this.#applyValueChange();
|
|
285
575
|
}
|
|
286
|
-
/**
|
|
287
|
-
* Stops tracking a display that leaves. A composition running on it hears no
|
|
288
|
-
* `compositionend` any more, so it ends here; a change it held waits for the
|
|
289
|
-
* next display to be read.
|
|
290
|
-
*/
|
|
291
576
|
displayTargetDisconnected(target) {
|
|
577
|
+
if (target === this.#renderedDisplay && !(this.#started && this.hasDisplayTarget && this.displayTarget === target)) {
|
|
578
|
+
this.#departed = target;
|
|
579
|
+
}
|
|
580
|
+
const composing = this.#composition.composingElement() === target;
|
|
292
581
|
this.#composition.unobserve(target);
|
|
293
|
-
this.#
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
#endUntrackedComposition() {
|
|
304
|
-
const display = this.#composing;
|
|
305
|
-
this.#composing = null;
|
|
582
|
+
if (composing && this.#composition.composingElement() !== target) {
|
|
583
|
+
this.#endUntrackedComposition(target);
|
|
584
|
+
}
|
|
585
|
+
if (this.#formatHeld?.display === target && this.#composition.composingElement() !== target) {
|
|
586
|
+
this.#formatHeld = null;
|
|
587
|
+
}
|
|
588
|
+
this.#applyValueChange();
|
|
589
|
+
}
|
|
590
|
+
#endUntrackedComposition(display) {
|
|
591
|
+
const round2 = this.#takeFormatHeld(display);
|
|
306
592
|
if (this.hasDisplayTarget && this.displayTarget === display) {
|
|
307
|
-
this.#reformat(
|
|
593
|
+
this.#reformat(round2, "reconcile");
|
|
308
594
|
}
|
|
309
595
|
}
|
|
310
|
-
/** Syncs a late-arriving hidden field without touching the display or events. */
|
|
311
596
|
fieldTargetConnected() {
|
|
312
597
|
if (this.#started) this.#resync();
|
|
313
598
|
}
|
|
314
|
-
|
|
599
|
+
fieldTargetDisconnected() {
|
|
600
|
+
if (this.#started) this.#resync();
|
|
601
|
+
}
|
|
315
602
|
srValueTargetConnected() {
|
|
316
603
|
if (this.#started) this.#resync();
|
|
317
604
|
}
|
|
318
|
-
|
|
605
|
+
srValueTargetDisconnected() {
|
|
606
|
+
if (this.#started) this.#resync();
|
|
607
|
+
}
|
|
319
608
|
onInput(event) {
|
|
320
|
-
|
|
609
|
+
const source = event?.target ?? null;
|
|
610
|
+
if (!this.#inCharge(source)) return;
|
|
611
|
+
this.#holdUnsettled(false);
|
|
612
|
+
if (event && this.#composition.consumesConfirmedInput(event)) return;
|
|
613
|
+
const input = event;
|
|
614
|
+
if (this.#composition.isComposing(input) || isCompositionInputType(input?.inputType)) {
|
|
615
|
+
if (this.#composition.composingElement() === null && this.hasDisplayTarget) {
|
|
616
|
+
this.#beginUnsettled(this.displayTarget);
|
|
617
|
+
}
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
const unsettled = this.#unsettled !== null;
|
|
621
|
+
if (unsettled) {
|
|
622
|
+
if (source !== this.#unsettled || input?.isComposing !== false || !input.inputType) return;
|
|
623
|
+
this.#unsettled = null;
|
|
624
|
+
this.#formatHeld = null;
|
|
625
|
+
}
|
|
321
626
|
this.#reformat(false, "edit");
|
|
627
|
+
if (unsettled && this.#owed(source)) this.#applyValueChange();
|
|
628
|
+
}
|
|
629
|
+
format(event) {
|
|
630
|
+
if (!this.#inCharge(event?.target ?? null)) return;
|
|
631
|
+
const returned = this.hasDisplayTarget && this.displayTarget === this.#departed;
|
|
632
|
+
this.#holdUnsettled(false);
|
|
633
|
+
if (this.hasDisplayTarget && (this.displayTarget !== this.#renderedDisplay || returned && !this.#showsOwnRendering(this.displayTarget)) && (event?.type === "blur" || event?.type === "focusout") && this.#composition.composingElement() !== this.displayTarget) {
|
|
634
|
+
this.#beginUnsettled(this.displayTarget);
|
|
635
|
+
}
|
|
636
|
+
if (this.#unsettled !== null) {
|
|
637
|
+
this.#formatHeld = { display: this.#unsettled, heard: false };
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
if (this.#composition.isComposing(event)) {
|
|
641
|
+
const composing = this.#composition.composingElement();
|
|
642
|
+
const display = composing ?? event?.target ?? (this.hasDisplayTarget ? this.displayTarget : null);
|
|
643
|
+
this.#formatHeld = display === null ? null : { display, heard: composing !== null };
|
|
644
|
+
if (composing === null && this.hasDisplayTarget && display === this.displayTarget) {
|
|
645
|
+
this.#beginUnsettled(this.displayTarget);
|
|
646
|
+
}
|
|
647
|
+
} else {
|
|
648
|
+
this.#formatHeld = null;
|
|
649
|
+
this.#reformat(true, "edit");
|
|
650
|
+
}
|
|
322
651
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
this.#
|
|
652
|
+
#takeFormatHeld(display) {
|
|
653
|
+
const held = this.#formatHeld;
|
|
654
|
+
this.#formatHeld = null;
|
|
655
|
+
return held !== null && held.display === display;
|
|
656
|
+
}
|
|
657
|
+
#readPageText(composing) {
|
|
658
|
+
if (this.#unsettled !== null || !this.#inCharge(composing) || this.#showsOwnRendering(this.displayTarget))
|
|
659
|
+
return;
|
|
660
|
+
const { scan } = this.#readDisplay();
|
|
661
|
+
this.#displayText.remember(this.displayTarget, this.displayTarget.value);
|
|
662
|
+
this.#renderedDisplay = this.displayTarget;
|
|
663
|
+
this.#reflect(scan.value, this.#render(scan.parts), "reconcile");
|
|
326
664
|
}
|
|
327
|
-
/**
|
|
328
|
-
* Parses the display value, rewrites it grouped (optionally at fixed
|
|
329
|
-
* precision), keeps the caret stable by significant characters, and syncs the
|
|
330
|
-
* field, the screen-reader span, and the event `cause` selects.
|
|
331
|
-
*/
|
|
332
665
|
#reformat(fixedPrecision, cause) {
|
|
333
|
-
if (!this.hasDisplayTarget) return;
|
|
666
|
+
if (!this.hasDisplayTarget || this.#unsettled === this.displayTarget) return;
|
|
334
667
|
const raw = this.displayTarget.value;
|
|
335
668
|
const { parts, value } = this.#scan(raw);
|
|
336
669
|
if (fixedPrecision) {
|
|
@@ -338,19 +671,17 @@ var CurrencyInputController = class extends Controller {
|
|
|
338
671
|
return;
|
|
339
672
|
}
|
|
340
673
|
const formatted = this.#render(parts);
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
674
|
+
this.#showAtCaret(formatted, this.#significantBefore(raw, this.displayTarget.selectionStart));
|
|
675
|
+
this.#reflect(value, formatted, cause);
|
|
676
|
+
}
|
|
677
|
+
#showAtCaret(formatted, anchor) {
|
|
678
|
+
if (formatted !== this.displayTarget.value) {
|
|
344
679
|
this.displayTarget.value = formatted;
|
|
345
680
|
if (anchor !== null) this.#restoreCaret(formatted, anchor);
|
|
346
681
|
}
|
|
347
|
-
this.#
|
|
348
|
-
this.#
|
|
682
|
+
this.#displayText.remember(this.displayTarget, formatted);
|
|
683
|
+
this.#renderedDisplay = this.displayTarget;
|
|
349
684
|
}
|
|
350
|
-
/**
|
|
351
|
-
* Shows `value` at the fixed precision — an empty display for no value — and
|
|
352
|
-
* reports a move under the event `cause` selects.
|
|
353
|
-
*/
|
|
354
685
|
#renderFixed(value, cause) {
|
|
355
686
|
if (value === null) {
|
|
356
687
|
this.#show("");
|
|
@@ -362,20 +693,15 @@ var CurrencyInputController = class extends Controller {
|
|
|
362
693
|
this.#show(formatted);
|
|
363
694
|
this.#reflect(rounded, formatted, cause);
|
|
364
695
|
}
|
|
365
|
-
/** Writes `text` to the display as this controller's own rendering. */
|
|
366
696
|
#show(text) {
|
|
367
|
-
this.displayTarget
|
|
368
|
-
this.#
|
|
697
|
+
this.#displayText.write(this.displayTarget, text);
|
|
698
|
+
this.#renderedDisplay = this.displayTarget;
|
|
369
699
|
}
|
|
370
|
-
/**
|
|
371
|
-
* The in-progress rendering: grouped integer, sign and fraction as typed.
|
|
372
|
-
*/
|
|
373
700
|
#render(parts) {
|
|
374
701
|
const int = parts.int === "" ? "" : this.#grouping.format(BigInt(parts.int));
|
|
375
702
|
const frac = parts.hasDot ? this.#decimal + parts.frac : "";
|
|
376
703
|
return parts.sign + int + frac;
|
|
377
704
|
}
|
|
378
|
-
/** Restores the caret to sit just after the n-th significant character. */
|
|
379
705
|
#restoreCaret(formatted, significantBefore) {
|
|
380
706
|
let seen = 0;
|
|
381
707
|
let position = formatted.length;
|
|
@@ -391,12 +717,8 @@ var CurrencyInputController = class extends Controller {
|
|
|
391
717
|
} catch {
|
|
392
718
|
}
|
|
393
719
|
}
|
|
394
|
-
/**
|
|
395
|
-
* Counts the characters before `caret` that survive into the rendering,
|
|
396
|
-
* applying the same acceptance rules as {@link #scan} — a rejected keystroke
|
|
397
|
-
* (a mid-string sign, a second decimal mark) must not shift the anchor.
|
|
398
|
-
*/
|
|
399
720
|
#significantBefore(text, caret) {
|
|
721
|
+
if (caret === null) return null;
|
|
400
722
|
let count = 0;
|
|
401
723
|
let sawSign = false;
|
|
402
724
|
let sawDigit = false;
|
|
@@ -415,13 +737,11 @@ var CurrencyInputController = class extends Controller {
|
|
|
415
737
|
}
|
|
416
738
|
return count;
|
|
417
739
|
}
|
|
418
|
-
/** Digits, signs, and the decimal mark anchor the caret; grouping does not. */
|
|
419
740
|
#isSignificant(ch) {
|
|
420
741
|
if (ch >= "0" && ch <= "9") return true;
|
|
421
742
|
if (ch === "-" || ch === "+") return true;
|
|
422
743
|
return ch === this.#decimal || ch === "." && this.#group !== ".";
|
|
423
744
|
}
|
|
424
|
-
/** Writes the normalized value to the field, the SR span, and the empty hook. */
|
|
425
745
|
#write(value) {
|
|
426
746
|
const isEmpty = value === null;
|
|
427
747
|
if (this.hasFieldTarget) this.fieldTarget.value = isEmpty ? "" : String(value);
|
|
@@ -430,13 +750,6 @@ var CurrencyInputController = class extends Controller {
|
|
|
430
750
|
}
|
|
431
751
|
this.element.toggleAttribute(`data-${this.identifier}-empty`, isEmpty);
|
|
432
752
|
}
|
|
433
|
-
/**
|
|
434
|
-
* {@link #write}, then reports a moved value under the event `cause` selects:
|
|
435
|
-
* `change` for the user's edit, `reconcile` for a move the page caused. The
|
|
436
|
-
* display may hold an in-progress `-`, but a `null` value always rides with an
|
|
437
|
-
* empty `formatted`, whichever event reports it, so consumers can treat the
|
|
438
|
-
* pair as cleared.
|
|
439
|
-
*/
|
|
440
753
|
#reflect(value, formatted, cause) {
|
|
441
754
|
this.#write(value);
|
|
442
755
|
if (value === this.#lastValue) return;
|
|
@@ -445,13 +758,6 @@ var CurrencyInputController = class extends Controller {
|
|
|
445
758
|
if (cause === "edit") this.dispatch("change", { detail });
|
|
446
759
|
else this.dispatch("reconcile", { detail });
|
|
447
760
|
}
|
|
448
|
-
/**
|
|
449
|
-
* Scans arbitrary input text into its number-shaped parts and value. Keeps
|
|
450
|
-
* digits, one leading sign, one decimal mark, and the fraction verbatim;
|
|
451
|
-
* everything else (grouping, symbols, words) is dropped. An ASCII "." is only
|
|
452
|
-
* a decimal mark where it is not the locale's grouping separator. Precision
|
|
453
|
-
* plays no part here — rounding belongs to the blur-time format.
|
|
454
|
-
*/
|
|
455
761
|
#scan(text) {
|
|
456
762
|
let sign = "";
|
|
457
763
|
let int = "";
|
|
@@ -471,40 +777,82 @@ var CurrencyInputController = class extends Controller {
|
|
|
471
777
|
const value = Number(`${sign}${int}.${frac}`);
|
|
472
778
|
return { parts, value: Number.isFinite(value) ? value : null };
|
|
473
779
|
}
|
|
474
|
-
/** Whether `ch` reads as this locale's decimal mark. */
|
|
475
780
|
#isDecimalMark(ch) {
|
|
476
781
|
return ch === this.#decimal || ch === "." && this.#group !== ".";
|
|
477
782
|
}
|
|
478
|
-
/**
|
|
479
|
-
* Re-syncs field / srValue / hook without dispatching: from the display, or —
|
|
480
|
-
* while it is composing, when its text is not committed yet — from the value
|
|
481
|
-
* last committed.
|
|
482
|
-
*/
|
|
483
783
|
#resync() {
|
|
484
784
|
if (!this.hasDisplayTarget) return;
|
|
485
|
-
const
|
|
785
|
+
const unsettled = this.#trackUnsettled(false);
|
|
786
|
+
if (this.#renderedDisplay === null) return;
|
|
787
|
+
const value = unsettled || this.#composition.isComposing() ? this.#lastValue : this.#scan(this.displayTarget.value).value;
|
|
486
788
|
this.#write(value);
|
|
487
789
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
#
|
|
790
|
+
#holdUnsettled(arriving) {
|
|
791
|
+
if (!this.#trackUnsettled(arriving)) return false;
|
|
792
|
+
this.#declarationsHeld = this.#declarationsChanged();
|
|
793
|
+
this.#resync();
|
|
794
|
+
return true;
|
|
795
|
+
}
|
|
796
|
+
#trackUnsettled(arriving) {
|
|
797
|
+
this.#forgetUnsettledOwner();
|
|
798
|
+
if (!this.hasDisplayTarget) return false;
|
|
799
|
+
const display = this.displayTarget;
|
|
800
|
+
const returned = display === this.#departed;
|
|
801
|
+
if (returned) this.#departed = null;
|
|
802
|
+
if (this.#unsettled === null && document.activeElement === display && (arriving || display !== this.#renderedDisplay || returned && !this.#showsOwnRendering(display)) && this.#composition.composingElement() !== display) {
|
|
803
|
+
this.#beginUnsettled(display);
|
|
804
|
+
}
|
|
805
|
+
return this.#unsettled !== null;
|
|
806
|
+
}
|
|
807
|
+
#beginUnsettled(display) {
|
|
808
|
+
if (this.#unsettled === null && this.#renderedDisplay === null && this.#declarationsChanged()) {
|
|
809
|
+
this.#revalidate();
|
|
810
|
+
}
|
|
811
|
+
this.#unsettled = display;
|
|
812
|
+
}
|
|
813
|
+
#forgetUnsettledOwner() {
|
|
814
|
+
if (this.#unsettled !== null && this.hasDisplayTarget && this.#unsettled !== this.displayTarget) {
|
|
815
|
+
if (this.#formatHeld?.display === this.#unsettled) this.#formatHeld = null;
|
|
816
|
+
this.#unsettled = null;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
#protectUnsettled = (event) => {
|
|
820
|
+
this.#holdUnsettled(false);
|
|
821
|
+
if (this.#unsettled === null || event.target !== this.#unsettled) return;
|
|
822
|
+
const detail = event.detail;
|
|
823
|
+
if (detail?.attributeName === "value") event.preventDefault();
|
|
824
|
+
};
|
|
825
|
+
#declared() {
|
|
495
826
|
const resolved = resolveLocale(this.element, this.localeValue);
|
|
496
827
|
const usable = intlFormatter(Intl.NumberFormat, resolved, {});
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
this.#precision = Number.isInteger(precision) && precision >= 0 && precision <= 100 ? precision : 2;
|
|
500
|
-
this.#currency = "";
|
|
828
|
+
const locale = usable === null ? FALLBACK_LOCALE : resolved;
|
|
829
|
+
let currency = "";
|
|
501
830
|
if (this.currencyValue !== "") {
|
|
502
|
-
const declaredCurrency = intlFormatter(Intl.NumberFormat,
|
|
831
|
+
const declaredCurrency = intlFormatter(Intl.NumberFormat, locale, {
|
|
503
832
|
style: "currency",
|
|
504
833
|
currency: this.currencyValue
|
|
505
834
|
});
|
|
506
|
-
if (declaredCurrency !== null)
|
|
835
|
+
if (declaredCurrency !== null) currency = this.currencyValue;
|
|
507
836
|
}
|
|
837
|
+
return { locale, currency, precision: this.#safePrecision };
|
|
838
|
+
}
|
|
839
|
+
#owed(composed) {
|
|
840
|
+
if (this.#declarationsHeld) return true;
|
|
841
|
+
if (!this.hasDisplayTarget) return false;
|
|
842
|
+
const display = this.displayTarget;
|
|
843
|
+
return display !== this.#renderedDisplay || display !== composed && !this.#showsOwnRendering(display);
|
|
844
|
+
}
|
|
845
|
+
#declarationsChanged() {
|
|
846
|
+
const { locale, currency, precision } = this.#declared();
|
|
847
|
+
return locale !== this.#locale || currency !== this.#currency || precision !== this.#precision;
|
|
848
|
+
}
|
|
849
|
+
#revalidate() {
|
|
850
|
+
this.#configured = true;
|
|
851
|
+
this.#declarationsHeld = false;
|
|
852
|
+
const declared = this.#declared();
|
|
853
|
+
this.#locale = declared.locale;
|
|
854
|
+
this.#currency = declared.currency;
|
|
855
|
+
this.#precision = declared.precision;
|
|
508
856
|
this.#grouping = intlFormatter(
|
|
509
857
|
Intl.NumberFormat,
|
|
510
858
|
this.#locale,
|
|
@@ -544,12 +892,6 @@ var CurrencyInputController = class extends Controller {
|
|
|
544
892
|
if (digit !== String(i)) this.#digits.set(digit, String(i));
|
|
545
893
|
}
|
|
546
894
|
}
|
|
547
|
-
/**
|
|
548
|
-
* Maps the locale's own digits to ASCII, folds full-width forms (the digits,
|
|
549
|
-
* signs, and marks an IME confirms as 0-9+-.,) through the shared
|
|
550
|
-
* half-width mapping, and reads U+2212 MINUS SIGN as "-", which some locales'
|
|
551
|
-
* formatted output uses for negatives.
|
|
552
|
-
*/
|
|
553
895
|
#normalize(text) {
|
|
554
896
|
let out = "";
|
|
555
897
|
for (const ch of text) {
|
|
@@ -564,6 +906,15 @@ var CurrencyInputController = class extends Controller {
|
|
|
564
906
|
}
|
|
565
907
|
return out;
|
|
566
908
|
}
|
|
909
|
+
get #safePrecision() {
|
|
910
|
+
return this.#numbers.read(
|
|
911
|
+
this,
|
|
912
|
+
"precision",
|
|
913
|
+
this.precisionValue,
|
|
914
|
+
_CurrencyInputController.values.precision.default,
|
|
915
|
+
_CurrencyInputController.valueConstraints.precision
|
|
916
|
+
);
|
|
917
|
+
}
|
|
567
918
|
};
|
|
568
919
|
function round(value, precision) {
|
|
569
920
|
const factor = 10 ** Math.max(0, precision);
|
|
@@ -573,5 +924,4 @@ function round(value, precision) {
|
|
|
573
924
|
}
|
|
574
925
|
|
|
575
926
|
export { CurrencyInputController };
|
|
576
|
-
//# sourceMappingURL=currency_input_controller.js.map
|
|
577
927
|
//# sourceMappingURL=currency_input_controller.js.map
|