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
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
},
|
|
40
40
|
"stimeo--calendar": {
|
|
41
41
|
"file": "examples/calendar/_demo.html.erb",
|
|
42
|
-
"source": "<%# Markup for the calendar (APG Date Picker Dialog) demo.\n stimeo--calendar provides the displayed month label via Intl.DateTimeFormat,\n date navigation via roving focus, month transitions, 42-cell sync, and min/max\n boundary limits. %>\n<div\n class=\"calendar-demo demo-card\"\n data-controller=\"stimeo--calendar\"\n data-stimeo--calendar-month-value=\"<%= Time.current.strftime(\"%Y-%m\") %>\"\n data-stimeo--calendar-selected-value=\"<%= Time.current.strftime(\"%Y-%m-%d\") %>\"\n data-stimeo--calendar-min-value=\"<%= (Time.current - 1.month).beginning_of_month.strftime(\n \"%Y-%m-%d\"\n ) %>\"\n data-stimeo--calendar-max-value=\"<%= (Time.current + 2.months).end_of_month.strftime(\n \"%Y-%m-%d\"\n ) %>\"\n data-stimeo--calendar-week-start-value=\"0\"\n>\n <%# The hidden fields carry the selected day and the painted month into the\n form, so a server can serve the days it is showing. Both are optional. %>\n <input type=\"hidden\" name=\"on\" data-stimeo--calendar-target=\"field\" />\n <input type=\"hidden\" name=\"month\" data-stimeo--calendar-target=\"monthField\" />\n \n <div class=\"calendar-demo__header\">\n <button\n class=\"calendar-demo__btn\"\n type=\"button\"\n data-action=\"click->stimeo--calendar#prev\"\n aria-label=\"<%= t(\"components.calendar.demo.prev_month\") %>\"\n >\n <svg\n class=\"calendar-demo__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"15 18 9 12 15 6\"></polyline>\n </svg>\n </button>\n <span\n class=\"calendar-demo__label\"\n data-stimeo--calendar-target=\"label\"\n ></span>\n <button\n class=\"calendar-demo__btn\"\n type=\"button\"\n data-action=\"click->stimeo--calendar#next\"\n aria-label=\"<%= t(\"components.calendar.demo.next_month\") %>\"\n >\n <svg\n class=\"calendar-demo__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"9 18 15 12 9 6\"></polyline>\n </svg>\n </button>\n </div>\n\n <table class=\"calendar-demo__table\" role=\"grid\">\n <thead>\n <tr role=\"row\">\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.sunday\") %>\"\n >\n <%= t(\"components.calendar.demo.sunday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.monday\") %>\"\n >\n <%= t(\"components.calendar.demo.monday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.tuesday\") %>\"\n >\n <%= t(\"components.calendar.demo.tuesday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.wednesday\") %>\"\n >\n <%= t(\"components.calendar.demo.wednesday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.thursday\") %>\"\n >\n <%= t(\"components.calendar.demo.thursday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.friday\") %>\"\n >\n <%= t(\"components.calendar.demo.friday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.saturday\") %>\"\n >\n <%= t(\"components.calendar.demo.saturday\")[0] %>\n </th>\n </tr>\n </thead>\n <tbody\n data-stimeo--calendar-target=\"grid\"\n data-action=\"\n keydown->stimeo--calendar#onKeydown\n click->stimeo--calendar#
|
|
42
|
+
"source": "<%# Markup for the calendar (APG Date Picker Dialog) demo.\n stimeo--calendar provides the displayed month label via Intl.DateTimeFormat,\n date navigation via roving focus, month transitions, 42-cell sync, and min/max\n boundary limits. %>\n<div\n class=\"calendar-demo demo-card\"\n data-controller=\"stimeo--calendar\"\n data-stimeo--calendar-month-value=\"<%= Time.current.strftime(\"%Y-%m\") %>\"\n data-stimeo--calendar-selected-value=\"<%= Time.current.strftime(\"%Y-%m-%d\") %>\"\n data-stimeo--calendar-min-value=\"<%= (Time.current - 1.month).beginning_of_month.strftime(\n \"%Y-%m-%d\"\n ) %>\"\n data-stimeo--calendar-max-value=\"<%= (Time.current + 2.months).end_of_month.strftime(\n \"%Y-%m-%d\"\n ) %>\"\n data-stimeo--calendar-week-start-value=\"0\"\n>\n <%# The hidden fields carry the selected day and the painted month into the\n form, so a server can serve the days it is showing. Both are optional. %>\n <input type=\"hidden\" name=\"on\" data-stimeo--calendar-target=\"field\" />\n <input type=\"hidden\" name=\"month\" data-stimeo--calendar-target=\"monthField\" />\n \n <div class=\"calendar-demo__header\">\n <button\n class=\"calendar-demo__btn\"\n type=\"button\"\n data-action=\"click->stimeo--calendar#prev\"\n aria-label=\"<%= t(\"components.calendar.demo.prev_month\") %>\"\n >\n <svg\n class=\"calendar-demo__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"15 18 9 12 15 6\"></polyline>\n </svg>\n </button>\n <span\n class=\"calendar-demo__label\"\n data-stimeo--calendar-target=\"label\"\n ></span>\n <button\n class=\"calendar-demo__btn\"\n type=\"button\"\n data-action=\"click->stimeo--calendar#next\"\n aria-label=\"<%= t(\"components.calendar.demo.next_month\") %>\"\n >\n <svg\n class=\"calendar-demo__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"9 18 15 12 9 6\"></polyline>\n </svg>\n </button>\n </div>\n\n <table class=\"calendar-demo__table\" role=\"grid\">\n <thead>\n <tr role=\"row\">\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.sunday\") %>\"\n >\n <%= t(\"components.calendar.demo.sunday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.monday\") %>\"\n >\n <%= t(\"components.calendar.demo.monday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.tuesday\") %>\"\n >\n <%= t(\"components.calendar.demo.tuesday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.wednesday\") %>\"\n >\n <%= t(\"components.calendar.demo.wednesday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.thursday\") %>\"\n >\n <%= t(\"components.calendar.demo.thursday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.friday\") %>\"\n >\n <%= t(\"components.calendar.demo.friday\")[0] %>\n </th>\n <th\n scope=\"col\"\n aria-label=\"<%= t(\"components.calendar.demo.saturday\") %>\"\n >\n <%= t(\"components.calendar.demo.saturday\")[0] %>\n </th>\n </tr>\n </thead>\n <tbody\n data-stimeo--calendar-target=\"grid\"\n data-action=\"\n keydown->stimeo--calendar#onKeydown\n click->stimeo--calendar#select\n \"\n >\n <% 6.times do %>\n <tr role=\"row\">\n <% 7.times do %>\n <td\n role=\"gridcell\"\n class=\"calendar-demo__cell\"\n data-stimeo--calendar-target=\"day\"\n tabindex=\"-1\"\n ></td>\n <% end %>\n </tr>\n <% end %>\n </tbody>\n </table>\n</div>\n\n<%# Readout: what the component just reported. Purely visual — the component\n already announces what a screen reader needs, so this line is aria-hidden to\n keep it from being read twice. The value is a code fragment (API identifiers\n and values), so only the label is translated. %>\n<p class=\"demo-readout\" aria-hidden=\"true\">\n <span><%= t(\"catalog.readout.field\") %></span>\n <span class=\"demo-readout__value\" data-readout\n data-empty-text=\"<%= t(\"catalog.readout.empty\") %>\">—</span>\n</p>\n"
|
|
43
43
|
},
|
|
44
44
|
"stimeo--carousel": {
|
|
45
45
|
"file": "examples/carousel/_demo.html.erb",
|
|
46
|
-
"source": "<%# Markup for the carousel demo.\n The library handles slide advance, autoplay, syncing the current slide's\n data-state / hidden / inert, the pickers' (tabs) aria-selected and roving, the\n aria-disabled of controls that cannot be reached, and the viewport's aria-live.\n There is no data-action anywhere: the controller delegates clicks, picker keys,\n hover, and focus from its own element, so the markup only declares targets.\n Autoplay deliberately demonstrates WCAG 2.2.2: the play toggle is what stops it for\n good, while hovering, focusing, or backgrounding the tab only suspends it until that\n condition ends. This is spelled out in the on-screen note below the carousel.\n Transitions and layout are the consumer's CSS. %>\n<section\n class=\"carousel\"\n data-controller=\"stimeo--carousel\"\n aria-roledescription=\"carousel\"\n aria-label=\"<%= t(\"components.carousel.demo.label\") %>\"\n data-stimeo--carousel-autoplay-value=\"false\"\n data-stimeo--carousel-interval-value=\"2500\"\n data-stimeo--carousel-loop-value=\"true\">\n <div class=\"carousel__bar\">\n <button\n type=\"button\"\n class=\"carousel__play\"\n aria-label=\"<%= t(\"components.carousel.demo.autoplay\") %>\"\n data-stimeo--carousel-target=\"playToggle\">\n <%# The library owns aria-pressed (derived from the autoplay Value, whether a slide\n is left to rotate to, and the reduced-motion preference) and the hidden of the\n two glyph halves: ❚❚ shows while autoplay runs, ▶ while it is stopped. The\n icons are decorative; the accessible name comes from the aria-label above and\n stays the same in both states. %>\n <span aria-hidden=\"true\" data-stimeo--carousel-target=\"offLabel\">▶</span>\n <span aria-hidden=\"true\" hidden data-stimeo--carousel-target=\"onLabel\">❚❚</span>\n </button>\n <%# A visual read-out only. The library makes the viewport the live region, so a\n second one here would make a screen reader announce the change twice. %>\n <p\n class=\"carousel__status\"\n data-carousel-status\n data-template=\"<%= t(\"components.carousel.demo.status_template\") %>\"\n data-playing-suffix=\"<%= t(\"components.carousel.demo.status_playing\") %>\"></p>\n </div>\n\n <div class=\"carousel__viewport\" data-stimeo--carousel-target=\"viewport\">\n <% t(\"components.carousel.demo.slides\").each_with_index do |slide, i| %>\n <div\n id=\"carousel-slide-<%= i + 1 %>\"\n class=\"carousel__slide\"\n role=\"tabpanel\"\n aria-roledescription=\"slide\"\n aria-label=\"<%= \"#{i + 1} of #{t('components.carousel.demo.slides').size}\" %>\"\n aria-labelledby=\"carousel-dot-<%= i + 1 %>\"\n data-stimeo--carousel-target=\"slide\"\n <%= \"hidden inert\" if i.positive? %>>\n <h3 class=\"carousel__title\"><%= slide[:title] %></h3>\n <p><%= slide[:body] %></p>\n </div>\n <% end %>\n </div>\n\n <div class=\"carousel__nav\">\n <button type=\"button\" class=\"carousel__arrow\"\n aria-label=\"<%= t(\"components.carousel.demo.prev\") %>\"\n data-stimeo--carousel-target=\"prev\">‹</button>\n <button type=\"button\" class=\"carousel__arrow\"\n aria-label=\"<%= t(\"components.carousel.demo.next\") %>\"\n data-stimeo--carousel-target=\"next\">›</button>\n </div>\n\n <div class=\"carousel__dots\" role=\"tablist\"\n aria-label=\"<%= t(\"components.carousel.demo.tablist\") %>\">\n <% t(\"components.carousel.demo.slides\").each_with_index do |slide, i| %>\n <button\n id=\"carousel-dot-<%= i + 1 %>\"\n class=\"carousel__dot\"\n role=\"tab\"\n aria-selected=\"<%= i.zero? %>\"\n aria-controls=\"carousel-slide-<%= i + 1 %>\"\n aria-label=\"<%= slide[:title] %>\"\n tabindex=\"<%= i.zero? ? 0 : -1 %>\"\n data-stimeo--carousel-target=\"picker\"></button>\n <% end %>\n </div>\n</section>\n\n<%# On-screen explanation of the deliberate autoplay accessibility behavior, so the\n
|
|
46
|
+
"source": "<%# Markup for the carousel demo.\n The library handles slide advance, autoplay, syncing the current slide's\n data-state / hidden / inert, the pickers' (tabs) aria-selected and roving, the\n aria-disabled of controls that cannot be reached, and the viewport's aria-live.\n There is no data-action anywhere: the controller delegates clicks, picker keys,\n hover, and focus from its own element, so the markup only declares targets.\n Autoplay deliberately demonstrates WCAG 2.2.2: the play toggle is what stops it for\n good, while hovering, focusing, or backgrounding the tab only suspends it until that\n condition ends. This is spelled out in the on-screen note below the carousel.\n Transitions and layout are the consumer's CSS. %>\n<section\n class=\"carousel\"\n data-controller=\"stimeo--carousel\"\n aria-roledescription=\"carousel\"\n aria-label=\"<%= t(\"components.carousel.demo.label\") %>\"\n data-stimeo--carousel-autoplay-value=\"false\"\n data-stimeo--carousel-interval-value=\"2500\"\n data-stimeo--carousel-loop-value=\"true\">\n <div class=\"carousel__bar\">\n <button\n type=\"button\"\n class=\"carousel__play\"\n aria-label=\"<%= t(\"components.carousel.demo.autoplay\") %>\"\n data-stimeo--carousel-target=\"playToggle\">\n <%# The library owns aria-pressed (derived from the autoplay Value, whether a slide\n is left to rotate to, and the reduced-motion preference) and the hidden of the\n two glyph halves: ❚❚ shows while autoplay runs, ▶ while it is stopped. The\n icons are decorative; the accessible name comes from the aria-label above and\n stays the same in both states. %>\n <span aria-hidden=\"true\" data-stimeo--carousel-target=\"offLabel\">▶</span>\n <span aria-hidden=\"true\" hidden data-stimeo--carousel-target=\"onLabel\">❚❚</span>\n </button>\n <%# A visual read-out only. The library makes the viewport the live region, so a\n second one here would make a screen reader announce the change twice. %>\n <p\n class=\"carousel__status\"\n data-carousel-status\n data-template=\"<%= t(\"components.carousel.demo.status_template\") %>\"\n data-playing-suffix=\"<%= t(\"components.carousel.demo.status_playing\") %>\"></p>\n </div>\n\n <div class=\"carousel__viewport\" data-stimeo--carousel-target=\"viewport\">\n <% t(\"components.carousel.demo.slides\").each_with_index do |slide, i| %>\n <div\n id=\"carousel-slide-<%= i + 1 %>\"\n class=\"carousel__slide\"\n role=\"tabpanel\"\n aria-roledescription=\"slide\"\n aria-label=\"<%= \"#{i + 1} of #{t('components.carousel.demo.slides').size}\" %>\"\n aria-labelledby=\"carousel-dot-<%= i + 1 %>\"\n data-stimeo--carousel-target=\"slide\"\n <%= \"hidden inert\" if i.positive? %>>\n <h3 class=\"carousel__title\"><%= slide[:title] %></h3>\n <p><%= slide[:body] %></p>\n </div>\n <% end %>\n </div>\n\n <div class=\"carousel__nav\">\n <button type=\"button\" class=\"carousel__arrow\"\n aria-label=\"<%= t(\"components.carousel.demo.prev\") %>\"\n data-stimeo--carousel-target=\"prev\">‹</button>\n <button type=\"button\" class=\"carousel__arrow\"\n aria-label=\"<%= t(\"components.carousel.demo.next\") %>\"\n data-stimeo--carousel-target=\"next\">›</button>\n </div>\n\n <div class=\"carousel__dots\" role=\"tablist\" data-stimeo--carousel-target=\"pickerList\"\n aria-label=\"<%= t(\"components.carousel.demo.tablist\") %>\">\n <% t(\"components.carousel.demo.slides\").each_with_index do |slide, i| %>\n <button\n id=\"carousel-dot-<%= i + 1 %>\"\n class=\"carousel__dot\"\n role=\"tab\"\n aria-selected=\"<%= i.zero? %>\"\n aria-controls=\"carousel-slide-<%= i + 1 %>\"\n aria-label=\"<%= slide[:title] %>\"\n tabindex=\"<%= i.zero? ? 0 : -1 %>\"\n data-stimeo--carousel-target=\"picker\"></button>\n <% end %>\n </div>\n</section>\n\n<%# On-screen explanation of the deliberate autoplay accessibility behavior, so the\n hover and focus suspensions are understood as intentional (WCAG 2.2.2).\n Kept outside the <section> so reading it doesn't itself pause the carousel. %>\n<p class=\"carousel__hint\"><%= t(\"components.carousel.demo.hint\") %></p>\n"
|
|
47
47
|
},
|
|
48
48
|
"stimeo--character-counter": {
|
|
49
49
|
"file": "examples/character_counter/_demo.html.erb",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"stimeo--checkbox": {
|
|
53
53
|
"file": "examples/checkbox/_demo.html.erb",
|
|
54
|
-
"source": "<%# Markup for the checkbox (APG Checkbox / 3-state) demo.\n The parent (\"select all\") derives checked / indeterminate from the children's\n state, and a parent toggle sets all children at once. The aggregate state is\n reflected on the root's data-state (all/partial/none); the look is the consumer's CSS. %>\n<div class=\"checkbox-demo\" role=\"group\" aria-labelledby=\"cb-group-label\"\n data-controller=\"stimeo--checkbox\">\n <span class=\"checkbox-demo__legend\" id=\"cb-group-label\">\n <%= t(\"components.checkbox.demo.group\") %>\n </span>\n\n <label class=\"checkbox-demo__row checkbox-demo__row--parent\">\n <input type=\"checkbox\" data-stimeo--checkbox-target=\"parent\"\n data-action=\"change->stimeo--checkbox#onParentChange\" />\n <span><%= t(\"components.checkbox.demo.all\") %></span>\n </label>\n\n <div class=\"checkbox-demo__children\">\n <label class=\"checkbox-demo__row\">\n <input type=\"checkbox\" checked data-stimeo--checkbox-target=\"child\"\n data-action=\"change->stimeo--checkbox#onChildChange\" />\n <span><%= t(\"components.checkbox.demo.item_a\") %></span>\n </label>\n <label class=\"checkbox-demo__row\">\n <input type=\"checkbox\" data-stimeo--checkbox-target=\"child\"\n data-action=\"change->stimeo--checkbox#onChildChange\" />\n <span><%= t(\"components.checkbox.demo.item_b\") %></span>\n </label>\n <label class=\"checkbox-demo__row\">\n <input type=\"checkbox\" data-stimeo--checkbox-target=\"child\"\n data-action=\"change->stimeo--checkbox#onChildChange\" />\n <span><%= t(\"components.checkbox.demo.item_c\") %></span>\n </label>\n </div>\n\n <%#
|
|
54
|
+
"source": "<%# Markup for the checkbox (APG Checkbox / 3-state) demo.\n The parent (\"select all\") derives checked / indeterminate from the children's\n state, and a parent toggle sets all children at once. The aggregate state is\n reflected on the root's data-state (all/partial/none); the look is the consumer's CSS. %>\n<div class=\"checkbox-demo\" role=\"group\" aria-labelledby=\"cb-group-label\"\n data-controller=\"stimeo--checkbox\">\n <span class=\"checkbox-demo__legend\" id=\"cb-group-label\">\n <%= t(\"components.checkbox.demo.group\") %>\n </span>\n\n <label class=\"checkbox-demo__row checkbox-demo__row--parent\">\n <input type=\"checkbox\" data-stimeo--checkbox-target=\"parent\"\n data-action=\"change->stimeo--checkbox#onParentChange\" />\n <span><%= t(\"components.checkbox.demo.all\") %></span>\n </label>\n\n <div class=\"checkbox-demo__children\">\n <label class=\"checkbox-demo__row\">\n <input type=\"checkbox\" checked data-stimeo--checkbox-target=\"child\"\n data-action=\"change->stimeo--checkbox#onChildChange\" />\n <span><%= t(\"components.checkbox.demo.item_a\") %></span>\n </label>\n <label class=\"checkbox-demo__row\">\n <input type=\"checkbox\" data-stimeo--checkbox-target=\"child\"\n data-action=\"change->stimeo--checkbox#onChildChange\" />\n <span><%= t(\"components.checkbox.demo.item_b\") %></span>\n </label>\n <label class=\"checkbox-demo__row\">\n <input type=\"checkbox\" data-stimeo--checkbox-target=\"child\"\n data-action=\"change->stimeo--checkbox#onChildChange\" />\n <span><%= t(\"components.checkbox.demo.item_c\") %></span>\n </label>\n </div>\n\n <%# Show the selected count after individual edits and aggregate changes (updated by demo.js). %>\n <p class=\"checkbox-demo__status\" aria-live=\"polite\">\n <span data-checkbox-count>1</span> <%= t(\"components.checkbox.demo.selected\") %>\n </p>\n</div>\n"
|
|
55
55
|
},
|
|
56
56
|
"stimeo--clipboard": {
|
|
57
57
|
"file": "examples/clipboard/_demo.html.erb",
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
},
|
|
68
68
|
"stimeo--combobox": {
|
|
69
69
|
"file": "examples/combobox/_demo.html.erb",
|
|
70
|
-
"source": "<%# Markup for the combobox (APG Combobox / list autocomplete) demo.\n stimeo--combobox provides list filtering on input, Arrow/Enter/Esc, and\n aria-activedescendant. Focus stays on the input and the active option is shown via\n aria-selected. On selection, data-value (or the text, if absent) is placed in the input. %>\n<div class=\"combobox\" data-controller=\"stimeo--combobox\">\n <label id=\"fruit-label\" class=\"combobox__label\" for=\"fruit-input\"><%= t(\n \"components.combobox.demo.label\"\n ) %></label>\n <input\n id=\"fruit-input\"\n type=\"text\"\n class=\"combobox__input\"\n role=\"combobox\"\n aria-expanded=\"false\"\n aria-autocomplete=\"list\"\n aria-controls=\"fruit-list\"\n autocomplete=\"off\"\n data-stimeo--combobox-target=\"input\"\n data-action=\"input->stimeo--combobox#filter\n keydown->stimeo--combobox#onKeydown\n focus->stimeo--combobox#open\n click->stimeo--combobox#open\">\n\n <ul\n id=\"fruit-list\"\n class=\"combobox__list\"\n role=\"listbox\"\n aria-labelledby=\"fruit-label\"\n data-stimeo--combobox-target=\"list\"\n hidden>\n
|
|
70
|
+
"source": "<%# Markup for the combobox (APG Combobox / list autocomplete) demo.\n stimeo--combobox provides list filtering on input, Arrow/Enter/Esc, and\n aria-activedescendant. Focus stays on the input and the active option is shown via\n aria-selected. On selection, data-value (or the text, if absent) is placed in the input. %>\n<div class=\"combobox\" data-controller=\"stimeo--combobox\">\n <label id=\"fruit-label\" class=\"combobox__label\" for=\"fruit-input\"><%= t(\n \"components.combobox.demo.label\"\n ) %></label>\n <input\n id=\"fruit-input\"\n type=\"text\"\n class=\"combobox__input\"\n role=\"combobox\"\n aria-expanded=\"false\"\n aria-autocomplete=\"list\"\n aria-controls=\"fruit-list\"\n autocomplete=\"off\"\n data-stimeo--combobox-target=\"input\"\n data-action=\"input->stimeo--combobox#filter\n keydown->stimeo--combobox#onKeydown\n focus->stimeo--combobox#open\n click->stimeo--combobox#open\">\n\n <ul\n id=\"fruit-list\"\n class=\"combobox__list\"\n role=\"listbox\"\n aria-labelledby=\"fruit-label\"\n data-stimeo--combobox-target=\"list\"\n hidden>\n <% %w[apple apricot banana cherry].each do |fruit| %>\n <% label = t(\"components.combobox.demo.fruits.#{fruit}\") %>\n <li role=\"option\" id=\"fruit-<%= fruit %>\" class=\"combobox__option\" data-value=\"<%= label %>\"\n data-stimeo--combobox-target=\"option\"\n data-action=\"click->stimeo--combobox#select\"><%= label %></li>\n <% end %>\n </ul>\n\n <%# The no-results message is a region of the empty state: the library shows it while the\n open listbox has no match and hides it otherwise, so it is authored hidden. Copy via\n i18n. %>\n <div\n class=\"combobox__empty\"\n data-stimeo--combobox-target=\"empty\"\n hidden><%= t(\"components.combobox.demo.empty\") %></div>\n</div>\n"
|
|
71
71
|
},
|
|
72
72
|
"stimeo--command-palette": {
|
|
73
73
|
"file": "examples/command_palette/_demo.html.erb",
|
|
74
|
-
"source": "<%# Markup for the command_palette demo.\n The single source used for both the live render and the copy-paste code.\n stimeo--command-palette provides the global shortcut (Cmd+K) / arrow navigation /\n focus trap. The controller registers the global keydown itself in connect(), so no\n keydown wiring is needed here. %>\n<div\n class=\"command-palette-demo\"\n data-controller=\"stimeo--command-palette\">\n \n <button\n type=\"button\"\n class=\"demo-trigger\"\n data-action=\"click->stimeo--command-palette#open\">\n <%= t(\"components.command_palette.demo.open_button\") %>\n </button>\n <p class=\"command-palette-demo__help\">\n <%= t(\"components.command_palette.demo.help_text_html\") %>\n </p>\n\n <%# Overlay backdrop. Closes only on a click on the backdrop itself\n (closeOnBackdrop ignores inner clicks). %>\n <div\n class=\"command-palette\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"<%= t(\"components.command_palette.demo.popular_title\") %>\"\n data-stimeo--command-palette-target=\"dialog\"\n data-action=\"click->stimeo--command-palette#closeOnBackdrop\"\n hidden>\n \n <%# The palette body container. %>\n <div class=\"command-palette__panel\">\n <%# Control area (Combobox structure). role/aria-* go on the real input\n (the controller syncs them). %>\n <div class=\"command-palette__search-wrapper\">\n \n <svg class=\"command-palette__search-icon\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/>\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/>\n </svg>\n\n <input\n type=\"text\"\n placeholder=\"<%= t(\"components.command_palette.demo.placeholder\") %>\"\n class=\"command-palette__input\"\n data-stimeo--command-palette-target=\"input\"\n data-action=\"input->stimeo--command-palette#filter\n keydown->stimeo--command-palette#onKeydown\"\n role=\"combobox\"\n aria-expanded=\"false\"\n aria-haspopup=\"listbox\"\n aria-controls=\"playground-command-list\"\n aria-autocomplete=\"list\" />\n\n <button\n type=\"button\"\n class=\"command-palette__close-btn\"\n data-action=\"click->stimeo--command-palette#close\"\n aria-label=\"<%= t(\"components.command_palette.demo.close_label\") %>\">\n <kbd class=\"command-palette-demo__kbd font-normal text-xs\">ESC</kbd>\n </button>\n </div>\n\n <%# Listbox display area. %>\n <ul\n id=\"playground-command-list\"\n role=\"listbox\"\n aria-label=\"<%= t(\"components.command_palette.demo.popular_title\") %>\"\n class=\"command-palette__listbox\"\n data-stimeo--command-palette-target=\"list\">\n \n <%# Section heading (data-disabled=\"true\" makes it non-selectable). %>\n <li id=\"cmd-popular-heading\" role=\"option\"\n data-stimeo--command-palette-target=\"option\"\n data-disabled=\"true\" class=\"command-palette__group-title\">\n <%= t(\"components.command_palette.demo.popular_title\") %>\n </li>\n\n <li\n id=\"cmd-profile\"\n role=\"option\"\n data-stimeo--command-palette-target=\"option\"\n data-action=\"click->stimeo--command-palette#
|
|
74
|
+
"source": "<%# Markup for the command_palette demo.\n The single source used for both the live render and the copy-paste code.\n stimeo--command-palette provides the global shortcut (Cmd+K) / arrow navigation /\n focus trap. The controller registers the global keydown itself in connect(), so no\n keydown wiring is needed here. %>\n<div\n class=\"command-palette-demo\"\n data-controller=\"stimeo--command-palette\">\n \n <button\n type=\"button\"\n class=\"demo-trigger\"\n data-action=\"click->stimeo--command-palette#open\">\n <%= t(\"components.command_palette.demo.open_button\") %>\n </button>\n <p class=\"command-palette-demo__help\">\n <%= t(\"components.command_palette.demo.help_text_html\") %>\n </p>\n\n <%# Overlay backdrop. Closes only on a click on the backdrop itself\n (closeOnBackdrop ignores inner clicks). %>\n <div\n class=\"command-palette\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"<%= t(\"components.command_palette.demo.popular_title\") %>\"\n data-stimeo--command-palette-target=\"dialog\"\n data-action=\"click->stimeo--command-palette#closeOnBackdrop\"\n hidden>\n \n <%# The palette body container. %>\n <div class=\"command-palette__panel\">\n <%# Control area (Combobox structure). role/aria-* go on the real input\n (the controller syncs them). %>\n <div class=\"command-palette__search-wrapper\">\n \n <svg class=\"command-palette__search-icon\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/>\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/>\n </svg>\n\n <input\n type=\"text\"\n placeholder=\"<%= t(\"components.command_palette.demo.placeholder\") %>\"\n class=\"command-palette__input\"\n data-stimeo--command-palette-target=\"input\"\n data-action=\"input->stimeo--command-palette#filter\n keydown->stimeo--command-palette#onKeydown\"\n role=\"combobox\"\n aria-expanded=\"false\"\n aria-haspopup=\"listbox\"\n aria-controls=\"playground-command-list\"\n aria-autocomplete=\"list\" />\n\n <button\n type=\"button\"\n class=\"command-palette__close-btn\"\n data-action=\"click->stimeo--command-palette#close\"\n aria-label=\"<%= t(\"components.command_palette.demo.close_label\") %>\">\n <kbd class=\"command-palette-demo__kbd font-normal text-xs\">ESC</kbd>\n </button>\n </div>\n\n <%# Listbox display area. %>\n <ul\n id=\"playground-command-list\"\n role=\"listbox\"\n aria-label=\"<%= t(\"components.command_palette.demo.popular_title\") %>\"\n class=\"command-palette__listbox\"\n data-stimeo--command-palette-target=\"list\">\n \n <%# Section heading (data-disabled=\"true\" makes it non-selectable). %>\n <li id=\"cmd-popular-heading\" role=\"option\"\n data-stimeo--command-palette-target=\"option\"\n data-disabled=\"true\" class=\"command-palette__group-title\">\n <%= t(\"components.command_palette.demo.popular_title\") %>\n </li>\n\n <li\n id=\"cmd-profile\"\n role=\"option\"\n data-stimeo--command-palette-target=\"option\"\n data-action=\"click->stimeo--command-palette#select\"\n data-alert=\"<%= t(\"components.command_palette.demo.profile_alert\") %>\"\n class=\"command-palette__option\">\n <svg class=\"command-palette__option-icon\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/>\n <circle cx=\"12\" cy=\"7\" r=\"4\"/>\n </svg>\n <span class=\"command-palette__option-text\"><%= t(\n \"components.command_palette.demo.profile_label\"\n ) %></span>\n <span class=\"command-palette__option-shortcut\">Go P</span>\n </li>\n\n <li\n id=\"cmd-settings\"\n role=\"option\"\n data-stimeo--command-palette-target=\"option\"\n data-action=\"click->stimeo--command-palette#select\"\n data-alert=\"<%= t(\"components.command_palette.demo.settings_alert\") %>\"\n class=\"command-palette__option\">\n <svg class=\"command-palette__option-icon\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"3\"/>\n <path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65\n 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0\n 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65\n 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0\n 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0\n 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1\n 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0\n 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0\n 0-1.51 1z\"/>\n </svg>\n <span class=\"command-palette__option-text\"><%= t(\n \"components.command_palette.demo.settings_label\"\n ) %></span>\n <span class=\"command-palette__option-shortcut\">Go S</span>\n </li>\n\n <li id=\"cmd-admin-heading\" role=\"option\"\n data-stimeo--command-palette-target=\"option\"\n data-disabled=\"true\" class=\"command-palette__group-title\">\n <%= t(\"components.command_palette.demo.admin_title\") %>\n </li>\n\n <li\n id=\"cmd-theme-dark\"\n role=\"option\"\n data-stimeo--command-palette-target=\"option\"\n data-action=\"click->stimeo--command-palette#select\"\n data-alert=\"<%= t(\"components.command_palette.demo.dark_alert\") %>\"\n class=\"command-palette__option\">\n <svg class=\"command-palette__option-icon\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"/>\n </svg>\n <span class=\"command-palette__option-text\"><%= t(\n \"components.command_palette.demo.dark_label\"\n ) %></span>\n </li>\n\n <li\n id=\"cmd-theme-light\"\n role=\"option\"\n data-stimeo--command-palette-target=\"option\"\n data-action=\"click->stimeo--command-palette#select\"\n data-alert=\"<%= t(\"components.command_palette.demo.light_alert\") %>\"\n class=\"command-palette__option\">\n <svg class=\"command-palette__option-icon\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"5\"/>\n <line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"3\"/>\n <line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"23\"/>\n <line x1=\"4.22\" y1=\"4.22\" x2=\"5.64\" y2=\"5.64\"/>\n <line x1=\"18.36\" y1=\"18.36\" x2=\"19.78\" y2=\"19.78\"/>\n <line x1=\"1\" y1=\"12\" x2=\"3\" y2=\"12\"/>\n <line x1=\"21\" y1=\"12\" x2=\"23\" y2=\"12\"/>\n <line x1=\"4.22\" y1=\"19.78\" x2=\"5.64\" y2=\"18.36\"/>\n <line x1=\"18.36\" y1=\"5.64\" x2=\"19.78\" y2=\"4.22\"/>\n </svg>\n <span class=\"command-palette__option-text\"><%= t(\n \"components.command_palette.demo.light_label\"\n ) %></span>\n </li>\n </ul>\n </div>\n </div>\n</div>\n"
|
|
75
75
|
},
|
|
76
76
|
"stimeo--conditional-fields": {
|
|
77
77
|
"file": "examples/conditional_fields/_demo.html.erb",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
},
|
|
84
84
|
"stimeo--context-menu": {
|
|
85
85
|
"file": "examples/context_menu/_demo.html.erb",
|
|
86
|
-
"source": "<%# Markup for the context_menu demo.\n A right-click on the region (or the ContextMenu key / Shift+F10) opens a\n role=\"menu\" at the pointer position. The
|
|
86
|
+
"source": "<%# Markup for the context_menu demo.\n A right-click on the region (or the ContextMenu key / Shift+F10) opens a\n role=\"menu\" at the pointer position. The menu itself follows the APG Menu\n pattern. The region's role and name are yours: here a named group, which\n advertises its opening key with aria-keyshortcuts. The click coordinate is\n reflected on the menu as --stimeo--context-menu-x / -y, and the Playground\n CSS uses it for top/left placement (works even without the positioning\n module). %>\n<div class=\"context-menu\" data-controller=\"stimeo--context-menu\">\n <div\n class=\"context-menu__region\"\n data-stimeo--context-menu-target=\"region\"\n tabindex=\"0\"\n role=\"group\"\n aria-label=\"<%= t(\"components.context_menu.demo.region_label\") %>\"\n aria-keyshortcuts=\"Shift+F10\"\n aria-controls=\"context-menu-list\"\n data-action=\"\n contextmenu->stimeo--context-menu#open\n keydown->stimeo--context-menu#onRegionKeydown\">\n <%= t(\"components.context_menu.demo.region\") %>\n </div>\n\n <ul\n class=\"context-menu__list\"\n id=\"context-menu-list\"\n role=\"menu\"\n aria-label=\"<%= t(\"components.context_menu.demo.label\") %>\"\n data-stimeo--context-menu-target=\"menu\"\n hidden>\n <li role=\"none\">\n <button type=\"button\" class=\"demo-menuitem\" role=\"menuitem\" tabindex=\"-1\"\n data-stimeo--context-menu-target=\"item\"\n data-action=\"\n click->stimeo--context-menu#activate\n keydown->stimeo--context-menu#onItemKeydown\">\n <%= t(\"components.context_menu.demo.copy\") %>\n </button>\n </li>\n <li role=\"none\">\n <button type=\"button\" class=\"demo-menuitem\" role=\"menuitem\" tabindex=\"-1\"\n data-stimeo--context-menu-target=\"item\"\n data-action=\"\n click->stimeo--context-menu#activate\n keydown->stimeo--context-menu#onItemKeydown\">\n <%= t(\"components.context_menu.demo.paste\") %>\n </button>\n </li>\n <li role=\"none\">\n <button type=\"button\" class=\"demo-menuitem\" role=\"menuitem\" tabindex=\"-1\"\n data-stimeo--context-menu-target=\"item\"\n data-action=\"\n click->stimeo--context-menu#activate\n keydown->stimeo--context-menu#onItemKeydown\">\n <%= t(\"components.context_menu.demo.delete\") %>\n </button>\n </li>\n </ul>\n</div>\n\n<%# Readout: what the component just reported. Purely visual — the component\n already announces what a screen reader needs, so this line is aria-hidden to\n keep it from being read twice. The value is a code fragment (API identifiers\n and values), so only the label is translated. %>\n<p class=\"demo-readout\" aria-hidden=\"true\">\n <span><%= t(\"catalog.readout.events\") %></span>\n <span class=\"demo-readout__value\" data-readout>—</span>\n</p>\n"
|
|
87
87
|
},
|
|
88
88
|
"stimeo--count-up": {
|
|
89
89
|
"file": "examples/count_up/_demo.html.erb",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
},
|
|
104
104
|
"stimeo--date-range-picker": {
|
|
105
105
|
"file": "examples/date_range_picker/_demo.html.erb",
|
|
106
|
-
"source": "<%# Markup for the date-range-picker (range-selection calendar) demo.\n stimeo--date-range-picker
|
|
106
|
+
"source": "<%# Markup for the date-range-picker (range-selection calendar) demo.\n stimeo--date-range-picker reuses stimeo--calendar's month-grid navigation model and\n handles two-point start/end selection, a provisional range preview mid-selection,\n marking in-range cells, auto-swapping when start > end, applying presets, and grid\n keyboard movement (roving). Range ends are shown with aria-selected and the inside\n with data-in-range; placement and styling live in demo.css.\n\n Two unavailable days are declared as data rather than written onto cells. The\n 42 cells are reused for a different date every month, so availability has to\n be keyed by the date; the controller derives each cell's aria-disabled from\n this array on every paint. A range may still span such a day — it just cannot\n end on one. %>\n<% blackout = [3.days.from_now, 4.days.from_now].map { |day| day.strftime(\"%Y-%m-%d\") } %>\n<div class=\"drp demo-card\" data-controller=\"stimeo--date-range-picker\"\n data-stimeo--date-range-picker-disabled-dates-value=\"<%= blackout.to_json %>\">\n <div class=\"drp__header\">\n <button class=\"drp__nav\" type=\"button\"\n data-action=\"click->stimeo--date-range-picker#prev\"\n aria-label=\"<%= t(\"components.date_range_picker.demo.prev_month\") %>\">‹</button>\n <span class=\"drp__label\" id=\"drp-month\" aria-live=\"polite\"\n data-stimeo--date-range-picker-target=\"monthLabel\"></span>\n <button class=\"drp__nav\" type=\"button\"\n data-action=\"click->stimeo--date-range-picker#next\"\n aria-label=\"<%= t(\"components.date_range_picker.demo.next_month\") %>\">›</button>\n </div>\n\n <div class=\"drp__weekdays\" aria-hidden=\"true\">\n <% t(\"components.date_range_picker.demo.weekdays\").each do |day| %>\n <span class=\"drp__weekday\"><%= day %></span>\n <% end %>\n </div>\n\n <div class=\"drp__grid\" role=\"grid\" aria-labelledby=\"drp-month\"\n data-stimeo--date-range-picker-target=\"grid\">\n <% 6.times do %>\n <div class=\"drp__row\" role=\"row\">\n <% 7.times do %>\n <button class=\"drp__cell\" type=\"button\" role=\"gridcell\" tabindex=\"-1\"\n data-stimeo--date-range-picker-target=\"cell\"\n data-action=\"click->stimeo--date-range-picker#selectDate\n mouseenter->stimeo--date-range-picker#previewTo\n focus->stimeo--date-range-picker#previewTo\n keydown->stimeo--date-range-picker#onKeydown\"></button>\n <% end %>\n </div>\n <% end %>\n </div>\n\n <div class=\"drp__presets\" role=\"group\"\n aria-label=\"<%= t(\"components.date_range_picker.demo.presets_label\") %>\">\n <button class=\"drp__preset\" type=\"button\" data-range=\"today\"\n data-action=\"click->stimeo--date-range-picker#applyPreset\">\n <%= t(\"components.date_range_picker.demo.preset_today\") %>\n </button>\n <button class=\"drp__preset\" type=\"button\" data-range=\"last7\"\n data-action=\"click->stimeo--date-range-picker#applyPreset\">\n <%= t(\"components.date_range_picker.demo.preset_last7\") %>\n </button>\n <button class=\"drp__preset\" type=\"button\" data-range=\"thisMonth\"\n data-action=\"click->stimeo--date-range-picker#applyPreset\">\n <%= t(\"components.date_range_picker.demo.preset_this_month\") %>\n </button>\n </div>\n\n <span class=\"drp__status\" role=\"status\" aria-live=\"polite\"\n data-stimeo--date-range-picker-target=\"status\"></span>\n\n <%# Says on screen why two days are struck out. The dates move with today, so\n without this the exclusion reads as a glitch rather than a demonstration. %>\n <p class=\"drp__note\"><%= t(\"components.date_range_picker.demo.blackout_note\") %></p>\n\n <input type=\"hidden\" name=\"start_date\" data-stimeo--date-range-picker-target=\"startField\" />\n <input type=\"hidden\" name=\"end_date\" data-stimeo--date-range-picker-target=\"endField\" />\n</div>\n\n<%# Readout: what the component just reported. Purely visual — the component\n already announces what a screen reader needs, so this line is aria-hidden to\n keep it from being read twice. The value is a code fragment (API identifiers\n and values), so only the label is translated. %>\n<p class=\"demo-readout\" aria-hidden=\"true\">\n <span><%= t(\"catalog.readout.field\") %></span>\n <span class=\"demo-readout__value\" data-readout\n data-empty-text=\"<%= t(\"catalog.readout.empty\") %>\">—</span>\n</p>\n"
|
|
107
107
|
},
|
|
108
108
|
"stimeo--dialog": {
|
|
109
109
|
"file": "examples/dialog/_demo.html.erb",
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
},
|
|
128
128
|
"stimeo--dropdown": {
|
|
129
129
|
"file": "examples/dropdown/_demo.html.erb",
|
|
130
|
-
"source": "<%# Markup for the dropdown demo.\n The single source used for both the live render and the copy-paste code.\n Connect to stimeo--dropdown via data-controller / data-*-target / data-action.\n The behavior is the library's; the look (classes) is the Playground's CSS. %>\n<div class=\"dropdown\" data-controller=\"stimeo--dropdown\">\n <button\n type=\"button\"\n class=\"demo-trigger\"\n aria-expanded=\"false\"\n data-stimeo--dropdown-target=\"trigger\"\n data-action=\"click->stimeo--dropdown#toggle\">\n <%= t(\"components.dropdown.demo.trigger\") %>\n </button>\n\n <%# The toggled menu. Starts hidden (closed).\n Each link
|
|
130
|
+
"source": "<%# Markup for the dropdown demo.\n The single source used for both the live render and the copy-paste code.\n Connect to stimeo--dropdown via data-controller / data-*-target / data-action.\n The behavior is the library's; the look (classes) is the Playground's CSS. %>\n<div class=\"dropdown\" data-controller=\"stimeo--dropdown\">\n <button\n type=\"button\"\n class=\"demo-trigger\"\n aria-expanded=\"false\"\n data-stimeo--dropdown-target=\"trigger\"\n data-action=\"click->stimeo--dropdown#toggle\">\n <%= t(\"components.dropdown.demo.trigger\") %>\n </button>\n\n <%# The toggled menu. Starts hidden (closed).\n Each placeholder link closes the menu and prevents navigation so the event\n readout stays visible. Real destination links can omit :prevent.\n (The links are inside the controller element, so an outside click won't close\n it — wire it explicitly.) %>\n <ul class=\"dropdown__menu\" data-stimeo--dropdown-target=\"menu\" hidden>\n <li><a class=\"demo-menuitem\" href=\"#profile\"\n data-action=\"click->stimeo--dropdown#close:prevent\"><%= t(\n \"components.dropdown.demo.profile\"\n ) %></a></li>\n <li><a class=\"demo-menuitem\" href=\"#settings\"\n data-action=\"click->stimeo--dropdown#close:prevent\"><%= t(\n \"components.dropdown.demo.settings\"\n ) %></a></li>\n <li><a class=\"demo-menuitem\" href=\"#sign-out\"\n data-action=\"click->stimeo--dropdown#close:prevent\"><%= t(\n \"components.dropdown.demo.sign_out\"\n ) %></a></li>\n </ul>\n</div>\n\n<%# Readout: what the component just reported. Purely visual — the component\n already announces what a screen reader needs, so this line is aria-hidden to\n keep it from being read twice. The value is a code fragment (API identifiers\n and values), so only the label is translated. %>\n<p class=\"demo-readout\" aria-hidden=\"true\">\n <span><%= t(\"catalog.readout.events\") %></span>\n <span class=\"demo-readout__value\" data-readout>—</span>\n</p>\n"
|
|
131
131
|
},
|
|
132
132
|
"stimeo--editable": {
|
|
133
133
|
"file": "examples/editable/_demo.html.erb",
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
},
|
|
152
152
|
"stimeo--focus": {
|
|
153
153
|
"file": "examples/focus/_demo.html.erb",
|
|
154
|
-
"source": "<%#
|
|
154
|
+
"source": "<%# stimeo--focus demo: the Activate button sits outside the scope, so it invokes the\n controller's activate action through the playground's exposed Stimulus app\n (window.Stimulus) in demo.js. Once active, Tab cycles within the box, focus lands on\n the initial target, and Escape or the Release button (a descendant, wired with a plain\n data-action) ends it and restores focus. inert is left off so the soft boundary does\n not isolate the rest of the catalog page. The library only manages focus and reflects\n data-focus-trapped; demo.css owns the look. %>\n<div class=\"focus-demo\">\n <button\n type=\"button\"\n class=\"demo-trigger\"\n data-focus-demo-activate\n aria-pressed=\"false\"\n data-activate-label=\"<%= t('components.focus.demo.activate') %>\"\n data-deactivate-label=\"<%= t('components.focus.demo.deactivate') %>\">\n <%= t(\"components.focus.demo.activate\") %>\n </button>\n\n <div class=\"focus-demo__scope\" data-controller=\"stimeo--focus\">\n <p class=\"focus-demo__hint\"><%= t(\"components.focus.demo.hint\") %></p>\n <label class=\"focus-demo__field\">\n <span><%= t(\"components.focus.demo.field\") %></span>\n <input type=\"text\" class=\"demo-input\" data-stimeo--focus-target=\"initial\" />\n </label>\n <div class=\"focus-demo__bar\">\n <button type=\"button\" class=\"demo-trigger\"><%= t(\"components.focus.demo.inner\") %></button>\n <button type=\"button\" class=\"demo-trigger\" data-action=\"click->stimeo--focus#deactivate\">\n <%= t(\"components.focus.demo.release\") %>\n </button>\n </div>\n </div>\n</div>\n"
|
|
155
155
|
},
|
|
156
156
|
"stimeo--form-field": {
|
|
157
157
|
"file": "examples/form_field/_demo.html.erb",
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
},
|
|
224
224
|
"stimeo--navigation-menu": {
|
|
225
225
|
"file": "examples/navigation_menu/_demo.html.erb",
|
|
226
|
-
"source": "<%# Markup for the navigation-menu demo.\n Two arrangements are shown.\n\n 1. Click-only (the default): a global nav where each top item opens/closes a\n sub-panel (a set of links). The contents are links and don't use role=\"menu\"\n (APG Disclosure navigation). The library handles syncing aria-expanded,\n single-open behavior, closing on Escape / outside click / focus leaving, and\n moving between top items with the left/right keys.\n 2. Hover (opt-in): openOnHover plus a hoverArea wrapper — the APG \"Disclosure\n Navigation with Top-Level Links\" arrangement, where each <li> holds a real\n link, a small disclosure button, and the panel. Hovering anywhere over the\n <li> opens that item's panel; every keyboard path stays identical.\n\n Panel placement and styling are the consumer's CSS (demo.css). %>\n<p class=\"nav-menu__caption\"><%= t(\"components.navigation_menu.demo.click_caption\") %></p>\n<nav class=\"nav-menu\" data-controller=\"stimeo--navigation-menu\"\n aria-label=\"<%= t(\"components.navigation_menu.demo.label\") %>\">\n <ul class=\"nav-menu__list\">\n <li class=\"nav-menu__item\">\n <button\n type=\"button\"\n class=\"demo-baritem\"\n aria-expanded=\"false\"\n aria-controls=\"nav-menu-products\"\n data-stimeo--navigation-menu-target=\"trigger\"\n data-action=\"click->stimeo--navigation-menu#toggle\n keydown->stimeo--navigation-menu#onTriggerKeydown\">\n <%= t(\"components.navigation_menu.demo.products.label\") %>\n </button>\n <div id=\"nav-menu-products\" class=\"nav-menu__panel\"\n data-stimeo--navigation-menu-target=\"panel\" hidden>\n <a class=\"demo-menuitem\" href=\"#analytics\"><%= t(\n \"components.navigation_menu.demo.products.links.analytics\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#automation\"><%= t(\n \"components.navigation_menu.demo.products.links.automation\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#reports\"><%= t(\n \"components.navigation_menu.demo.products.links.reports\"\n ) %></a>\n </div>\n </li>\n <li class=\"nav-menu__item\">\n <button\n type=\"button\"\n class=\"demo-baritem\"\n aria-expanded=\"false\"\n aria-controls=\"nav-menu-company\"\n data-stimeo--navigation-menu-target=\"trigger\"\n data-action=\"click->stimeo--navigation-menu#toggle\n keydown->stimeo--navigation-menu#onTriggerKeydown\">\n <%= t(\"components.navigation_menu.demo.company.label\") %>\n </button>\n <div id=\"nav-menu-company\" class=\"nav-menu__panel\"\n data-stimeo--navigation-menu-target=\"panel\" hidden>\n <a class=\"demo-menuitem\" href=\"#about\"><%= t(\n \"components.navigation_menu.demo.company.links.about\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#careers\"><%= t(\n \"components.navigation_menu.demo.company.links.careers\"\n ) %></a>\n </div>\n </li>\n </ul>\n</nav>\n\n<p class=\"nav-menu__caption\"><%= t(\"components.navigation_menu.demo.hover_caption\") %></p>\n<%# openOnHover is opt-in; hoverArea widens the hover region to the whole <li>, so\n hovering the top-level link (not just the disclosure button) opens the panel.\n The button keeps its own accessible name so keyboard and SR users can tell the\n link and its disclosure apart. %>\n<nav class=\"nav-menu\" data-controller=\"stimeo--navigation-menu\"\n data-stimeo--navigation-menu-open-on-hover-value=\"true\"\n aria-label=\"<%= t(\"components.navigation_menu.demo.hover.label\") %>\">\n <ul class=\"nav-menu__list\">\n <li class=\"nav-menu__item\" data-stimeo--navigation-menu-target=\"hoverArea\">\n <a class=\"demo-baritem nav-menu__link\" href=\"#solutions\">\n <%= t(\"components.navigation_menu.demo.hover.solutions.label\") %>\n </a>\n <button\n type=\"button\"\n class=\"demo-baritem nav-menu__disclosure\"\n aria-expanded=\"false\"\n aria-controls=\"nav-menu-solutions\"\n data-stimeo--navigation-menu-target=\"trigger\"\n data-action=\"click->stimeo--navigation-menu#toggle\n keydown->stimeo--navigation-menu#onTriggerKeydown\">\n <span aria-hidden=\"true\">▾</span>\n <span class=\"visually-hidden\"><%= t(\n \"components.navigation_menu.demo.hover.solutions.toggle\"\n ) %></span>\n </button>\n <div id=\"nav-menu-solutions\" class=\"nav-menu__panel\"\n data-stimeo--navigation-menu-target=\"panel\" hidden>\n <a class=\"demo-menuitem\" href=\"#retail\"><%= t(\n \"components.navigation_menu.demo.hover.solutions.links.retail\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#finance\"><%= t(\n \"components.navigation_menu.demo.hover.solutions.links.finance\"\n ) %></a>\n </div>\n </li>\n <li class=\"nav-menu__item\" data-stimeo--navigation-menu-target=\"hoverArea\">\n <a class=\"demo-baritem nav-menu__link\" href=\"#resources\">\n <%= t(\"components.navigation_menu.demo.hover.resources.label\") %>\n </a>\n <button\n type=\"button\"\n class=\"demo-baritem nav-menu__disclosure\"\n aria-expanded=\"false\"\n aria-controls=\"nav-menu-resources\"\n data-stimeo--navigation-menu-target=\"trigger\"\n data-action=\"click->stimeo--navigation-menu#toggle\n keydown->stimeo--navigation-menu#onTriggerKeydown\">\n <span aria-hidden=\"true\">▾</span>\n <span class=\"visually-hidden\"><%= t(\n \"components.navigation_menu.demo.hover.resources.toggle\"\n ) %></span>\n </button>\n <div id=\"nav-menu-resources\" class=\"nav-menu__panel\"\n data-stimeo--navigation-menu-target=\"panel\" hidden>\n <a class=\"demo-menuitem\" href=\"#guides\"><%= t(\n \"components.navigation_menu.demo.hover.resources.links.guides\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#blog\"><%= t(\n \"components.navigation_menu.demo.hover.resources.links.blog\"\n ) %></a>\n </div>\n </li>\n </ul>\n</nav>\n\n<%# Readout: what the component just reported. Purely visual — the component\n already announces what a screen reader needs, so this line is aria-hidden to\n keep it from being read twice. The value is a code fragment (API identifiers\n and values), so only the label is translated. %>\n<p class=\"demo-readout\" aria-hidden=\"true\">\n <span><%= t(\"catalog.readout.events\") %></span>\n <span class=\"demo-readout__value\" data-readout>—</span>\n</p>\n"
|
|
226
|
+
"source": "<%# Markup for the navigation-menu demo.\n Two arrangements are shown.\n\n 1. Click-only (the default): a global nav where each top item opens/closes a\n sub-panel (a set of links). The contents are links and don't use role=\"menu\"\n (APG Disclosure navigation). The library handles syncing aria-expanded,\n single-open behavior, closing on Escape / outside click / focus leaving, and\n moving between top items with the left/right keys.\n 2. Hover (opt-in): openOnHover plus a hoverArea wrapper — the APG \"Disclosure\n Navigation with Top-Level Links\" arrangement, where each <li> holds a real\n link, a small disclosure button, and the panel. Hovering anywhere over the\n <li> opens that item's panel; every keyboard path stays identical.\n\n Panel placement and styling are the consumer's CSS (demo.css). %>\n<p class=\"nav-menu__caption\"><%= t(\"components.navigation_menu.demo.click_caption\") %></p>\n<nav class=\"nav-menu\" data-controller=\"stimeo--navigation-menu\"\n aria-label=\"<%= t(\"components.navigation_menu.demo.label\") %>\">\n <ul class=\"nav-menu__list\" data-stimeo--navigation-menu-target=\"list\">\n <li class=\"nav-menu__item\">\n <button\n type=\"button\"\n class=\"demo-baritem\"\n aria-expanded=\"false\"\n aria-controls=\"nav-menu-products\"\n data-stimeo--navigation-menu-target=\"trigger\"\n data-action=\"click->stimeo--navigation-menu#toggle\n keydown->stimeo--navigation-menu#onTriggerKeydown\">\n <%= t(\"components.navigation_menu.demo.products.label\") %>\n </button>\n <div id=\"nav-menu-products\" class=\"nav-menu__panel\"\n data-stimeo--navigation-menu-target=\"panel\" hidden>\n <a class=\"demo-menuitem\" href=\"#analytics\"><%= t(\n \"components.navigation_menu.demo.products.links.analytics\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#automation\"><%= t(\n \"components.navigation_menu.demo.products.links.automation\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#reports\"><%= t(\n \"components.navigation_menu.demo.products.links.reports\"\n ) %></a>\n </div>\n </li>\n <li class=\"nav-menu__item\">\n <button\n type=\"button\"\n class=\"demo-baritem\"\n aria-expanded=\"false\"\n aria-controls=\"nav-menu-company\"\n data-stimeo--navigation-menu-target=\"trigger\"\n data-action=\"click->stimeo--navigation-menu#toggle\n keydown->stimeo--navigation-menu#onTriggerKeydown\">\n <%= t(\"components.navigation_menu.demo.company.label\") %>\n </button>\n <div id=\"nav-menu-company\" class=\"nav-menu__panel\"\n data-stimeo--navigation-menu-target=\"panel\" hidden>\n <a class=\"demo-menuitem\" href=\"#about\"><%= t(\n \"components.navigation_menu.demo.company.links.about\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#careers\"><%= t(\n \"components.navigation_menu.demo.company.links.careers\"\n ) %></a>\n </div>\n </li>\n </ul>\n</nav>\n\n<p class=\"nav-menu__caption\"><%= t(\"components.navigation_menu.demo.hover_caption\") %></p>\n<%# openOnHover is opt-in; hoverArea widens the hover region to the whole <li>, so\n hovering the top-level link (not just the disclosure button) opens the panel.\n The button keeps its own accessible name so keyboard and SR users can tell the\n link and its disclosure apart. %>\n<nav class=\"nav-menu\" data-controller=\"stimeo--navigation-menu\"\n data-stimeo--navigation-menu-open-on-hover-value=\"true\"\n aria-label=\"<%= t(\"components.navigation_menu.demo.hover.label\") %>\">\n <ul class=\"nav-menu__list\" data-stimeo--navigation-menu-target=\"list\">\n <li class=\"nav-menu__item\" data-stimeo--navigation-menu-target=\"hoverArea\">\n <a class=\"demo-baritem nav-menu__link\" href=\"#solutions\">\n <%= t(\"components.navigation_menu.demo.hover.solutions.label\") %>\n </a>\n <button\n type=\"button\"\n class=\"demo-baritem nav-menu__disclosure\"\n aria-expanded=\"false\"\n aria-controls=\"nav-menu-solutions\"\n data-stimeo--navigation-menu-target=\"trigger\"\n data-action=\"click->stimeo--navigation-menu#toggle\n keydown->stimeo--navigation-menu#onTriggerKeydown\">\n <span aria-hidden=\"true\">▾</span>\n <span class=\"visually-hidden\"><%= t(\n \"components.navigation_menu.demo.hover.solutions.toggle\"\n ) %></span>\n </button>\n <div id=\"nav-menu-solutions\" class=\"nav-menu__panel\"\n data-stimeo--navigation-menu-target=\"panel\" hidden>\n <a class=\"demo-menuitem\" href=\"#retail\"><%= t(\n \"components.navigation_menu.demo.hover.solutions.links.retail\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#finance\"><%= t(\n \"components.navigation_menu.demo.hover.solutions.links.finance\"\n ) %></a>\n </div>\n </li>\n <li class=\"nav-menu__item\" data-stimeo--navigation-menu-target=\"hoverArea\">\n <a class=\"demo-baritem nav-menu__link\" href=\"#resources\">\n <%= t(\"components.navigation_menu.demo.hover.resources.label\") %>\n </a>\n <button\n type=\"button\"\n class=\"demo-baritem nav-menu__disclosure\"\n aria-expanded=\"false\"\n aria-controls=\"nav-menu-resources\"\n data-stimeo--navigation-menu-target=\"trigger\"\n data-action=\"click->stimeo--navigation-menu#toggle\n keydown->stimeo--navigation-menu#onTriggerKeydown\">\n <span aria-hidden=\"true\">▾</span>\n <span class=\"visually-hidden\"><%= t(\n \"components.navigation_menu.demo.hover.resources.toggle\"\n ) %></span>\n </button>\n <div id=\"nav-menu-resources\" class=\"nav-menu__panel\"\n data-stimeo--navigation-menu-target=\"panel\" hidden>\n <a class=\"demo-menuitem\" href=\"#guides\"><%= t(\n \"components.navigation_menu.demo.hover.resources.links.guides\"\n ) %></a>\n <a class=\"demo-menuitem\" href=\"#blog\"><%= t(\n \"components.navigation_menu.demo.hover.resources.links.blog\"\n ) %></a>\n </div>\n </li>\n </ul>\n</nav>\n\n<%# Readout: what the component just reported. Purely visual — the component\n already announces what a screen reader needs, so this line is aria-hidden to\n keep it from being read twice. The value is a code fragment (API identifiers\n and values), so only the label is translated. %>\n<p class=\"demo-readout\" aria-hidden=\"true\">\n <span><%= t(\"catalog.readout.events\") %></span>\n <span class=\"demo-readout__value\" data-readout>—</span>\n</p>\n"
|
|
227
227
|
},
|
|
228
228
|
"stimeo--nested-form": {
|
|
229
229
|
"file": "examples/nested_form/_demo.html.erb",
|
|
@@ -251,11 +251,11 @@
|
|
|
251
251
|
},
|
|
252
252
|
"stimeo--overflow-menu": {
|
|
253
253
|
"file": "examples/overflow_menu/_demo.html.erb",
|
|
254
|
-
"source": "<%# Overflow-menu demo: drag the width slider to shrink the
|
|
254
|
+
"source": "<%# Overflow-menu demo: drag the width slider to shrink the bar — the controller\n measures the items and banks the lowest-priority ones into the More menu (delegated\n to stimeo--menu), moving them back as space returns. The items need no data-action of\n their own: stimeo--menu handles clicks and keys from its own element, so an item becomes\n operable the moment it lands in the menu. Only the More trigger is bound. The library\n moves items and sets data-overflowing / data-overflow-count; demo.css owns the look. %>\n<div class=\"overflow-demo\">\n <label class=\"demo-width-control\">\n <span><%= t(\"components.overflow_menu.demo.width\") %></span>\n <input type=\"range\" min=\"220\" max=\"640\" value=\"640\" data-overflow-demo-width>\n </label>\n\n <div\n class=\"overflow-demo__bar\"\n data-controller=\"stimeo--overflow-menu\"\n <%# A group, not a toolbar: these buttons stay in the normal Tab order. The\n single-tab-stop roving an APG Toolbar implies belongs to stimeo--toolbar,\n which this controller does not provide. %>\n role=\"group\"\n aria-label=\"<%= t(\"components.overflow_menu.name\") %>\">\n <div class=\"overflow-demo__items\" data-stimeo--overflow-menu-target=\"items\">\n <% %w[save edit share archive delete].each_with_index do |id, i| %>\n <button\n type=\"button\"\n class=\"demo-menuitem overflow-demo__item\"\n <%= \"data-priority=\\\"#{i + 1}\\\"\".html_safe if i < 3 %>>\n <%= t(\"components.overflow_menu.demo.#{id}\") %>\n </button>\n <% end %>\n </div>\n\n <div\n class=\"overflow-demo__more\"\n data-controller=\"stimeo--menu\"\n data-stimeo--overflow-menu-target=\"more\"\n hidden>\n <button\n id=\"overflow-menu-trigger\"\n type=\"button\"\n class=\"demo-trigger overflow-demo__trigger\"\n aria-haspopup=\"menu\"\n aria-expanded=\"false\"\n data-stimeo--menu-target=\"trigger\"\n data-action=\"click->stimeo--menu#toggle keydown->stimeo--menu#onTriggerKeydown\">\n <%= t(\"components.overflow_menu.demo.more\") %>\n </button>\n <%# A div, not a ul: the controller appends the items themselves, and a ul may only\n hold li children. One container shape keeps the markup contract unambiguous. %>\n <div class=\"overflow-demo__menu\" role=\"menu\" aria-labelledby=\"overflow-menu-trigger\"\n data-stimeo--menu-target=\"menu\" hidden></div>\n </div>\n </div>\n</div>\n"
|
|
255
255
|
},
|
|
256
256
|
"stimeo--pagination": {
|
|
257
257
|
"file": "examples/pagination/_demo.html.erb",
|
|
258
|
-
"source": "<%# Markup for the pagination demo.\n Built on nav + aria-label and aria-current=\"page\", the library handles current-page\n management, boundary control of the prev/next buttons, and firing the change event.\n Data fetching and URL rewriting are the consumer's (here demo.js just updates the\n results area). %>\n<nav\n class=\"pagination\"\n data-controller=\"stimeo--pagination\"\n aria-label=\"<%= t(\"components.pagination.demo.label\") %>\"\n data-stimeo--pagination-page-value=\"1\"\n data-stimeo--pagination-total-value=\"5\">\n <button\n type=\"button\"\n class=\"pagination__button\"\n data-stimeo--pagination-target=\"prev\"\n data-action=\"click->stimeo--pagination#prev\">\n <%= t(\"components.pagination.demo.prev\") %>\n </button>\n <% (1..5).each do |page| %>\n <button\n type=\"button\"\n class=\"pagination__button pagination__page\"\n data-page=\"<%= page %>\"\n <%= \"aria-current=\\\"page\\\"\".html_safe if page == 1 %>\n data-stimeo--pagination-target=\"page\"\n data-action=\"click->stimeo--pagination#select\"><%= page %></button>\n <% end %>\n <button\n type=\"button\"\n class=\"pagination__button\"\n data-stimeo--pagination-target=\"next\"\n data-action=\"click->stimeo--pagination#next\">\n <%= t(\"components.pagination.demo.next\") %>\n </button>\n</nav>\n\n<p\n class=\"pagination__status\"\n data-pagination-status\n data-template=\"<%= t(\"components.pagination.demo.status_template\") %>\"\n aria-live=\"polite\">\n <%= t(\"components.pagination.demo.
|
|
258
|
+
"source": "<%# Markup for the pagination demo.\n Built on nav + aria-label and aria-current=\"page\", the library handles current-page\n management, boundary control of the prev/next buttons, and firing the change event.\n Data fetching and URL rewriting are the consumer's (here demo.js just updates the\n results area). %>\n<nav\n class=\"pagination\"\n data-controller=\"stimeo--pagination\"\n aria-label=\"<%= t(\"components.pagination.demo.label\") %>\"\n data-stimeo--pagination-page-value=\"1\"\n data-stimeo--pagination-total-value=\"5\">\n <button\n type=\"button\"\n class=\"pagination__button\"\n data-stimeo--pagination-target=\"prev\"\n data-action=\"click->stimeo--pagination#prev\">\n <%= t(\"components.pagination.demo.prev\") %>\n </button>\n <% (1..5).each do |page| %>\n <button\n type=\"button\"\n class=\"pagination__button pagination__page\"\n data-page=\"<%= page %>\"\n <%= \"aria-current=\\\"page\\\"\".html_safe if page == 1 %>\n data-stimeo--pagination-target=\"page\"\n data-action=\"click->stimeo--pagination#select\"><%= page %></button>\n <% end %>\n <button\n type=\"button\"\n class=\"pagination__button\"\n data-stimeo--pagination-target=\"next\"\n data-action=\"click->stimeo--pagination#next\">\n <%= t(\"components.pagination.demo.next\") %>\n </button>\n</nav>\n\n<p\n class=\"pagination__status\"\n data-pagination-status\n data-template=\"<%= t(\"components.pagination.demo.status_template\") %>\"\n aria-live=\"polite\">\n <%= t(\"components.pagination.demo.initial_status\", page: 1, total: 5) %>\n</p>\n"
|
|
259
259
|
},
|
|
260
260
|
"stimeo--password-reveal": {
|
|
261
261
|
"file": "examples/password_reveal/_demo.html.erb",
|
|
@@ -271,7 +271,7 @@
|
|
|
271
271
|
},
|
|
272
272
|
"stimeo--pointer-drag": {
|
|
273
273
|
"file": "examples/pointer_drag/_demo.html.erb",
|
|
274
|
-
"source": "<%# pointer-drag: the primitive normalizes the drag lifecycle (threshold, axis\n lock, pointer capture, touch-action, cancel) and adds a keyboard alternative.\n With the opt-in follow value it also moves the card itself — translate on\n move, committed on drop, restored on cancel — so the consumer JS below only\n mirrors the signal into the status line. The card can travel out of the\n dashed area, which the area clips; the reset action brings it back,
|
|
274
|
+
"source": "<%# pointer-drag: the primitive normalizes the drag lifecycle (threshold, axis\n lock, pointer capture, touch-action, cancel) and adds a keyboard alternative.\n With the opt-in follow value it also moves the card itself — translate on\n move, committed on drop, restored on cancel — so the consumer JS below only\n mirrors the signal into the status line. The card can travel out of the\n dashed area, which the area clips; the reset action brings it back, ending\n any drag in flight and clearing the inline translate follow moved it with.\n With follow on, a translate the page writes itself in the <x>px <y>px form\n works too, since the next drag reads its start back from the inline\n translate. The button sits outside the controller element, so its click\n reaches the action as a custom event the element's own data-action maps. %>\n<div class=\"pointer-drag-demo\">\n <p class=\"pointer-drag-demo__hint\"><%= t(\"components.pointer_drag.demo.hint\") %></p>\n <div class=\"pointer-drag-demo__area\">\n <button type=\"button\" class=\"pointer-drag-demo__card\" id=\"pointer-drag-card\"\n data-controller=\"stimeo--pointer-drag\"\n data-stimeo--pointer-drag-follow-value=\"true\"\n data-action=\"demo:reset->stimeo--pointer-drag#reset\">\n <svg class=\"demo-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\"\n aria-hidden=\"true\">\n <circle cx=\"9\" cy=\"6\" r=\"1.5\"></circle><circle cx=\"15\" cy=\"6\" r=\"1.5\"></circle>\n <circle cx=\"9\" cy=\"12\" r=\"1.5\"></circle><circle cx=\"15\" cy=\"12\" r=\"1.5\"></circle>\n <circle cx=\"9\" cy=\"18\" r=\"1.5\"></circle><circle cx=\"15\" cy=\"18\" r=\"1.5\"></circle>\n </svg>\n <%= t(\"components.pointer_drag.demo.card_label\") %>\n </button>\n </div>\n <p class=\"pointer-drag-demo__actions\">\n <button type=\"button\" class=\"demo-trigger\" data-pointer-drag-reset>\n <%= t(\"components.pointer_drag.demo.reset_label\") %>\n </button>\n </p>\n <p class=\"pointer-drag-demo__status\" data-pointer-drag-status aria-live=\"polite\"\n data-moved-template=\"<%= t(\"components.pointer_drag.demo.moved_template\") %>\"\n data-idle-text=\"<%= t(\"components.pointer_drag.demo.idle_text\") %>\"></p>\n</div>\n"
|
|
275
275
|
},
|
|
276
276
|
"stimeo--popover": {
|
|
277
277
|
"file": "examples/popover/_demo.html.erb",
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
},
|
|
284
284
|
"stimeo--presence": {
|
|
285
285
|
"file": "examples/presence/_demo.html.erb",
|
|
286
|
-
"source": "<%# presence: a who's-here roster with zero server state. Each client beacons\n { id, name } through PresenceChannel on a heartbeat; every client expires\n silent peers locally and re-announces itself to newcomers, so the roster\n converges in one round trip. Your own beacons are ignored (echo\n suppression), so open this page in a second tab to see a peer appear — then\n close it or navigate it away for the leave notice (sent best-effort on\n disconnect and pagehide); a lost notice is caught by the timeout expiry. The id/name\n pair is randomized per render, which is fine for a demo; a real app renders\n current_user.id / current_user.name. The count templates (data-zero/-one/\n -other) keep the text localizable;
|
|
286
|
+
"source": "<%# presence: a who's-here roster with zero server state. Each client beacons\n { id, name } through PresenceChannel on a heartbeat; every client expires\n silent peers locally and re-announces itself to newcomers, so the roster\n converges in one round trip. Your own beacons are ignored (echo\n suppression), so open this page in a second tab to see a peer appear — then\n close it or navigate it away for the leave notice (sent best-effort on\n disconnect and pagehide); a lost notice is caught by the timeout expiry. The id/name\n pair is randomized per render, which is fine for a demo; a real app renders\n current_user.id / current_user.name. The count templates (data-zero/-one/\n -other) keep the text localizable; {count} is substituted by the\n controller. Heartbeat/timeout are shortened so leaving is quick to observe. %>\n<% token = SecureRandom.hex(4) %>\n<% guest = t(\"components.presence.demo.guest_name\", token: token.first(4)) %>\n<div class=\"presence-demo\"\n data-controller=\"stimeo--presence\"\n data-stimeo--presence-channel-value=\"PresenceChannel\"\n data-stimeo--presence-params-value='{\"room\":\"<%= PresenceChannel::ROOM %>\"}'\n data-stimeo--presence-id-value=\"<%= token %>\"\n data-stimeo--presence-name-value=\"<%= guest %>\"\n data-stimeo--presence-heartbeat-value=\"5000\"\n data-stimeo--presence-timeout-value=\"12000\">\n <p class=\"presence-demo__hint\"><%= t(\"components.presence.demo.hint\") %></p>\n <p class=\"presence-demo__you\"><%= t(\"components.presence.demo.you_are\", name: guest) %></p>\n <p class=\"presence-demo__count\"\n data-stimeo--presence-target=\"count\"\n data-zero=\"<%= t(\"components.presence.demo.count_zero\") %>\"\n data-one=\"<%= t(\"components.presence.demo.count_one\") %>\"\n data-other=\"<%= t(\"components.presence.demo.count_other\") %>\"></p>\n <ul class=\"presence-demo__list\"\n aria-label=\"<%= t(\"components.presence.demo.list_label\") %>\"\n data-stimeo--presence-target=\"list\"></ul>\n <template data-stimeo--presence-target=\"template\">\n <li class=\"presence-demo__peer\">\n <span class=\"presence-demo__dot\" aria-hidden=\"true\"></span>\n <span data-presence-name></span>\n </li>\n </template>\n</div>\n"
|
|
287
287
|
},
|
|
288
288
|
"stimeo--preview-guard": {
|
|
289
289
|
"file": "examples/preview_guard/_demo.html.erb",
|
|
@@ -317,9 +317,9 @@
|
|
|
317
317
|
"file": "examples/relative_time/_demo.html.erb",
|
|
318
318
|
"source": "<%# Markup for the relative-time demo.\n Formats the absolute time in <time datetime> into \"3 minutes ago\" etc. via\n Intl.RelativeTimeFormat, updating at an interval that grows with elapsed time. The\n machine-readable datetime stays fixed and only the display text updates; it's not a\n live region, to avoid interrupting screen readers. The locale follows the page\n language. The last example, past the threshold, falls back to an absolute format. %>\n<ul class=\"relative-time-demo\">\n <% [\n { at: 3.minutes.ago, label: t(\"components.relative_time.demo.posted\") },\n { at: 2.hours.ago, label: t(\"components.relative_time.demo.updated\") },\n { at: 3.days.from_now, label: t(\"components.relative_time.demo.due\") }\n ].each do |row| %>\n <li class=\"relative-time-demo__row\">\n <span class=\"relative-time-demo__label\"><%= row[:label] %></span>\n <time\n class=\"relative-time\"\n data-controller=\"stimeo--relative-time\"\n datetime=\"<%= row[:at].iso8601 %>\"\n title=\"<%= row[:at].strftime(\"%Y-%m-%d %H:%M\") %>\"\n data-stimeo--relative-time-locale-value=\"<%= I18n.locale %>\">\n <%= row[:at].strftime(\"%Y-%m-%d %H:%M\") %>\n </time>\n </li>\n <% end %>\n\n <li class=\"relative-time-demo__row\">\n <span class=\"relative-time-demo__label\"><%= t(\n \"components.relative_time.demo.archived\"\n ) %></span>\n <%# Example that falls back to an absolute format past the threshold\n (30 days = 2592000 seconds). %>\n <time\n class=\"relative-time\"\n data-controller=\"stimeo--relative-time\"\n datetime=\"<%= 90.days.ago.iso8601 %>\"\n data-stimeo--relative-time-locale-value=\"<%= I18n.locale %>\"\n data-stimeo--relative-time-threshold-value=\"2592000\">\n <%= 90.days.ago.strftime(\"%Y-%m-%d %H:%M\") %>\n </time>\n </li>\n</ul>\n\n<p class=\"relative-time-demo__hint\"><%= t(\"components.relative_time.demo.hint\") %></p>\n"
|
|
319
319
|
},
|
|
320
|
-
"stimeo--reset-
|
|
321
|
-
"file": "examples/
|
|
322
|
-
"source": "<%# Markup for the
|
|
320
|
+
"stimeo--reset-on-restore": {
|
|
321
|
+
"file": "examples/reset_on_restore/_demo.html.erb",
|
|
322
|
+
"source": "<%# Markup for the restore reset demo.\n When Turbo restores a page from its cache (the Back button), the controller returns the\n transient UI it covers to the way the page was written. A page still on screen is never\n reset. \"Simulate a restore\" stands in for the Back button: demo.js puts a copy of the\n covered region in its place, as Turbo does with a cached page, and the copy is reset as\n it connects. Open the details, type in the field, and show the toast first. %>\n<div class=\"reset-demo\">\n <p class=\"reset-demo__note\"><%= t(\"components.reset_on_restore.demo.note\") %></p>\n\n <div class=\"reset-demo__page\" data-reset-demo=\"page\" data-controller=\"stimeo--reset-on-restore\">\n <details class=\"reset-demo__details\" data-reset-attr=\"open\">\n <summary><%= t(\"components.reset_on_restore.demo.details_summary\") %></summary>\n <p><%= t(\"components.reset_on_restore.demo.details_body\") %></p>\n </details>\n\n <label class=\"reset-demo__field\">\n <span><%= t(\"components.reset_on_restore.demo.input_label\") %></span>\n <input type=\"text\" class=\"demo-input\" data-reset-value\n placeholder=\"<%= t(\"components.reset_on_restore.demo.input_placeholder\") %>\">\n </label>\n\n <div class=\"reset-demo__toast\" data-reset-demo=\"toast\" data-reset-hidden hidden role=\"status\">\n <%= t(\"components.reset_on_restore.demo.toast_text\") %>\n </div>\n </div>\n\n <div class=\"reset-demo__controls\">\n <button type=\"button\" class=\"demo-trigger\" data-reset-demo=\"show-toast\">\n <%= t(\"components.reset_on_restore.demo.show_toast\") %>\n </button>\n <button type=\"button\" class=\"demo-trigger\" data-reset-demo=\"simulate\">\n <%= t(\"components.reset_on_restore.demo.simulate\") %>\n </button>\n </div>\n\n <p class=\"reset-demo__status\" data-reset-demo=\"status\" aria-live=\"polite\"\n data-done-text=\"<%= t(\"components.reset_on_restore.demo.done\") %>\"></p>\n</div>\n"
|
|
323
323
|
},
|
|
324
324
|
"stimeo--resizable": {
|
|
325
325
|
"file": "examples/resizable/_demo.html.erb",
|
|
@@ -415,7 +415,7 @@
|
|
|
415
415
|
},
|
|
416
416
|
"stimeo--time-picker": {
|
|
417
417
|
"file": "examples/time_picker/_demo.html.erb",
|
|
418
|
-
"source": "<%# Markup for the time-picker (time selection) demo.\n stimeo--time-picker treats each segment (hour / minute / AM·PM) as an APG Spinbutton,\n handling arrow-key increment/decrement, edge wrap and carry (minute→hour), left/right\n segment movement, and direct numeric entry, and reflects the composed 24-hour value\n (HH:MM) into a hidden input. Each segment is an independent tab stop. %>\n<div\n class=\"time-picker\"\n data-controller=\"stimeo--time-picker\"\n data-stimeo--time-picker-hour-cycle-value=\"12\"\n data-stimeo--time-picker-step-value=\"5\"\n role=\"group\"\n aria-label=\"<%= t(\"components.time_picker.demo.group_label\") %>\">\n <span class=\"time-picker__segment\" role=\"spinbutton\"\n aria-label=\"<%= t(\"components.time_picker.demo.hours\") %>\"\n tabindex=\"0\" aria-valuenow=\"9\" aria-
|
|
418
|
+
"source": "<%# Markup for the time-picker (time selection) demo.\n stimeo--time-picker treats each segment (hour / minute / AM·PM) as an APG Spinbutton,\n handling arrow-key increment/decrement, edge wrap and carry (minute→hour), left/right\n segment movement, and direct numeric entry, and reflects the composed 24-hour value\n (HH:MM) into a hidden input. Each segment is an independent tab stop. %>\n<% zero_based_hour = I18n.locale == :ja %>\n<div\n class=\"time-picker\"\n data-controller=\"stimeo--time-picker\"\n data-stimeo--time-picker-hour-cycle-value=\"12\"\n data-stimeo--time-picker-hour12-zero-based-value=\"<%= zero_based_hour %>\"\n data-stimeo--time-picker-step-value=\"5\"\n data-stimeo--time-picker-am-label-value=\"<%= t(\"components.time_picker.demo.am\") %>\"\n data-stimeo--time-picker-pm-label-value=\"<%= t(\"components.time_picker.demo.pm\") %>\"\n role=\"group\"\n aria-label=\"<%= t(\"components.time_picker.demo.group_label\") %>\">\n <span class=\"time-picker__segment\" role=\"spinbutton\"\n aria-label=\"<%= t(\"components.time_picker.demo.hours\") %>\"\n tabindex=\"0\" aria-valuenow=\"9\" aria-valuetext=\"09\"\n aria-valuemin=\"<%= zero_based_hour ? 0 : 1 %>\"\n aria-valuemax=\"<%= zero_based_hour ? 11 : 12 %>\"\n data-segment=\"hour\" data-stimeo--time-picker-target=\"segment\"\n data-action=\"keydown->stimeo--time-picker#onKeydown\">09</span>\n <span class=\"time-picker__colon\" aria-hidden=\"true\">:</span>\n <span class=\"time-picker__segment\" role=\"spinbutton\"\n aria-label=\"<%= t(\"components.time_picker.demo.minutes\") %>\"\n tabindex=\"0\" aria-valuenow=\"30\" aria-valuemin=\"0\" aria-valuemax=\"59\" aria-valuetext=\"30\"\n data-segment=\"minute\" data-stimeo--time-picker-target=\"segment\"\n data-action=\"keydown->stimeo--time-picker#onKeydown\">30</span>\n <span class=\"time-picker__segment time-picker__segment--meridiem\" role=\"spinbutton\"\n aria-label=\"<%= t(\"components.time_picker.demo.meridiem\") %>\"\n tabindex=\"0\" aria-valuenow=\"0\" aria-valuemin=\"0\" aria-valuemax=\"1\"\n aria-valuetext=\"<%= t(\"components.time_picker.demo.am\") %>\"\n data-segment=\"meridiem\" data-stimeo--time-picker-target=\"segment\"\n data-action=\"keydown->stimeo--time-picker#onKeydown\"><%= t(\n \"components.time_picker.demo.am\"\n ) %></span>\n\n <input type=\"hidden\" name=\"time\" data-stimeo--time-picker-target=\"field\" />\n</div>\n"
|
|
419
419
|
},
|
|
420
420
|
"stimeo--toast": {
|
|
421
421
|
"file": "examples/toast/_demo.html.erb",
|
|
@@ -439,11 +439,11 @@
|
|
|
439
439
|
},
|
|
440
440
|
"stimeo--tree-view": {
|
|
441
441
|
"file": "examples/tree_view/_demo.html.erb",
|
|
442
|
-
"source": "<%# Markup for the tree-view (tree view / single selection) demo.\n Nested role=\"tree\" / \"treeitem\" / \"group\" express the hierarchy. Arrows move between\n visible items; ArrowRight / ArrowLeft expand/collapse and move between parent/child;\n Home/End, typeahead, and Enter/Space select a single item. The library handles roving,\n aria-expanded / aria-selected sync, and toggling each group's hidden. Across the whole\n tree only one treeitem is tabindex=0.\n The chevron is an optional pointer affordance wired to the toggle action. It stays\n tabindex=\"-1\" (the tree remains a single Tab stop) and aria-hidden (the item itself\n already announces its expanded state); clicking it expands/collapses without selecting,\n because the tree never consumes events raised inside a nested control. The toggle action\n hands focus to the row afterwards, so focus never rests on this decorative button and\n the arrow keys keep working right after a click. %>\n<ul class=\"tree-view\" data-controller=\"stimeo--tree-view\" role=\"tree\"\n aria-label=\"<%= t('components.tree_view.demo.label') %>\">\n <%# The hidden field carries the selected item's data-value into the form; both\n the field and the values are optional. An item without a data-value submits\n an empty string, so give one to every item that should be selectable. %>\n <input type=\"hidden\" name=\"path\" data-stimeo--tree-view-target=\"field\" />\n <li\n class=\"tree-view__item\"\n role=\"treeitem\"\n aria-expanded=\"true\"\n aria-selected=\"false\"\n tabindex=\"0\"\n data-value=\"app\"\n data-stimeo--tree-view-target=\"item\"\n data-action=\"keydown->stimeo--tree-view#onKeydown click->stimeo--tree-view#
|
|
442
|
+
"source": "<%# Markup for the tree-view (tree view / single selection) demo.\n Nested role=\"tree\" / \"treeitem\" / \"group\" express the hierarchy. Arrows move between\n visible items; ArrowRight / ArrowLeft expand/collapse and move between parent/child;\n Home/End, typeahead, and Enter/Space select a single item. The library handles roving,\n aria-expanded / aria-selected sync, and toggling each group's hidden. Across the whole\n tree only one treeitem is tabindex=0.\n The chevron is an optional pointer affordance wired to the toggle action. It stays\n tabindex=\"-1\" (the tree remains a single Tab stop) and aria-hidden (the item itself\n already announces its expanded state); clicking it expands/collapses without selecting,\n because the tree never consumes events raised inside a nested control. The toggle action\n hands focus to the row afterwards, so focus never rests on this decorative button and\n the arrow keys keep working right after a click. %>\n<ul class=\"tree-view\" data-controller=\"stimeo--tree-view\" role=\"tree\"\n aria-label=\"<%= t('components.tree_view.demo.label') %>\">\n <%# The hidden field carries the selected item's data-value into the form; both\n the field and the values are optional. An item without a data-value submits\n an empty string, so give one to every item that should be selectable. %>\n <input type=\"hidden\" name=\"path\" data-stimeo--tree-view-target=\"field\" />\n <li\n class=\"tree-view__item\"\n role=\"treeitem\"\n aria-expanded=\"true\"\n aria-selected=\"false\"\n tabindex=\"0\"\n data-value=\"app\"\n data-stimeo--tree-view-target=\"item\"\n data-action=\"keydown->stimeo--tree-view#onKeydown click->stimeo--tree-view#select\">\n <button type=\"button\" class=\"tree-view__chevron\" tabindex=\"-1\" aria-hidden=\"true\"\n data-action=\"click->stimeo--tree-view#toggle\"></button>\n <span class=\"tree-view__label\">app</span>\n <ul class=\"tree-view__group\" role=\"group\" data-stimeo--tree-view-target=\"group\">\n <li\n class=\"tree-view__item\"\n role=\"treeitem\"\n aria-expanded=\"false\"\n aria-selected=\"false\"\n tabindex=\"-1\"\n data-value=\"app/controllers\"\n data-stimeo--tree-view-target=\"item\"\n data-action=\"keydown->stimeo--tree-view#onKeydown click->stimeo--tree-view#select\">\n <button type=\"button\" class=\"tree-view__chevron\" tabindex=\"-1\" aria-hidden=\"true\"\n data-action=\"click->stimeo--tree-view#toggle\"></button>\n <span class=\"tree-view__label\">controllers</span>\n <ul class=\"tree-view__group\" role=\"group\" data-stimeo--tree-view-target=\"group\" hidden>\n <li class=\"tree-view__item\" role=\"treeitem\" aria-selected=\"false\"\n tabindex=\"-1\" data-value=\"app/controllers/application_controller.rb\"\n data-stimeo--tree-view-target=\"item\"\n data-action=\"keydown->stimeo--tree-view#onKeydown click->stimeo--tree-view#select\">\n <span class=\"tree-view__label\">application_controller.rb</span>\n </li>\n <li class=\"tree-view__item\" role=\"treeitem\" aria-selected=\"false\"\n tabindex=\"-1\" data-value=\"app/controllers/components_controller.rb\"\n data-stimeo--tree-view-target=\"item\"\n data-action=\"keydown->stimeo--tree-view#onKeydown click->stimeo--tree-view#select\">\n <span class=\"tree-view__label\">components_controller.rb</span>\n </li>\n </ul>\n </li>\n <li class=\"tree-view__item\" role=\"treeitem\" aria-selected=\"false\"\n tabindex=\"-1\" data-value=\"app/application.rb\"\n data-stimeo--tree-view-target=\"item\"\n data-action=\"keydown->stimeo--tree-view#onKeydown click->stimeo--tree-view#select\">\n <span class=\"tree-view__label\">application.rb</span>\n </li>\n </ul>\n </li>\n <li class=\"tree-view__item\" role=\"treeitem\" aria-selected=\"false\"\n tabindex=\"-1\" data-value=\"README.md\"\n data-stimeo--tree-view-target=\"item\"\n data-action=\"keydown->stimeo--tree-view#onKeydown click->stimeo--tree-view#select\">\n <span class=\"tree-view__label\">README.md</span>\n </li>\n <li class=\"tree-view__item\" role=\"treeitem\" aria-selected=\"false\"\n tabindex=\"-1\" data-value=\"Gemfile\"\n data-stimeo--tree-view-target=\"item\"\n data-action=\"keydown->stimeo--tree-view#onKeydown click->stimeo--tree-view#select\">\n <span class=\"tree-view__label\">Gemfile</span>\n </li>\n</ul>\n\n<%# Readout: what the component just reported. Purely visual — the component\n already announces what a screen reader needs, so this line is aria-hidden to\n keep it from being read twice. The value is a code fragment (API identifiers\n and values), so only the label is translated. %>\n<p class=\"demo-readout\" aria-hidden=\"true\">\n <span><%= t(\"catalog.readout.field\") %></span>\n <span class=\"demo-readout__value\" data-readout\n data-empty-text=\"<%= t(\"catalog.readout.empty\") %>\">—</span>\n</p>\n"
|
|
443
443
|
},
|
|
444
444
|
"stimeo--typing-indicator": {
|
|
445
445
|
"file": "examples/typing_indicator/_demo.html.erb",
|
|
446
|
-
"source": "<%# typing-indicator: the state lives on the server stream, not in client memory.\n Typing in the composer broadcasts a throttled signal through TypingChannel;\n every OTHER client shows \"X is typing…\" in the visible status slot and clears\n it automatically after silence. Own echoes are suppressed by design, so open\n this page in a second tab to see the indicator. The guest name is randomized\n per render so each tab is a distinct \"user\" (a real app passes\n current_user.name). The data-one/data-many templates keep the
|
|
446
|
+
"source": "<%# typing-indicator: the state lives on the server stream, not in client memory.\n Typing in the composer broadcasts a throttled signal through TypingChannel;\n every OTHER client shows \"X is typing…\" in the visible status slot and clears\n it automatically after silence. Own echoes are suppressed by design, so open\n this page in a second tab to see the indicator. The guest name is randomized\n per render so each tab is a distinct \"user\" (a real app passes\n current_user.name). The data-one/data-many templates keep the visible copy\n localizable; {name}/{names} are substituted by the controller. The status slot is\n plain visible copy — assistive tech is reached through the page's shared announcer\n instead, so the announce-one/announce-many values carry the spoken wording with\n the same {name}/{names} syntax. Leaving them off shows the indicator without announcing it. %>\n<% guest = t(\"components.typing_indicator.demo.guest_name\", token: SecureRandom.hex(2)) %>\n<% announce_one = t(\"components.typing_indicator.demo.announce_one\") %>\n<% announce_many = t(\"components.typing_indicator.demo.announce_many\") %>\n<div class=\"typing-demo\"\n data-controller=\"stimeo--typing-indicator\"\n data-stimeo--typing-indicator-channel-value=\"TypingChannel\"\n data-stimeo--typing-indicator-params-value='{\"room\":\"<%= TypingChannel::ROOM %>\"}'\n data-stimeo--typing-indicator-name-value=\"<%= guest %>\"\n data-stimeo--typing-indicator-timeout-value=\"3000\"\n data-stimeo--typing-indicator-throttle-value=\"1000\"\n data-stimeo--typing-indicator-announce-one-text-value=\"<%= announce_one %>\"\n data-stimeo--typing-indicator-announce-many-text-value=\"<%= announce_many %>\">\n <p class=\"typing-demo__hint\"><%= t(\"components.typing_indicator.demo.hint\") %></p>\n <p class=\"typing-demo__you\"><%= t(\"components.typing_indicator.demo.you_are\", name: guest) %></p>\n <label class=\"typing-demo__label\" for=\"typing-demo-input\">\n <%= t(\"components.typing_indicator.demo.input_label\") %>\n </label>\n <textarea id=\"typing-demo-input\" class=\"demo-input typing-demo__input\" rows=\"3\"\n data-stimeo--typing-indicator-target=\"input\"></textarea>\n <p class=\"typing-demo__status\"\n data-stimeo--typing-indicator-target=\"status\"\n data-one=\"<%= t(\"components.typing_indicator.demo.one\") %>\"\n data-many=\"<%= t(\"components.typing_indicator.demo.many\") %>\"></p>\n</div>\n"
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
449
|
}
|