stimeo-ui 0.17.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -2
- package/README.md +19 -10
- package/dist/cable/index.d.ts +11 -9
- package/dist/cable/index.js +22 -14
- package/dist/cable/index.js.map +1 -1
- package/dist/coerce-JtZVNG5h.d.ts +20 -0
- package/dist/controllers/accordion_controller.js +14 -6
- package/dist/controllers/accordion_controller.js.map +1 -1
- package/dist/controllers/alert_dialog_controller.js +145 -118
- package/dist/controllers/alert_dialog_controller.js.map +1 -1
- package/dist/controllers/announcer_controller.d.ts +5 -3
- package/dist/controllers/announcer_controller.js +113 -17
- package/dist/controllers/announcer_controller.js.map +1 -1
- package/dist/controllers/auto_submit_controller.js +185 -60
- package/dist/controllers/auto_submit_controller.js.map +1 -1
- package/dist/controllers/avatar_controller.js +55 -43
- package/dist/controllers/avatar_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/bulk_select_controller.d.ts +3 -3
- package/dist/controllers/bulk_select_controller.js +64 -50
- package/dist/controllers/bulk_select_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +15 -12
- package/dist/controllers/calendar_controller.js +55 -53
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +9 -5
- package/dist/controllers/carousel_controller.js +124 -86
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/character_counter_controller.d.ts +27 -6
- package/dist/controllers/character_counter_controller.js +291 -95
- package/dist/controllers/character_counter_controller.js.map +1 -1
- package/dist/controllers/checkbox_controller.js +6 -0
- package/dist/controllers/checkbox_controller.js.map +1 -1
- package/dist/controllers/clipboard_controller.js +118 -27
- package/dist/controllers/clipboard_controller.js.map +1 -1
- package/dist/controllers/collapsible_controller.d.ts +1 -1
- package/dist/controllers/collapsible_controller.js +52 -49
- package/dist/controllers/collapsible_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.js +29 -7
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.d.ts +1 -1
- package/dist/controllers/combobox_controller.js +210 -71
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +9 -9
- package/dist/controllers/command_palette_controller.js +290 -140
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/conditional_fields_controller.js +145 -58
- package/dist/controllers/conditional_fields_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.js +145 -118
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/context_menu_controller.d.ts +49 -14
- package/dist/controllers/context_menu_controller.js +138 -73
- package/dist/controllers/context_menu_controller.js.map +1 -1
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/countdown_controller.d.ts +2 -2
- package/dist/controllers/countdown_controller.js +109 -21
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +75 -11
- package/dist/controllers/currency_input_controller.js +446 -72
- package/dist/controllers/currency_input_controller.js.map +1 -1
- package/dist/controllers/data_grid_controller.d.ts +10 -8
- package/dist/controllers/data_grid_controller.js +134 -28
- package/dist/controllers/data_grid_controller.js.map +1 -1
- package/dist/controllers/date_range_picker_controller.d.ts +12 -9
- package/dist/controllers/date_range_picker_controller.js +93 -72
- package/dist/controllers/date_range_picker_controller.js.map +1 -1
- package/dist/controllers/dialog_controller.d.ts +4 -5
- package/dist/controllers/dialog_controller.js +145 -118
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.d.ts +1 -1
- package/dist/controllers/direct_upload_controller.js +24 -14
- package/dist/controllers/direct_upload_controller.js.map +1 -1
- package/dist/controllers/dirty_form_controller.d.ts +6 -1
- package/dist/controllers/dirty_form_controller.js +68 -31
- package/dist/controllers/dirty_form_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.js +66 -46
- package/dist/controllers/dismissible_controller.js.map +1 -1
- package/dist/controllers/drawer_controller.js +145 -118
- package/dist/controllers/drawer_controller.js.map +1 -1
- package/dist/controllers/dropdown_controller.js +76 -63
- package/dist/controllers/dropdown_controller.js.map +1 -1
- package/dist/controllers/editable_controller.js +200 -62
- package/dist/controllers/editable_controller.js.map +1 -1
- package/dist/controllers/empty_state_controller.js +13 -6
- package/dist/controllers/empty_state_controller.js.map +1 -1
- package/dist/controllers/file_dropzone_controller.d.ts +3 -0
- package/dist/controllers/file_dropzone_controller.js +55 -48
- package/dist/controllers/file_dropzone_controller.js.map +1 -1
- package/dist/controllers/filter_controller.js +9 -2
- package/dist/controllers/filter_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +4 -4
- package/dist/controllers/flash_controller.js +66 -33
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +3 -3
- package/dist/controllers/focus_controller.js +39 -14
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.d.ts +2 -1
- package/dist/controllers/form_field_controller.js +52 -43
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.d.ts +3 -3
- package/dist/controllers/form_validation_controller.js +18 -11
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.d.ts +13 -12
- package/dist/controllers/frame_loading_controller.js +55 -48
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.d.ts +5 -4
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/hover_card_controller.d.ts +4 -1
- package/dist/controllers/hover_card_controller.js +67 -61
- package/dist/controllers/hover_card_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +6 -5
- package/dist/controllers/idle_controller.js +10 -6
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/input_mask_controller.d.ts +31 -13
- package/dist/controllers/input_mask_controller.js +434 -24
- package/dist/controllers/input_mask_controller.js.map +1 -1
- package/dist/controllers/intersection_controller.js +3 -0
- package/dist/controllers/intersection_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.d.ts +3 -2
- package/dist/controllers/lazy_frame_controller.js +15 -3
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +10 -7
- package/dist/controllers/listbox_controller.js +260 -79
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.d.ts +8 -6
- package/dist/controllers/local_time_controller.js +48 -13
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.js +11 -4
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/menu_controller.d.ts +24 -5
- package/dist/controllers/menu_controller.js +138 -82
- package/dist/controllers/menu_controller.js.map +1 -1
- package/dist/controllers/menubar_controller.d.ts +49 -7
- package/dist/controllers/menubar_controller.js +65 -19
- package/dist/controllers/menubar_controller.js.map +1 -1
- package/dist/controllers/meter_controller.d.ts +13 -20
- package/dist/controllers/meter_controller.js +270 -24
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +19 -16
- package/dist/controllers/multi_select_controller.js +272 -95
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/navigation_menu_controller.d.ts +19 -5
- package/dist/controllers/navigation_menu_controller.js +67 -19
- package/dist/controllers/navigation_menu_controller.js.map +1 -1
- package/dist/controllers/nested_form_controller.js +98 -64
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/network_status_controller.js +70 -52
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +24 -6
- package/dist/controllers/number_input_controller.js +344 -94
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/optimistic_controller.d.ts +8 -5
- package/dist/controllers/optimistic_controller.js +29 -11
- package/dist/controllers/optimistic_controller.js.map +1 -1
- package/dist/controllers/otp_controller.d.ts +35 -4
- package/dist/controllers/otp_controller.js +502 -104
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.js +6 -0
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +10 -9
- package/dist/controllers/overflow_menu_controller.js +136 -21
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +3 -2
- package/dist/controllers/pagination_controller.js +47 -14
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +5 -4
- package/dist/controllers/password_reveal_controller.js +52 -49
- package/dist/controllers/password_reveal_controller.js.map +1 -1
- package/dist/controllers/password_strength_controller.d.ts +1 -1
- package/dist/controllers/password_strength_controller.js +13 -6
- package/dist/controllers/password_strength_controller.js.map +1 -1
- package/dist/controllers/persist_controller.js +48 -128
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +20 -8
- package/dist/controllers/pointer_drag_controller.js +255 -24
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.d.ts +9 -5
- package/dist/controllers/popover_controller.js +91 -65
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.js +6 -0
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/preview_guard_controller.js +14 -3
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/progress_controller.d.ts +9 -19
- package/dist/controllers/progress_controller.js +271 -27
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.d.ts +11 -8
- package/dist/controllers/radio_group_controller.js +167 -80
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/range_slider_controller.d.ts +4 -3
- package/dist/controllers/range_slider_controller.js +27 -7
- package/dist/controllers/range_slider_controller.js.map +1 -1
- package/dist/controllers/rating_controller.js +93 -57
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/read_more_controller.js +10 -6
- package/dist/controllers/read_more_controller.js.map +1 -1
- package/dist/controllers/reading_progress_controller.js +22 -5
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/relative_time_controller.d.ts +4 -4
- package/dist/controllers/relative_time_controller.js +75 -11
- package/dist/controllers/relative_time_controller.js.map +1 -1
- package/dist/controllers/reset_on_restore_controller.d.ts +3 -3
- package/dist/controllers/reset_on_restore_controller.js +6 -0
- package/dist/controllers/reset_on_restore_controller.js.map +1 -1
- package/dist/controllers/resizable_controller.d.ts +3 -0
- package/dist/controllers/resizable_controller.js +55 -22
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.d.ts +3 -3
- package/dist/controllers/roving_controller.js +10 -4
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.js +129 -88
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_restore_controller.d.ts +3 -3
- package/dist/controllers/scroll_restore_controller.js +14 -2
- package/dist/controllers/scroll_restore_controller.js.map +1 -1
- package/dist/controllers/scroll_visibility_controller.js +93 -60
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.js +11 -5
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +1 -1
- package/dist/controllers/separator_controller.js +59 -43
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/sidebar_controller.d.ts +1 -1
- package/dist/controllers/sidebar_controller.js +150 -122
- package/dist/controllers/sidebar_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.js +55 -48
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +2 -1
- package/dist/controllers/slider_controller.js +27 -6
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.d.ts +1 -1
- package/dist/controllers/smart_sticky_header_controller.js +13 -5
- package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
- package/dist/controllers/sortable_controller.d.ts +4 -4
- package/dist/controllers/sortable_controller.js +27 -14
- package/dist/controllers/sortable_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.js +55 -48
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +4 -4
- package/dist/controllers/step_indicator_controller.js +6 -0
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +2 -3
- package/dist/controllers/stepper_controller.js +6 -0
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +3 -1
- package/dist/controllers/stick_to_bottom_controller.js +19 -8
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.js +49 -43
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +2 -1
- package/dist/controllers/submit_once_controller.js +145 -85
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +7 -4
- package/dist/controllers/switch_controller.js +172 -28
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tabs_controller.d.ts +7 -4
- package/dist/controllers/tabs_controller.js +6 -1
- package/dist/controllers/tabs_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +4 -3
- package/dist/controllers/tags_input_controller.js +157 -28
- package/dist/controllers/tags_input_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.d.ts +1 -1
- package/dist/controllers/textarea_autosize_controller.js +40 -19
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/theme_controller.d.ts +3 -2
- package/dist/controllers/theme_controller.js +10 -4
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +38 -5
- package/dist/controllers/time_picker_controller.js +192 -54
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/toast_controller.d.ts +4 -5
- package/dist/controllers/toast_controller.js +58 -27
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.d.ts +2 -3
- package/dist/controllers/toggle_group_controller.js +158 -56
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.d.ts +8 -6
- package/dist/controllers/toolbar_controller.js +150 -21
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/tooltip_controller.d.ts +4 -1
- package/dist/controllers/tooltip_controller.js.map +1 -1
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +1 -1
- package/dist/controllers/tree_view_controller.js +134 -25
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2515 -1315
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +25 -12
- package/dist/inspector/cli.js +21 -3
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.d.ts +1 -1
- package/dist/inspector/cli_bin.js +62 -8
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +13 -13
- package/dist/inspector/manifest.json +19 -5
- package/dist/positioning/index.d.ts +9 -8
- package/dist/positioning/index.js +6 -0
- package/dist/positioning/index.js.map +1 -1
- package/package.json +11 -10
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,140 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
While the version is `0.x`, the public API (the `stimeo--*` data attributes) may
|
|
8
8
|
change between releases.
|
|
9
9
|
|
|
10
|
-
## [
|
|
10
|
+
## [0.18.1] - 2026-10-31
|
|
11
|
+
|
|
12
|
+
Patch release focused on keyboard ownership, focus handoff, masked selections,
|
|
13
|
+
and Inspector compatibility.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Inspector host contracts can admit the `<input>` types a controller composes
|
|
18
|
+
with instead of replacing (`inputTypes`); any other `<input>` on such a host is
|
|
19
|
+
still reported as `invalid-host`. The manifest carries this as `schemaVersion`
|
|
20
|
+
17. Update Inspector engines and the VS Code extension together with their
|
|
21
|
+
manifest; an older engine reading it may report an admitted input as
|
|
22
|
+
`invalid-host`.
|
|
23
|
+
- Refresh pinned build and test tooling: Biome 2.6.3, happy-dom 21.0.4,
|
|
24
|
+
tsup 9.0.0, and Rollup 4.66.0.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- command-palette and editable: respect keyboard events already handled by another
|
|
29
|
+
listener, including global shortcuts and F2.
|
|
30
|
+
- multi-select: close on Tab from a chip and keep the list closed when that Tab
|
|
31
|
+
reaches the input.
|
|
32
|
+
- popover: close when focus reaches an unrelated control after first falling to
|
|
33
|
+
the document body, while preserving the destination focus.
|
|
34
|
+
- dismissible: release focus from hidden content when no fallback can receive
|
|
35
|
+
focus.
|
|
36
|
+
- input-mask: preserve selected text when a single invalid typed character would
|
|
37
|
+
replace it.
|
|
38
|
+
- pointer-drag: cancel active sessions when a handle loses its target declaration
|
|
39
|
+
and restore the fallback handle when no declared handles remain.
|
|
40
|
+
|
|
41
|
+
## [0.18.0] - 2026-10-22
|
|
42
|
+
|
|
43
|
+
Minor release with no new components. IME composition, Turbo morphs, and form
|
|
44
|
+
submission now behave consistently across the input components, and several
|
|
45
|
+
contracts change, so read Changed before upgrading. The Inspector manifest moves
|
|
46
|
+
to schema v16; update `stimeo check` and the VS Code extension together and run
|
|
47
|
+
`stimeo check` before deploying.
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- time-picker: `amLabel` and `pmLabel` Values set the meridiem text and its
|
|
52
|
+
speech, and `hour12ZeroBased` shows and enters a twelve-hour clock's hours as
|
|
53
|
+
0–11, as `午前` / `午後` time is written. The submitted value stays on the
|
|
54
|
+
24-hour clock.
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- **Breaking** input-mask: a synchronized hidden field carries a unique internal
|
|
59
|
+
DOM name; native FormData and native / Turbo submission restore the original
|
|
60
|
+
name, and removing the source submits an empty entry. Find managed fields by id
|
|
61
|
+
or the pairing attribute, use native FormData, and call
|
|
62
|
+
`prepareInputMaskForm(form)` before reading FormData from a new detached form.
|
|
63
|
+
input-mask clears only the raw value it wrote.
|
|
64
|
+
- **Breaking** otp: a pattern drop held for a composition is reported as
|
|
65
|
+
`reconcile` before the edit's own `change` / `complete` / `invalid`, and a
|
|
66
|
+
reconnect under another `pattern` drops what it rejects as `reconcile`. Use the
|
|
67
|
+
edit events for submission.
|
|
68
|
+
- **Breaking** number-input: a range or step change made during IME composition
|
|
69
|
+
applies when the user confirms, reported as `change`; a morph that changes
|
|
70
|
+
neither holds nothing.
|
|
71
|
+
- **Breaking** currency-input: actions and events act only on the first `display`
|
|
72
|
+
target, and a display already focused when the controller connects starts
|
|
73
|
+
formatting at its next ordinary edit or composition end. Render the initial
|
|
74
|
+
hidden and accessible values on the server. `stimeo check` warns about extra
|
|
75
|
+
displays.
|
|
76
|
+
- **Breaking** tabs, calendar, date-range-picker, slider, range-slider,
|
|
77
|
+
color-picker, multi-select, and tags-input read the writing direction from their
|
|
78
|
+
layout targets instead of the root; carousel gains a `pickerList` and
|
|
79
|
+
navigation-menu a `list` target.
|
|
80
|
+
- **Breaking** dirty-form and optimistic accept only the terminal event matching
|
|
81
|
+
the latest start's source and token, and only `success: true` succeeds. For a
|
|
82
|
+
custom save, call `markClean` or dispatch the paired events with `success`.
|
|
83
|
+
- **Breaking** local-time and relative-time read `datetime` strictly: a clock
|
|
84
|
+
without a zone is UTC (relative-time read it as local time), and an incomplete
|
|
85
|
+
or invalid value keeps the current display.
|
|
86
|
+
- **Breaking** presence and typing-indicator templates use `{count}`, `{name}`,
|
|
87
|
+
and `{names}` instead of `%{…}`.
|
|
88
|
+
- **Breaking** modified `Home` / `End` / `PageUp` / `PageDown` go to the browser
|
|
89
|
+
in widgets without a dedicated binding; pointer-drag cancels a keyboard grab
|
|
90
|
+
when focus leaves the handle; time-picker accepts digits typed with `Shift`.
|
|
91
|
+
- **Breaking** progress, meter, pointer-drag, countdown, overflow-menu, listbox,
|
|
92
|
+
submit-once, clipboard, announcer, and currency-input change their ownership
|
|
93
|
+
markers (pointer-drag: `data-stimeo--pointer-drag-tabindex-loan`, listbox:
|
|
94
|
+
`owns-label`); re-render persisted HTML from authored markup. progress and meter
|
|
95
|
+
restore the authored `aria-valuetext` when the template is cleared or the
|
|
96
|
+
controller disconnects.
|
|
97
|
+
- **Breaking** menubar, navigation-menu, menu, and context-menu treat an entry
|
|
98
|
+
inside an `aria-disabled="true"` ancestor as disabled (it stays reachable with
|
|
99
|
+
the arrow keys), and with nested entries refuse an action when any entry holding
|
|
100
|
+
its target is disabled. A click is judged when it reaches the component, so a
|
|
101
|
+
handler inside the component that disables its entry during the click keeps the
|
|
102
|
+
open or close it started; a menubar top it leaves natively `disabled` then has
|
|
103
|
+
its menu closed again, without a `close` event.
|
|
104
|
+
- **Breaking** pointer-drag: `reset()` returns the inline `translate` to the
|
|
105
|
+
origin only when `follow` is on; otherwise it cancels the gesture in flight and
|
|
106
|
+
leaves the author's `translate` alone.
|
|
107
|
+
- toggle-group writes `aria-pressed`, time-picker `aria-valuenow`, and radio-group
|
|
108
|
+
its arrival and release `tabindex` only when the value changes.
|
|
109
|
+
- context-menu: the region contract drops `aria-haspopup`; give the region a role
|
|
110
|
+
and name that fit its content and advertise the key with
|
|
111
|
+
`aria-keyshortcuts="Shift+F10"`.
|
|
112
|
+
- `stimeo check` reports `missing-announcer` for the `stimeo-ui/cable`
|
|
113
|
+
controllers (live-counter, presence, typing-indicator), and the
|
|
114
|
+
`stimeo:install` generator writes commented-out pins and registrations for the
|
|
115
|
+
opt-in `stimeo-ui/cable` and `stimeo-ui/positioning` entry points.
|
|
116
|
+
|
|
117
|
+
### Removed
|
|
118
|
+
|
|
119
|
+
- character-counter: the `announceTextValueChanged()` callback is gone from the
|
|
120
|
+
shipped types; pending announcements still read the current `announceText`.
|
|
121
|
+
|
|
122
|
+
### Fixed
|
|
123
|
+
|
|
124
|
+
- IME composition no longer sticks after a page write, a move, or a Turbo morph
|
|
125
|
+
in auto-submit, character-counter, combobox, command-palette, currency-input,
|
|
126
|
+
editable, input-mask, multi-select, number-input, otp, tags-input, and toolbar.
|
|
127
|
+
A morph leaves a field mid-composition alone, and a focused draft survives
|
|
128
|
+
morphs and reconnection.
|
|
129
|
+
- switch, otp, currency-input, and input-mask keep their hidden form values right
|
|
130
|
+
across Turbo morphs and removal.
|
|
131
|
+
- State events and reconciliation stay right when a `change` listener disconnects
|
|
132
|
+
the controller or the page edits state during a repair.
|
|
133
|
+
- Components release what an earlier connection registered when connected twice,
|
|
134
|
+
and keep authored text, ARIA, and tab stops through restores.
|
|
135
|
+
- relative-time follows live `datetime` changes; template substitution leaves
|
|
136
|
+
inherited names such as `{constructor}` unchanged.
|
|
137
|
+
- menubar, navigation-menu, menu, and context-menu refuse a `hidden`, natively
|
|
138
|
+
`disabled`, or `aria-disabled` entry on every route — an explicit element, any
|
|
139
|
+
event, or hover — as a click on it already was; `context-menu#activate` takes
|
|
140
|
+
the optional event.
|
|
141
|
+
- The MCP server accepts JSON-RPC batches in sessions that negotiated protocol
|
|
142
|
+
version 2025-03-26; other versions, and batches before `initialize`, are still
|
|
143
|
+
rejected.
|
|
11
144
|
|
|
12
145
|
## [0.17.0] - 2026-10-04
|
|
13
146
|
|
|
@@ -1307,7 +1440,8 @@ Initial public alpha: 101 behavior-only, accessible Stimulus controllers driven
|
|
|
1307
1440
|
by `data-*` attributes, shipping no CSS. Published to npm (with provenance) and
|
|
1308
1441
|
RubyGems.
|
|
1309
1442
|
|
|
1310
|
-
[
|
|
1443
|
+
[0.18.1]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.18.1
|
|
1444
|
+
[0.18.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.18.0
|
|
1311
1445
|
[0.17.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.17.0
|
|
1312
1446
|
[0.16.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.16.0
|
|
1313
1447
|
[0.15.0]: https://github.com/taiyaky/stimeo-ui/releases/tag/v0.15.0
|
package/README.md
CHANGED
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
owns the look entirely.
|
|
16
16
|
|
|
17
17
|
- Lean by design: the **core** needs only `@hotwired/stimulus` at runtime (kept
|
|
18
|
-
external in the build).
|
|
19
|
-
|
|
20
|
-
Peer dependencies note below
|
|
18
|
+
external in the build). Two opt-in subpaths each add one optional **peer
|
|
19
|
+
dependency**: `stimeo-ui/positioning` (`@floating-ui/dom`) and `stimeo-ui/cable`
|
|
20
|
+
(`@rails/actioncable`); see the Peer dependencies note below.
|
|
21
21
|
- Accessibility first: every controller follows the relevant WAI-ARIA APG pattern
|
|
22
22
|
and the related WCAG 2.2 AA criteria.
|
|
23
23
|
- Public controller identifiers use the `stimeo--` namespace (e.g.
|
|
@@ -36,8 +36,12 @@ bin/rails generate stimeo:install
|
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
The generator vendors the prebuilt JS into `vendor/javascript/stimeo/`, pins
|
|
39
|
-
`stimeo-ui` in `config/importmap.rb`, and registers
|
|
40
|
-
Stimulus application.
|
|
39
|
+
`stimeo-ui` in `config/importmap.rb`, and registers the core controllers with your
|
|
40
|
+
Stimulus application (`app/javascript/controllers/stimeo.js`). It writes the opt-in
|
|
41
|
+
`stimeo-ui/positioning` and `stimeo-ui/cable` entry points into those two files
|
|
42
|
+
commented out; to enable one, uncomment its lines. The cable lines include the pin
|
|
43
|
+
for its `@rails/actioncable` peer; positioning also needs a pin for
|
|
44
|
+
`@floating-ui/dom`. Then drive components from HTML alone:
|
|
41
45
|
|
|
42
46
|
```erb
|
|
43
47
|
<div data-controller="stimeo--dropdown">
|
|
@@ -58,9 +62,12 @@ import { Application } from "@hotwired/stimulus";
|
|
|
58
62
|
import { registerStimeo } from "stimeo-ui";
|
|
59
63
|
|
|
60
64
|
const application = Application.start();
|
|
61
|
-
registerStimeo(application); // registers every
|
|
65
|
+
registerStimeo(application); // registers every controller of the core entry point
|
|
62
66
|
```
|
|
63
67
|
|
|
68
|
+
The opt-in `stimeo-ui/positioning` and `stimeo-ui/cable` entry points register
|
|
69
|
+
theirs with `registerPositioning` / `registerCable`.
|
|
70
|
+
|
|
64
71
|
Need only a few controllers? Import them individually from
|
|
65
72
|
`stimeo-ui/controllers/*` and register them under your own identifiers. Each
|
|
66
73
|
file loads on its own, yet the coordination between components — which layer
|
|
@@ -73,7 +80,8 @@ and peer departure decisions; generated ARIA ids stay distinct across copies too
|
|
|
73
80
|
|
|
74
81
|
- **Peer dependencies:** `@hotwired/stimulus` (always), `@floating-ui/dom` (only
|
|
75
82
|
if you use the opt-in `stimeo-ui/positioning` module — tooltips, popovers, etc.
|
|
76
|
-
work without it via the default flow layout)
|
|
83
|
+
work without it via the default flow layout), and `@rails/actioncable` (only if
|
|
84
|
+
you use the opt-in `stimeo-ui/cable` module).
|
|
77
85
|
- **No CSS is shipped.** Style the components yourself; controllers only toggle
|
|
78
86
|
ARIA state and `data-*` hooks.
|
|
79
87
|
|
|
@@ -118,8 +126,9 @@ keep the rules on everywhere else. For Biome:
|
|
|
118
126
|
The `eslint-plugin-jsx-a11y` equivalents are
|
|
119
127
|
`no-noninteractive-element-to-interactive-role`, `no-redundant-roles`,
|
|
120
128
|
`prefer-tag-over-role`, `interactive-supports-focus`, and
|
|
121
|
-
`no-noninteractive-tabindex`.
|
|
122
|
-
with axe-core and
|
|
129
|
+
`no-noninteractive-tabindex`. This repository's tests check these components
|
|
130
|
+
with axe-core and with a virtual screen reader for speech order; neither stands
|
|
131
|
+
in for a real screen reader on your own pages.
|
|
123
132
|
|
|
124
133
|
## Composing components
|
|
125
134
|
|
|
@@ -279,7 +288,7 @@ or in `.mcp.json` (Claude Code) / `.cursor/mcp.json` (Cursor):
|
|
|
279
288
|
It exposes four read-only tools — `stimeo_check` (validate a source string),
|
|
280
289
|
`stimeo_catalog`, `stimeo_controller` (one controller's full contract,
|
|
281
290
|
accessibility requirements included), and `stimeo_example` (verified example
|
|
282
|
-
markup: the
|
|
291
|
+
markup: the controller's demo under [`examples/`](examples/), bundled at
|
|
283
292
|
build time and guaranteed to pass the checker) — plus MCP resources
|
|
284
293
|
(`stimeo://manifest`, `stimeo://examples/<id>`) for preloading context without
|
|
285
294
|
a tool round-trip. The server reads only its bundled manifest and example
|
package/dist/cable/index.d.ts
CHANGED
|
@@ -145,7 +145,7 @@ declare class LiveCounterController extends Controller<HTMLElement> {
|
|
|
145
145
|
* data-stimeo--presence-channel-value="PresenceChannel"
|
|
146
146
|
* data-stimeo--presence-params-value='{"room":"doc_7"}'
|
|
147
147
|
* data-stimeo--presence-id-value="17" data-stimeo--presence-name-value="Alice">
|
|
148
|
-
* <span data-stimeo--presence-target="count" data-other="
|
|
148
|
+
* <span data-stimeo--presence-target="count" data-other="{count} viewing"></span>
|
|
149
149
|
* <ul data-stimeo--presence-target="list"></ul>
|
|
150
150
|
* <template data-stimeo--presence-target="template">
|
|
151
151
|
* <li><span data-presence-name></span></li>
|
|
@@ -169,7 +169,7 @@ declare class LiveCounterController extends Controller<HTMLElement> {
|
|
|
169
169
|
* `template` pair, one clone per peer is appended (elements marked
|
|
170
170
|
* `data-presence-name` receive the name; the clone root is tagged
|
|
171
171
|
* `data-presence-id`), and the `count` target renders through localizable
|
|
172
|
-
* `data-zero` / `data-one` / `data-other` templates (
|
|
172
|
+
* `data-zero` / `data-one` / `data-other` templates (`{count}`). Richer
|
|
173
173
|
* per-user rendering (avatars, links) belongs to the consumer via the `join` /
|
|
174
174
|
* `leave` / `change` events or a server-rendered Turbo Stream. A `template` holds
|
|
175
175
|
* one root element: the clone appended for a peer, and the node removed when the
|
|
@@ -189,9 +189,10 @@ declare class LiveCounterController extends Controller<HTMLElement> {
|
|
|
189
189
|
* whatever a Turbo cache snapshot preserved (hooks + rendered clones), renders
|
|
190
190
|
* the known-empty count (the `data-present*` hooks stay absent until the first
|
|
191
191
|
* beacon), and the stream re-populates; a `count` or `list` target swapped in by a
|
|
192
|
-
* Stream or a morph arrives empty and is drawn from the roster as it connects;
|
|
193
|
-
* per-peer expiry timers, and the
|
|
194
|
-
* `disconnect()` (Turbo navigation
|
|
192
|
+
* Stream or a morph arrives empty and is drawn from the roster as it connects;
|
|
193
|
+
* the subscription, heartbeat interval, per-peer expiry timers, and the
|
|
194
|
+
* `pagehide` listener are all released on `disconnect()` (Turbo navigation
|
|
195
|
+
* included).
|
|
195
196
|
*
|
|
196
197
|
* The live resources follow the declaration; Values changed together move them
|
|
197
198
|
* once, after the batch, and nothing moves before `connect()` or after
|
|
@@ -316,7 +317,7 @@ declare class PresenceController extends Controller<HTMLElement> {
|
|
|
316
317
|
* data-stimeo--typing-indicator-announce-one-text-value="{name} is typing">
|
|
317
318
|
* <textarea data-stimeo--typing-indicator-target="input"></textarea>
|
|
318
319
|
* <p data-stimeo--typing-indicator-target="status"
|
|
319
|
-
* data-one="
|
|
320
|
+
* data-one="{name} is typing…" data-many="{names} are typing…"></p>
|
|
320
321
|
* </div>
|
|
321
322
|
*
|
|
322
323
|
* Server contract (a trivial rebroadcast channel):
|
|
@@ -337,8 +338,8 @@ declare class PresenceController extends Controller<HTMLElement> {
|
|
|
337
338
|
* @remarks
|
|
338
339
|
* Behavior only — the indicator's look is the consumer's CSS, keyed off the
|
|
339
340
|
* `data-typing` hook; the copy is localizable through the `data-one` /
|
|
340
|
-
* `data-many` templates (
|
|
341
|
-
*
|
|
341
|
+
* `data-many` templates (`{name}` / `{names}` / `{count}`), with terse English
|
|
342
|
+
* as the fallback. The own echo is
|
|
342
343
|
* dropped by comparing the broadcast `name` against `name` (a same-name guard,
|
|
343
344
|
* not authentication — identity belongs to the server). Sending tracks the full
|
|
344
345
|
* subscription lifecycle (via the shared confirmation-aware subscription):
|
|
@@ -563,4 +564,5 @@ declare const cableControllers: {
|
|
|
563
564
|
*/
|
|
564
565
|
declare function registerCable(application: Application): void;
|
|
565
566
|
|
|
566
|
-
export {
|
|
567
|
+
export { LiveCounterController, PresenceController, TypingIndicatorController, cableControllers, createConfirmedSubscription, getCableConsumer, registerCable, setCableConsumer };
|
|
568
|
+
export type { CableConsumer, CableSubscription, CableSubscriptionMixin, ConfirmedCableSubscription };
|
package/dist/cable/index.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
import { createConsumer } from '@rails/actioncable';
|
|
3
3
|
|
|
4
|
+
function fillTemplate(template, values) {
|
|
5
|
+
return template.replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (match, name) => {
|
|
6
|
+
const replacement = Object.hasOwn(values, name) ? values[name] : void 0;
|
|
7
|
+
return replacement === void 0 ? match : String(replacement);
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
4
11
|
function announce(message, options = {}) {
|
|
5
12
|
const text = message.trim();
|
|
6
13
|
if (text.length === 0) return;
|
|
@@ -10,12 +17,6 @@ function announce(message, options = {}) {
|
|
|
10
17
|
})
|
|
11
18
|
);
|
|
12
19
|
}
|
|
13
|
-
function fillTemplate(template, values) {
|
|
14
|
-
return template.replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (match, name) => {
|
|
15
|
-
const replacement = values[name];
|
|
16
|
-
return replacement === void 0 ? match : String(replacement);
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
20
|
|
|
20
21
|
var TOKEN_BODY = /\d[\d.,'’’ _]*\d|\d/;
|
|
21
22
|
var SIGN_OPENER = /[\s([]/;
|
|
@@ -97,6 +98,9 @@ var MicrotaskCoalescer = class {
|
|
|
97
98
|
this.#queued = false;
|
|
98
99
|
this.#generation += 1;
|
|
99
100
|
}
|
|
101
|
+
get pending() {
|
|
102
|
+
return this.#queued;
|
|
103
|
+
}
|
|
100
104
|
schedule() {
|
|
101
105
|
if (!this.#active || this.#queued) return;
|
|
102
106
|
this.#queued = true;
|
|
@@ -138,6 +142,9 @@ var MorphRenderWatcher = class {
|
|
|
138
142
|
schedule() {
|
|
139
143
|
this.#pass.schedule();
|
|
140
144
|
}
|
|
145
|
+
get pending() {
|
|
146
|
+
return this.#pass.pending;
|
|
147
|
+
}
|
|
141
148
|
disconnect() {
|
|
142
149
|
this.#listeners.dispose();
|
|
143
150
|
this.#pass.cancel();
|
|
@@ -601,6 +608,7 @@ var PresenceController = class _PresenceController extends Controller {
|
|
|
601
608
|
#pendingBeacon = null;
|
|
602
609
|
#announceId = null;
|
|
603
610
|
#connected = false;
|
|
611
|
+
#cycleListeners = new ListenerSet();
|
|
604
612
|
#speakerKey = "";
|
|
605
613
|
#speakerId = "";
|
|
606
614
|
channelValueChanged() {
|
|
@@ -666,10 +674,10 @@ var PresenceController = class _PresenceController extends Controller {
|
|
|
666
674
|
received: (data) => this.#onReceived(data)
|
|
667
675
|
});
|
|
668
676
|
this.#armHeartbeat();
|
|
669
|
-
|
|
677
|
+
this.#cycleListeners.add(window, "pagehide", this.#onPageHide);
|
|
670
678
|
}
|
|
671
679
|
#close() {
|
|
672
|
-
|
|
680
|
+
this.#cycleListeners.dispose();
|
|
673
681
|
this.#sendLeaveNotice(this.#releaseSpeaker());
|
|
674
682
|
this.#subscription?.unsubscribe();
|
|
675
683
|
this.#subscription = null;
|
|
@@ -797,7 +805,7 @@ ${this.#speakerId}`;
|
|
|
797
805
|
#countMessage(count) {
|
|
798
806
|
const templates = this.countTarget.dataset;
|
|
799
807
|
const template = (count === 0 ? templates.zero : count === 1 ? templates.one : templates.other) ?? templates.other;
|
|
800
|
-
return template ? template
|
|
808
|
+
return template ? fillTemplate(template, { count }) : String(count);
|
|
801
809
|
}
|
|
802
810
|
#drawList() {
|
|
803
811
|
if (!this.hasListTarget) return;
|
|
@@ -877,7 +885,6 @@ var TRANSIENT3 = new TransientHooks({
|
|
|
877
885
|
});
|
|
878
886
|
var DEFAULT_TIMEOUT = 3e3;
|
|
879
887
|
var DEFAULT_THROTTLE = 2e3;
|
|
880
|
-
var fillTokens = (template, values) => template.replace(/%\{(name|names|count)\}/g, (match, token) => values[token] ?? match);
|
|
881
888
|
var TypingIndicatorController = class _TypingIndicatorController extends Controller {
|
|
882
889
|
#numbers = new NumberValueReader();
|
|
883
890
|
static targets = ["input", "status"];
|
|
@@ -905,6 +912,7 @@ var TypingIndicatorController = class _TypingIndicatorController extends Control
|
|
|
905
912
|
#lastSentAt = 0;
|
|
906
913
|
#announceId = null;
|
|
907
914
|
#connected = false;
|
|
915
|
+
#listeners = new ListenerSet();
|
|
908
916
|
channelValueChanged() {
|
|
909
917
|
this.#follow.schedule();
|
|
910
918
|
}
|
|
@@ -927,14 +935,14 @@ var TypingIndicatorController = class _TypingIndicatorController extends Control
|
|
|
927
935
|
connect() {
|
|
928
936
|
this.#connected = true;
|
|
929
937
|
this.#reset();
|
|
930
|
-
this.element
|
|
938
|
+
this.#listeners.add(this.element, "input", this.#onInput);
|
|
931
939
|
this.#follow.activate();
|
|
932
940
|
this.#open();
|
|
933
941
|
}
|
|
934
942
|
disconnect() {
|
|
935
943
|
this.#connected = false;
|
|
936
944
|
this.#follow.cancel();
|
|
937
|
-
this.
|
|
945
|
+
this.#listeners.dispose();
|
|
938
946
|
this.#close();
|
|
939
947
|
this.#reset();
|
|
940
948
|
}
|
|
@@ -1034,10 +1042,10 @@ var TypingIndicatorController = class _TypingIndicatorController extends Control
|
|
|
1034
1042
|
if (names.length === 1) {
|
|
1035
1043
|
const template2 = this.statusTarget.dataset.one;
|
|
1036
1044
|
const name = names[0] ?? "";
|
|
1037
|
-
return template2 ?
|
|
1045
|
+
return template2 ? fillTemplate(template2, { name }) : `${name} is typing\u2026`;
|
|
1038
1046
|
}
|
|
1039
1047
|
const template = this.statusTarget.dataset.many;
|
|
1040
|
-
return template ?
|
|
1048
|
+
return template ? fillTemplate(template, { names: joined, count: names.length }) : `${joined} are typing\u2026`;
|
|
1041
1049
|
}
|
|
1042
1050
|
get #safeTimeout() {
|
|
1043
1051
|
return this.#numbers.read(
|