stimeo-ui 0.14.0 → 0.16.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 +212 -0
- package/README.md +120 -0
- package/dist/cable/index.js +123 -29
- package/dist/cable/index.js.map +1 -1
- package/dist/controllers/accordion_controller.d.ts +30 -3
- package/dist/controllers/accordion_controller.js +98 -9
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.d.ts +8 -7
- package/dist/controllers/alert_dialog_controller.js.map +1 -1
- package/dist/controllers/announcer_controller.d.ts +3 -2
- package/dist/controllers/announcer_controller.js +96 -62
- package/dist/controllers/announcer_controller.js.map +1 -1
- package/dist/controllers/auto_submit_controller.js +83 -7
- package/dist/controllers/auto_submit_controller.js.map +1 -1
- package/dist/controllers/avatar_controller.js +1 -1
- package/dist/controllers/avatar_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.d.ts +10 -7
- package/dist/controllers/breadcrumb_controller.js +38 -11
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/bulk_select_controller.d.ts +4 -4
- package/dist/controllers/bulk_select_controller.js +7 -6
- package/dist/controllers/bulk_select_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +101 -23
- package/dist/controllers/calendar_controller.js +340 -123
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +67 -22
- package/dist/controllers/carousel_controller.js +263 -38
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/character_counter_controller.d.ts +1 -1
- package/dist/controllers/character_counter_controller.js +40 -2
- package/dist/controllers/character_counter_controller.js.map +1 -1
- package/dist/controllers/checkbox_controller.js +81 -12
- package/dist/controllers/checkbox_controller.js.map +1 -1
- package/dist/controllers/clipboard_controller.d.ts +28 -2
- package/dist/controllers/clipboard_controller.js +63 -5
- package/dist/controllers/clipboard_controller.js.map +1 -1
- package/dist/controllers/collapsible_controller.d.ts +25 -1
- package/dist/controllers/collapsible_controller.js +99 -14
- package/dist/controllers/collapsible_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.d.ts +29 -8
- package/dist/controllers/color_picker_controller.js +80 -34
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.d.ts +10 -1
- package/dist/controllers/combobox_controller.js +106 -16
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +3 -3
- package/dist/controllers/command_palette_controller.js +35 -3
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/conditional_fields_controller.js +85 -17
- package/dist/controllers/conditional_fields_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.js +3 -0
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +6 -0
- package/dist/controllers/context_menu_controller.js +32 -12
- 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 +30 -1
- package/dist/controllers/countdown_controller.js +129 -26
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +77 -16
- package/dist/controllers/currency_input_controller.js +221 -67
- package/dist/controllers/currency_input_controller.js.map +1 -1
- package/dist/controllers/data_grid_controller.d.ts +63 -18
- package/dist/controllers/data_grid_controller.js +195 -29
- package/dist/controllers/data_grid_controller.js.map +1 -1
- package/dist/controllers/date_range_picker_controller.d.ts +41 -6
- package/dist/controllers/date_range_picker_controller.js +151 -30
- package/dist/controllers/date_range_picker_controller.js.map +1 -1
- package/dist/controllers/dialog_controller.d.ts +10 -3
- package/dist/controllers/dialog_controller.js +35 -8
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.js +22 -4
- package/dist/controllers/direct_upload_controller.js.map +1 -1
- package/dist/controllers/dirty_form_controller.d.ts +2 -2
- package/dist/controllers/dirty_form_controller.js +46 -13
- package/dist/controllers/dirty_form_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.js +1 -0
- package/dist/controllers/dismissible_controller.js.map +1 -1
- package/dist/controllers/drawer_controller.d.ts +18 -10
- package/dist/controllers/drawer_controller.js +54 -19
- package/dist/controllers/drawer_controller.js.map +1 -1
- package/dist/controllers/dropdown_controller.d.ts +9 -3
- package/dist/controllers/dropdown_controller.js +36 -9
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.js +34 -0
- package/dist/controllers/editable_controller.js.map +1 -1
- package/dist/controllers/file_dropzone_controller.js +144 -51
- package/dist/controllers/file_dropzone_controller.js.map +1 -1
- package/dist/controllers/filter_controller.d.ts +10 -4
- package/dist/controllers/filter_controller.js +20 -6
- package/dist/controllers/filter_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +26 -6
- package/dist/controllers/flash_controller.js +432 -71
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.js +1 -0
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.js +7 -5
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.js +19 -13
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.js +45 -8
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.js +82 -25
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +10 -2
- package/dist/controllers/hover_card_controller.js +40 -14
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +16 -3
- package/dist/controllers/idle_controller.js +90 -5
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/input_mask_controller.d.ts +5 -2
- package/dist/controllers/input_mask_controller.js +65 -9
- 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.js +11 -2
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +50 -8
- package/dist/controllers/listbox_controller.js +203 -45
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.js +10 -5
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.d.ts +3 -3
- package/dist/controllers/masonry_controller.js +31 -15
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/menu_controller.d.ts +9 -3
- package/dist/controllers/menu_controller.js +45 -16
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +11 -0
- package/dist/controllers/menubar_controller.js +58 -24
- package/dist/controllers/menubar_controller.js.map +1 -1
- package/dist/controllers/meter_controller.js +9 -5
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +18 -3
- package/dist/controllers/multi_select_controller.js +278 -104
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/navigation_menu_controller.d.ts +11 -0
- package/dist/controllers/navigation_menu_controller.js +48 -15
- package/dist/controllers/navigation_menu_controller.js.map +1 -1
- package/dist/controllers/nested_form_controller.js +37 -8
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/network_status_controller.js +9 -1
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +36 -8
- package/dist/controllers/number_input_controller.js +124 -21
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/optimistic_controller.js +42 -5
- package/dist/controllers/optimistic_controller.js.map +1 -1
- package/dist/controllers/otp_controller.d.ts +22 -7
- package/dist/controllers/otp_controller.js +198 -55
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.d.ts +8 -12
- package/dist/controllers/overflow_indicator_controller.js +115 -21
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +26 -6
- package/dist/controllers/overflow_menu_controller.js +141 -44
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +19 -11
- package/dist/controllers/pagination_controller.js +74 -28
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +15 -1
- package/dist/controllers/password_reveal_controller.js +59 -2
- package/dist/controllers/password_reveal_controller.js.map +1 -1
- package/dist/controllers/persist_controller.js +30 -8
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.js +131 -52
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +9 -3
- package/dist/controllers/popover_controller.js +45 -11
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +1 -1
- package/dist/controllers/portal_controller.js +6 -2
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/preview_guard_controller.js +16 -1
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/progress_controller.js +8 -4
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.d.ts +6 -4
- package/dist/controllers/radio_group_controller.js +42 -17
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +49 -1
- package/dist/controllers/range_slider_controller.js +88 -42
- package/dist/controllers/range_slider_controller.js.map +1 -1
- package/dist/controllers/rating_controller.d.ts +14 -3
- package/dist/controllers/rating_controller.js +39 -15
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.d.ts +24 -2
- package/dist/controllers/read_more_controller.js +100 -7
- package/dist/controllers/read_more_controller.js.map +1 -1
- package/dist/controllers/reading_progress_controller.js +65 -19
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/relative_time_controller.js +10 -5
- package/dist/controllers/relative_time_controller.js.map +1 -1
- package/dist/controllers/resizable_controller.d.ts +16 -2
- package/dist/controllers/resizable_controller.js +82 -22
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.js +75 -27
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_restore_controller.js +37 -16
- package/dist/controllers/scroll_restore_controller.js.map +1 -1
- package/dist/controllers/scroll_visibility_controller.js +49 -30
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.d.ts +3 -2
- package/dist/controllers/scrollspy_controller.js +71 -26
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +41 -14
- package/dist/controllers/separator_controller.js +66 -37
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/sidebar_controller.d.ts +20 -3
- package/dist/controllers/sidebar_controller.js +77 -18
- package/dist/controllers/sidebar_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.js +6 -1
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +45 -7
- package/dist/controllers/slider_controller.js +82 -47
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.js +60 -26
- package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.js +17 -2
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.js +10 -2
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +19 -17
- package/dist/controllers/step_indicator_controller.js +18 -17
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +34 -9
- package/dist/controllers/stepper_controller.js +101 -19
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +19 -0
- package/dist/controllers/stick_to_bottom_controller.js +104 -8
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +3 -2
- package/dist/controllers/submit_once_controller.js +45 -9
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +29 -7
- package/dist/controllers/switch_controller.js +101 -10
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +12 -0
- package/dist/controllers/tabs_controller.js +21 -2
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +15 -3
- package/dist/controllers/tags_input_controller.js +209 -59
- package/dist/controllers/tags_input_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.js +29 -3
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/theme_controller.d.ts +20 -3
- package/dist/controllers/theme_controller.js +64 -14
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.js +23 -8
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/toast_controller.d.ts +55 -15
- package/dist/controllers/toast_controller.js +451 -105
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.d.ts +49 -7
- package/dist/controllers/toggle_group_controller.js +159 -23
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.js +32 -0
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +8 -0
- package/dist/controllers/tooltip_controller.js +39 -13
- package/dist/controllers/tooltip_controller.js.map +1 -1
- package/dist/controllers/transition_controller.js +4 -0
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +39 -8
- package/dist/controllers/tree_view_controller.js +169 -16
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +5002 -1911
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +72 -6
- package/dist/inspector/cli.js +262 -51
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +309 -51
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +40 -40
- package/dist/inspector/manifest.json +529 -61
- package/dist/positioning/index.js +2 -0
- package/dist/positioning/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -33,13 +33,26 @@ import { Controller } from '@hotwired/stimulus';
|
|
|
33
33
|
* `data-range-start` / `data-in-range` / `data-range-end` hooks. Assistive tech
|
|
34
34
|
* is told the two confirmed endpoints via `aria-selected`; inner cells use
|
|
35
35
|
* `data-in-range` (visual only) so the announcement stays to the two ends. The
|
|
36
|
-
*
|
|
36
|
+
* range the user confirms is also announced in the live `status` region.
|
|
37
37
|
*
|
|
38
38
|
* Selection model: the first click/Enter sets a *pending* start and enters
|
|
39
39
|
* "selecting" mode (preview follows the pointer/focus); the second confirms the
|
|
40
|
-
* end (auto-swapped if earlier than the start) and
|
|
41
|
-
*
|
|
42
|
-
*
|
|
40
|
+
* end (auto-swapped if earlier than the start), and a preset confirms its range
|
|
41
|
+
* in one step. Escape abandons an in-progress selection, restoring the last
|
|
42
|
+
* confirmed range.
|
|
43
|
+
*
|
|
44
|
+
* A confirmed range is painted — the cells, both hidden fields and the status —
|
|
45
|
+
* before anything reports it. Each hidden field that moved then emits a native
|
|
46
|
+
* bubbling `change`, the way a form control does, so `stimeo--auto-submit` and
|
|
47
|
+
* form-level validation hear it; `monthchange` follows when the paint moved the
|
|
48
|
+
* month, and last `change` dispatches `{ start: string, end: string }`, the ISO
|
|
49
|
+
* range the picker holds. A bound a listener moves meanwhile is applied by the
|
|
50
|
+
* repaint its Value callback runs, so the `reconcile` it causes follows the
|
|
51
|
+
* `change`. A listener that replaces the range before these reports are all out
|
|
52
|
+
* — by confirming another range, or with a repaint that narrows this one — has
|
|
53
|
+
* the replacing range report itself: what is still pending for the replaced
|
|
54
|
+
* range is not sent, and focus stays where the replacing move put it. The seed
|
|
55
|
+
* `connect()` reads out of the hidden fields is written back silently.
|
|
43
56
|
*
|
|
44
57
|
* Availability is declarative on both axes: `min` / `max` bound the selectable
|
|
45
58
|
* interval and `disabledDates` excludes individual dates inside it. Both are
|
|
@@ -49,6 +62,17 @@ import { Controller } from '@hotwired/stimulus';
|
|
|
49
62
|
* navigation dispatches `monthchange` with `{ month }` as a notification (for
|
|
50
63
|
* fetching a month's availability, say); the fetched result comes back in
|
|
51
64
|
* through `disabledDates`, which repaints on its own.
|
|
65
|
+
*
|
|
66
|
+
* The same predicate holds the confirmed range. When a change to `min`, `max`
|
|
67
|
+
* or `disabledDates` leaves an end unselectable, the paint narrows the range:
|
|
68
|
+
* each end moves inward to the nearest day that can still be chosen, and a
|
|
69
|
+
* range with no such day left is cleared. The hidden fields follow without a
|
|
70
|
+
* native `change`, the status keeps announcing what the user confirmed, and
|
|
71
|
+
* `reconcile` dispatches `{ start: string, end: string }` — the narrowed range,
|
|
72
|
+
* empty strings once cleared — rather than `change`, which stays the user's.
|
|
73
|
+
* `connect()` narrows the range it reads from the fields the same way,
|
|
74
|
+
* silently. An in-progress selection whose start becomes unselectable is
|
|
75
|
+
* dropped, as Escape would drop it, and the next pick starts a new one.
|
|
52
76
|
*/
|
|
53
77
|
declare class DateRangePickerController extends Controller<HTMLElement> {
|
|
54
78
|
#private;
|
|
@@ -66,9 +90,13 @@ declare class DateRangePickerController extends Controller<HTMLElement> {
|
|
|
66
90
|
type: StringConstructor;
|
|
67
91
|
default: string;
|
|
68
92
|
};
|
|
93
|
+
locale: {
|
|
94
|
+
type: StringConstructor;
|
|
95
|
+
default: string;
|
|
96
|
+
};
|
|
69
97
|
};
|
|
70
98
|
static actions: readonly ["applyPreset", "next", "onKeydown", "prev", "previewTo", "selectDate"];
|
|
71
|
-
static events: readonly ["change", "monthchange"];
|
|
99
|
+
static events: readonly ["change", "monthchange", "reconcile"];
|
|
72
100
|
readonly gridTarget: HTMLElement;
|
|
73
101
|
readonly hasGridTarget: boolean;
|
|
74
102
|
readonly monthLabelTarget: HTMLElement;
|
|
@@ -83,10 +111,17 @@ declare class DateRangePickerController extends Controller<HTMLElement> {
|
|
|
83
111
|
minValue: string;
|
|
84
112
|
maxValue: string;
|
|
85
113
|
disabledDatesValue: string;
|
|
86
|
-
|
|
114
|
+
localeValue: string;
|
|
115
|
+
/**
|
|
116
|
+
* Seeds the range from optional hidden fields — ordered, and narrowed to the
|
|
117
|
+
* days that can be chosen — then paints the grid, which writes the range back
|
|
118
|
+
* to the fields silently.
|
|
119
|
+
*/
|
|
87
120
|
connect(): void;
|
|
88
121
|
/** Cancels any pending deferred focus so it never fires on a detached element. */
|
|
89
122
|
disconnect(): void;
|
|
123
|
+
/** Repaints the label when application code changes `locale` at runtime. */
|
|
124
|
+
localeValueChanged(): void;
|
|
90
125
|
/** Repaints when application code (or a Turbo morph) changes `min` at runtime. */
|
|
91
126
|
minValueChanged(): void;
|
|
92
127
|
/** Repaints when application code (or a Turbo morph) changes `max` at runtime. */
|
|
@@ -114,6 +114,21 @@ function monthLabelFormatter(locale) {
|
|
|
114
114
|
return intlFormatter(Intl.DateTimeFormat, locale, MONTH_LABEL_OPTIONS, "en");
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
// src/utils/field_mirror.ts
|
|
118
|
+
function writeField(field, value) {
|
|
119
|
+
if (field.value === value) return false;
|
|
120
|
+
field.value = value;
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
function commitField(target) {
|
|
124
|
+
target.dispatchEvent(new Event("change", { bubbles: true }));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/utils/locale.ts
|
|
128
|
+
function resolveLocale(element, declared = "") {
|
|
129
|
+
return declared || element.closest("[lang]")?.getAttribute("lang") || void 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
117
132
|
// src/utils/microtask_coalescer.ts
|
|
118
133
|
var MicrotaskCoalescer = class {
|
|
119
134
|
#run;
|
|
@@ -214,6 +229,11 @@ function parseStringList(raw, fallback = []) {
|
|
|
214
229
|
return parsed.filter((entry) => typeof entry === "string");
|
|
215
230
|
}
|
|
216
231
|
|
|
232
|
+
// src/utils/target_selector.ts
|
|
233
|
+
function targetSelector(identifier, name) {
|
|
234
|
+
return `[data-${identifier}-target~="${name}"]`;
|
|
235
|
+
}
|
|
236
|
+
|
|
217
237
|
// src/controllers/date_range_picker_controller.ts
|
|
218
238
|
var GRID_SIZE = 42;
|
|
219
239
|
var DateRangePickerController = class extends Controller {
|
|
@@ -224,10 +244,11 @@ var DateRangePickerController = class extends Controller {
|
|
|
224
244
|
// A JSON list read through `parseStringList` rather than Stimulus's `Array`
|
|
225
245
|
// type: that reader throws out of the value observer before any callback
|
|
226
246
|
// runs, so one malformed attribute would stop the picker from connecting.
|
|
227
|
-
disabledDates: { type: String, default: "" }
|
|
247
|
+
disabledDates: { type: String, default: "" },
|
|
248
|
+
locale: { type: String, default: "" }
|
|
228
249
|
};
|
|
229
250
|
static actions = ["applyPreset", "next", "onKeydown", "prev", "previewTo", "selectDate"];
|
|
230
|
-
static events = ["change", "monthchange"];
|
|
251
|
+
static events = ["change", "monthchange", "reconcile"];
|
|
231
252
|
/** The month currently rendered, as `YYYY-MM`. */
|
|
232
253
|
#viewMonth = "";
|
|
233
254
|
/** The confirmed range endpoints (ISO), or "" when unset. */
|
|
@@ -241,6 +262,13 @@ var DateRangePickerController = class extends Controller {
|
|
|
241
262
|
#focusedDate = /* @__PURE__ */ new Date();
|
|
242
263
|
/** Deferred focus after an async month transition (cancelled on teardown). */
|
|
243
264
|
#focusTimer = new SafeTimeout();
|
|
265
|
+
/**
|
|
266
|
+
* How many times the confirmed range has moved — a commit or a narrowing — so
|
|
267
|
+
* a report still pending for a range a listener has since replaced can tell.
|
|
268
|
+
*/
|
|
269
|
+
#rangeMoves = 0;
|
|
270
|
+
/** How many month transitions have started, so one a listener starts mid-paint keeps its focus. */
|
|
271
|
+
#transitions = 0;
|
|
244
272
|
/** The declared unavailable dates, indexed for the per-cell paint lookup. */
|
|
245
273
|
#disabledDates = /* @__PURE__ */ new Set();
|
|
246
274
|
/** Rewinds an unfinished selection before Turbo snapshots the page. */
|
|
@@ -254,17 +282,22 @@ var DateRangePickerController = class extends Controller {
|
|
|
254
282
|
#repaint = new MicrotaskCoalescer(() => {
|
|
255
283
|
this.#render();
|
|
256
284
|
});
|
|
257
|
-
/**
|
|
285
|
+
/**
|
|
286
|
+
* Seeds the range from optional hidden fields — ordered, and narrowed to the
|
|
287
|
+
* days that can be chosen — then paints the grid, which writes the range back
|
|
288
|
+
* to the fields silently.
|
|
289
|
+
*/
|
|
258
290
|
connect() {
|
|
259
291
|
this.#repaint.activate();
|
|
260
292
|
this.#beforeCache.activate();
|
|
261
293
|
const authoredStart = this.hasStartFieldTarget ? normalizeISO(this.startFieldTarget.value) : "";
|
|
262
294
|
const authoredEnd = this.hasEndFieldTarget ? normalizeISO(this.endFieldTarget.value) : "";
|
|
263
|
-
[this.#startDate, this.#endDate] =
|
|
295
|
+
[this.#startDate, this.#endDate] = this.#selectableRange(
|
|
296
|
+
...orderRange(authoredStart, authoredEnd)
|
|
297
|
+
);
|
|
264
298
|
this.#pendingStart = "";
|
|
265
299
|
this.#previewDate = "";
|
|
266
300
|
this.#announcedMonth = null;
|
|
267
|
-
this.#commitFields();
|
|
268
301
|
const anchor = parseISODateString(this.#startDate) ?? this.#clampToBounds(/* @__PURE__ */ new Date()) ?? /* @__PURE__ */ new Date();
|
|
269
302
|
this.#focusedDate = anchor;
|
|
270
303
|
this.#viewMonth = toISOMonthString(anchor);
|
|
@@ -277,6 +310,10 @@ var DateRangePickerController = class extends Controller {
|
|
|
277
310
|
this.#beforeCache.deactivate();
|
|
278
311
|
this.#focusTimer.clearAll();
|
|
279
312
|
}
|
|
313
|
+
/** Repaints the label when application code changes `locale` at runtime. */
|
|
314
|
+
localeValueChanged() {
|
|
315
|
+
this.#repaint.schedule();
|
|
316
|
+
}
|
|
280
317
|
/** Repaints when application code (or a Turbo morph) changes `min` at runtime. */
|
|
281
318
|
minValueChanged() {
|
|
282
319
|
this.#repaint.schedule();
|
|
@@ -335,16 +372,11 @@ var DateRangePickerController = class extends Controller {
|
|
|
335
372
|
if (!intersection) return;
|
|
336
373
|
const { start, end } = intersection;
|
|
337
374
|
if (!this.#isSelectable(start) || !this.#isSelectable(end)) return;
|
|
338
|
-
|
|
339
|
-
this.#endDate = end;
|
|
340
|
-
this.#pendingStart = "";
|
|
341
|
-
this.#previewDate = "";
|
|
375
|
+
const move = this.#setConfirmed(start, end);
|
|
342
376
|
const endDate = parseISODateString(end);
|
|
343
377
|
if (endDate) this.#focusedDate = endDate;
|
|
344
|
-
this.#
|
|
345
|
-
this.#
|
|
346
|
-
this.#announce();
|
|
347
|
-
this.dispatch("change", { detail: { start, end } });
|
|
378
|
+
this.#transitionTo(toISOMonthString(parseISODateString(end) ?? /* @__PURE__ */ new Date()), end, true);
|
|
379
|
+
this.#reportConfirmed(move);
|
|
348
380
|
}
|
|
349
381
|
/** Grid keyboard navigation, selection (Enter/Space), and Escape-to-cancel. */
|
|
350
382
|
onKeydown(event) {
|
|
@@ -403,7 +435,7 @@ var DateRangePickerController = class extends Controller {
|
|
|
403
435
|
}
|
|
404
436
|
/** Records a chosen date as either the pending start or the confirmed end. */
|
|
405
437
|
#choose(date) {
|
|
406
|
-
if (!this.#pendingStart) {
|
|
438
|
+
if (!this.#pendingStart || !this.#isSelectable(this.#pendingStart)) {
|
|
407
439
|
this.#pendingStart = date;
|
|
408
440
|
this.#previewDate = date;
|
|
409
441
|
const parsed = parseISODateString(date);
|
|
@@ -412,14 +444,32 @@ var DateRangePickerController = class extends Controller {
|
|
|
412
444
|
return;
|
|
413
445
|
}
|
|
414
446
|
const [start, end] = date < this.#pendingStart ? [date, this.#pendingStart] : [this.#pendingStart, date];
|
|
447
|
+
const move = this.#setConfirmed(start, end);
|
|
448
|
+
this.#render(true);
|
|
449
|
+
this.#reportConfirmed(move);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Makes `start`–`end` the confirmed range, ending any selection in progress,
|
|
453
|
+
* ahead of the paint that shows it.
|
|
454
|
+
*
|
|
455
|
+
* @returns The move count the range is now at, which its `change` checks.
|
|
456
|
+
*/
|
|
457
|
+
#setConfirmed(start, end) {
|
|
415
458
|
this.#startDate = start;
|
|
416
459
|
this.#endDate = end;
|
|
417
460
|
this.#pendingStart = "";
|
|
418
461
|
this.#previewDate = "";
|
|
419
|
-
this.#
|
|
420
|
-
this.#
|
|
421
|
-
|
|
422
|
-
|
|
462
|
+
this.#rangeMoves += 1;
|
|
463
|
+
return this.#rangeMoves;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Dispatches `change` for the range confirmed at `move`, once its paint has
|
|
467
|
+
* reported it through the fields. A listener of those reports that moved the
|
|
468
|
+
* range on has had the range it moved to reported instead.
|
|
469
|
+
*/
|
|
470
|
+
#reportConfirmed(move) {
|
|
471
|
+
if (move !== this.#rangeMoves) return;
|
|
472
|
+
this.dispatch("change", { detail: { start: this.#startDate, end: this.#endDate } });
|
|
423
473
|
}
|
|
424
474
|
/** Moves roving focus to `date`, transitioning the month when needed. */
|
|
425
475
|
#moveFocusTo(date) {
|
|
@@ -428,12 +478,21 @@ var DateRangePickerController = class extends Controller {
|
|
|
428
478
|
if (this.#pendingStart && this.#isSelectable(iso)) this.#previewDate = iso;
|
|
429
479
|
this.#transitionTo(toISOMonthString(date), iso);
|
|
430
480
|
}
|
|
431
|
-
/**
|
|
432
|
-
|
|
481
|
+
/**
|
|
482
|
+
* Renders `month`, then focuses the cell for `dateStr` (deferred if async).
|
|
483
|
+
* A listener of the paint's reports that started another move has placed
|
|
484
|
+
* focus itself, so this one leaves it there.
|
|
485
|
+
*
|
|
486
|
+
* @param confirmed - Whether the paint shows a range the user has just confirmed.
|
|
487
|
+
*/
|
|
488
|
+
#transitionTo(month, dateStr, confirmed = false) {
|
|
433
489
|
const isTransition = month !== this.#viewMonth;
|
|
434
490
|
this.#focusTimer.clearAll();
|
|
435
491
|
this.#viewMonth = month;
|
|
436
|
-
this.#
|
|
492
|
+
this.#transitions += 1;
|
|
493
|
+
const transition = this.#transitions;
|
|
494
|
+
this.#render(confirmed);
|
|
495
|
+
if (transition !== this.#transitions) return;
|
|
437
496
|
const focusCell = () => {
|
|
438
497
|
this.cellTargets.find((c) => c.getAttribute("data-date") === dateStr)?.focus();
|
|
439
498
|
};
|
|
@@ -455,18 +514,27 @@ var DateRangePickerController = class extends Controller {
|
|
|
455
514
|
this.#render();
|
|
456
515
|
}
|
|
457
516
|
/**
|
|
458
|
-
* Builds the six-week grid and binds range/roving/disabled state per cell
|
|
517
|
+
* Builds the six-week grid and binds range/roving/disabled state per cell,
|
|
518
|
+
* mirrors the confirmed range to the hidden fields, then reports what the
|
|
519
|
+
* paint moved.
|
|
520
|
+
*
|
|
521
|
+
* @param confirmed - Whether the paint shows a range the user has just
|
|
522
|
+
* confirmed, which the status then announces and each moved field reports.
|
|
459
523
|
*
|
|
460
524
|
* @stimeoRenderRoot
|
|
461
525
|
*/
|
|
462
|
-
#render() {
|
|
526
|
+
#render(confirmed = false) {
|
|
463
527
|
const info = parseISOMonthString(this.#viewMonth);
|
|
464
528
|
if (!info) return;
|
|
465
529
|
const { year, month } = info;
|
|
530
|
+
if (this.#pendingStart && !this.#isSelectable(this.#pendingStart)) {
|
|
531
|
+
this.#pendingStart = "";
|
|
532
|
+
this.#previewDate = "";
|
|
533
|
+
}
|
|
466
534
|
if (this.#previewDate && !this.#isSelectable(this.#previewDate)) this.#previewDate = "";
|
|
535
|
+
const narrowed = this.#narrowConfirmedRange();
|
|
467
536
|
if (this.hasMonthLabelTarget) {
|
|
468
|
-
const
|
|
469
|
-
const formatter = monthLabelFormatter(lang);
|
|
537
|
+
const formatter = monthLabelFormatter(resolveLocale(this.element, this.localeValue));
|
|
470
538
|
this.monthLabelTarget.textContent = formatter.format(new Date(year, month - 1, 1));
|
|
471
539
|
}
|
|
472
540
|
const [rangeStart, rangeEnd] = this.#visualRange();
|
|
@@ -504,11 +572,54 @@ var DateRangePickerController = class extends Controller {
|
|
|
504
572
|
const fallback = cells.find((cell) => cell.getAttribute("data-outside") === "false") ?? cells[0];
|
|
505
573
|
fallback?.setAttribute("tabindex", "0");
|
|
506
574
|
}
|
|
575
|
+
const move = this.#rangeMoves;
|
|
576
|
+
const moved = this.#mirrorFields();
|
|
577
|
+
if (confirmed) {
|
|
578
|
+
this.#announce();
|
|
579
|
+
for (const [field, value] of moved) {
|
|
580
|
+
if (field.value === value) commitField(field);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
507
583
|
const previous = this.#announcedMonth;
|
|
508
584
|
this.#announcedMonth = this.#viewMonth;
|
|
509
585
|
if (previous !== null && previous !== this.#viewMonth) {
|
|
510
586
|
this.dispatch("monthchange", { detail: { month: this.#viewMonth } });
|
|
511
587
|
}
|
|
588
|
+
if (narrowed && move === this.#rangeMoves) {
|
|
589
|
+
this.dispatch("reconcile", { detail: { start: this.#startDate, end: this.#endDate } });
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Narrows the confirmed range to days that can still be chosen. The paint
|
|
594
|
+
* mirrors it to the fields without reporting a commit.
|
|
595
|
+
*
|
|
596
|
+
* @returns Whether the range moved.
|
|
597
|
+
*/
|
|
598
|
+
#narrowConfirmedRange() {
|
|
599
|
+
const [start, end] = this.#selectableRange(this.#startDate, this.#endDate);
|
|
600
|
+
if (start === this.#startDate && end === this.#endDate) return false;
|
|
601
|
+
this.#startDate = start;
|
|
602
|
+
this.#endDate = end;
|
|
603
|
+
this.#rangeMoves += 1;
|
|
604
|
+
return true;
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* The range `start`–`end` with each end moved inward to the nearest day that
|
|
608
|
+
* can be chosen, or two empty strings when none of its days can be. A lone
|
|
609
|
+
* endpoint is the one-day range it names, and stays lone.
|
|
610
|
+
*/
|
|
611
|
+
#selectableRange(start, end) {
|
|
612
|
+
let from = parseISODateString(start || end);
|
|
613
|
+
let to = parseISODateString(end || start);
|
|
614
|
+
if (!from || !to) return [start, end];
|
|
615
|
+
while (from.getTime() <= to.getTime() && !this.#isSelectable(toISODateString(from))) {
|
|
616
|
+
from = addDays(from, 1);
|
|
617
|
+
}
|
|
618
|
+
while (to.getTime() >= from.getTime() && !this.#isSelectable(toISODateString(to))) {
|
|
619
|
+
to = addDays(to, -1);
|
|
620
|
+
}
|
|
621
|
+
if (from.getTime() > to.getTime()) return ["", ""];
|
|
622
|
+
return [start ? toISODateString(from) : "", end ? toISODateString(to) : ""];
|
|
512
623
|
}
|
|
513
624
|
/** The ordered [start, end] pair to paint: the preview while selecting, else confirmed. */
|
|
514
625
|
#visualRange() {
|
|
@@ -518,10 +629,20 @@ var DateRangePickerController = class extends Controller {
|
|
|
518
629
|
}
|
|
519
630
|
return [this.#startDate, this.#endDate];
|
|
520
631
|
}
|
|
521
|
-
/**
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
632
|
+
/**
|
|
633
|
+
* Writes the confirmed range to the hidden fields.
|
|
634
|
+
*
|
|
635
|
+
* @returns Each field whose value moved, with the value written to it.
|
|
636
|
+
*/
|
|
637
|
+
#mirrorFields() {
|
|
638
|
+
const moved = [];
|
|
639
|
+
if (this.hasStartFieldTarget && writeField(this.startFieldTarget, this.#startDate)) {
|
|
640
|
+
moved.push([this.startFieldTarget, this.#startDate]);
|
|
641
|
+
}
|
|
642
|
+
if (this.hasEndFieldTarget && writeField(this.endFieldTarget, this.#endDate)) {
|
|
643
|
+
moved.push([this.endFieldTarget, this.#endDate]);
|
|
644
|
+
}
|
|
645
|
+
return moved;
|
|
525
646
|
}
|
|
526
647
|
/** Announces the confirmed range in the live status region. */
|
|
527
648
|
#announce() {
|
|
@@ -581,7 +702,7 @@ var DateRangePickerController = class extends Controller {
|
|
|
581
702
|
/** Resolves the cell element from an event target, or null. */
|
|
582
703
|
#cellFrom(target) {
|
|
583
704
|
return target?.closest(
|
|
584
|
-
"
|
|
705
|
+
targetSelector(this.identifier, "cell")
|
|
585
706
|
) ?? null;
|
|
586
707
|
}
|
|
587
708
|
};
|