stimeo-ui 0.6.0 → 0.8.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 +124 -0
- package/dist/controllers/alert_dialog_controller.d.ts +2 -0
- package/dist/controllers/alert_dialog_controller.js +75 -4
- package/dist/controllers/alert_dialog_controller.js.map +1 -1
- package/dist/controllers/auto_submit_controller.d.ts +16 -3
- package/dist/controllers/auto_submit_controller.js +94 -16
- package/dist/controllers/auto_submit_controller.js.map +1 -1
- package/dist/controllers/avatar_controller.js +47 -5
- package/dist/controllers/avatar_controller.js.map +1 -1
- package/dist/controllers/breadcrumb_controller.d.ts +2 -0
- package/dist/controllers/breadcrumb_controller.js.map +1 -1
- package/dist/controllers/bulk_select_controller.d.ts +2 -0
- package/dist/controllers/bulk_select_controller.js.map +1 -1
- package/dist/controllers/calendar_controller.d.ts +2 -0
- package/dist/controllers/calendar_controller.js.map +1 -1
- package/dist/controllers/carousel_controller.d.ts +81 -47
- package/dist/controllers/carousel_controller.js +451 -100
- package/dist/controllers/carousel_controller.js.map +1 -1
- package/dist/controllers/character_counter_controller.d.ts +52 -20
- package/dist/controllers/character_counter_controller.js +338 -63
- package/dist/controllers/character_counter_controller.js.map +1 -1
- package/dist/controllers/checkbox_controller.d.ts +3 -0
- package/dist/controllers/checkbox_controller.js.map +1 -1
- package/dist/controllers/color_picker_controller.d.ts +3 -0
- package/dist/controllers/color_picker_controller.js.map +1 -1
- package/dist/controllers/combobox_controller.d.ts +2 -0
- package/dist/controllers/combobox_controller.js.map +1 -1
- package/dist/controllers/command_palette_controller.d.ts +2 -0
- package/dist/controllers/command_palette_controller.js +75 -4
- package/dist/controllers/command_palette_controller.js.map +1 -1
- package/dist/controllers/conditional_fields_controller.d.ts +42 -14
- package/dist/controllers/conditional_fields_controller.js +345 -51
- package/dist/controllers/conditional_fields_controller.js.map +1 -1
- package/dist/controllers/confirm_controller.d.ts +2 -0
- package/dist/controllers/confirm_controller.js +75 -4
- package/dist/controllers/confirm_controller.js.map +1 -1
- package/dist/controllers/count_up_controller.d.ts +2 -0
- package/dist/controllers/count_up_controller.js.map +1 -1
- package/dist/controllers/countdown_controller.d.ts +4 -0
- package/dist/controllers/countdown_controller.js.map +1 -1
- package/dist/controllers/currency_input_controller.d.ts +40 -4
- package/dist/controllers/currency_input_controller.js +305 -74
- package/dist/controllers/currency_input_controller.js.map +1 -1
- package/dist/controllers/data_grid_controller.d.ts +3 -0
- package/dist/controllers/data_grid_controller.js.map +1 -1
- package/dist/controllers/dialog_controller.js +75 -4
- package/dist/controllers/dialog_controller.js.map +1 -1
- package/dist/controllers/direct_upload_controller.d.ts +59 -25
- package/dist/controllers/direct_upload_controller.js +212 -46
- package/dist/controllers/direct_upload_controller.js.map +1 -1
- package/dist/controllers/dirty_form_controller.d.ts +14 -6
- package/dist/controllers/dirty_form_controller.js +192 -29
- package/dist/controllers/dirty_form_controller.js.map +1 -1
- package/dist/controllers/dismissible_controller.d.ts +2 -0
- package/dist/controllers/dismissible_controller.js +83 -18
- package/dist/controllers/dismissible_controller.js.map +1 -1
- package/dist/controllers/drawer_controller.js +75 -4
- package/dist/controllers/drawer_controller.js.map +1 -1
- package/dist/controllers/empty_state_controller.d.ts +2 -0
- package/dist/controllers/empty_state_controller.js.map +1 -1
- package/dist/controllers/file_dropzone_controller.d.ts +123 -27
- package/dist/controllers/file_dropzone_controller.js +386 -63
- package/dist/controllers/file_dropzone_controller.js.map +1 -1
- package/dist/controllers/filter_controller.d.ts +2 -0
- package/dist/controllers/filter_controller.js.map +1 -1
- package/dist/controllers/flash_controller.d.ts +7 -1
- package/dist/controllers/flash_controller.js +3 -1
- package/dist/controllers/flash_controller.js.map +1 -1
- package/dist/controllers/focus_controller.d.ts +2 -0
- package/dist/controllers/focus_controller.js +75 -4
- package/dist/controllers/focus_controller.js.map +1 -1
- package/dist/controllers/form_field_controller.d.ts +50 -10
- package/dist/controllers/form_field_controller.js +280 -62
- package/dist/controllers/form_field_controller.js.map +1 -1
- package/dist/controllers/form_validation_controller.d.ts +10 -8
- package/dist/controllers/form_validation_controller.js +208 -83
- package/dist/controllers/form_validation_controller.js.map +1 -1
- package/dist/controllers/frame_loading_controller.d.ts +5 -1
- package/dist/controllers/frame_loading_controller.js +2 -1
- package/dist/controllers/frame_loading_controller.js.map +1 -1
- package/dist/controllers/highlight_controller.d.ts +2 -0
- package/dist/controllers/highlight_controller.js.map +1 -1
- package/dist/controllers/idle_controller.d.ts +2 -0
- package/dist/controllers/idle_controller.js.map +1 -1
- package/dist/controllers/input_mask_controller.d.ts +43 -15
- package/dist/controllers/input_mask_controller.js +251 -76
- package/dist/controllers/input_mask_controller.js.map +1 -1
- package/dist/controllers/lazy_frame_controller.d.ts +2 -0
- package/dist/controllers/lazy_frame_controller.js.map +1 -1
- package/dist/controllers/listbox_controller.d.ts +2 -0
- package/dist/controllers/listbox_controller.js.map +1 -1
- package/dist/controllers/local_time_controller.d.ts +2 -0
- package/dist/controllers/local_time_controller.js.map +1 -1
- package/dist/controllers/masonry_controller.d.ts +2 -0
- package/dist/controllers/masonry_controller.js.map +1 -1
- package/dist/controllers/meter_controller.d.ts +2 -0
- package/dist/controllers/meter_controller.js.map +1 -1
- package/dist/controllers/multi_select_controller.d.ts +2 -0
- package/dist/controllers/multi_select_controller.js.map +1 -1
- package/dist/controllers/nested_form_controller.d.ts +52 -13
- package/dist/controllers/nested_form_controller.js +450 -42
- package/dist/controllers/nested_form_controller.js.map +1 -1
- package/dist/controllers/network_status_controller.d.ts +2 -0
- package/dist/controllers/network_status_controller.js.map +1 -1
- package/dist/controllers/number_input_controller.d.ts +2 -0
- package/dist/controllers/number_input_controller.js +47 -5
- package/dist/controllers/number_input_controller.js.map +1 -1
- package/dist/controllers/otp_controller.d.ts +62 -23
- package/dist/controllers/otp_controller.js +472 -114
- package/dist/controllers/otp_controller.js.map +1 -1
- package/dist/controllers/overflow_indicator_controller.d.ts +2 -0
- package/dist/controllers/overflow_indicator_controller.js.map +1 -1
- package/dist/controllers/overflow_menu_controller.d.ts +2 -0
- package/dist/controllers/overflow_menu_controller.js +2 -1
- package/dist/controllers/overflow_menu_controller.js.map +1 -1
- package/dist/controllers/pagination_controller.d.ts +2 -0
- package/dist/controllers/pagination_controller.js +2 -1
- package/dist/controllers/pagination_controller.js.map +1 -1
- package/dist/controllers/password_reveal_controller.d.ts +2 -0
- package/dist/controllers/password_reveal_controller.js.map +1 -1
- package/dist/controllers/password_strength_controller.d.ts +2 -0
- package/dist/controllers/password_strength_controller.js.map +1 -1
- package/dist/controllers/persist_controller.d.ts +30 -16
- package/dist/controllers/persist_controller.js +432 -122
- package/dist/controllers/persist_controller.js.map +1 -1
- package/dist/controllers/pointer_drag_controller.d.ts +3 -0
- package/dist/controllers/pointer_drag_controller.js.map +1 -1
- package/dist/controllers/popover_controller.js +77 -4
- package/dist/controllers/popover_controller.js.map +1 -1
- package/dist/controllers/portal_controller.d.ts +2 -0
- package/dist/controllers/portal_controller.js.map +1 -1
- package/dist/controllers/preview_guard_controller.d.ts +2 -0
- package/dist/controllers/preview_guard_controller.js.map +1 -1
- package/dist/controllers/progress_controller.d.ts +3 -0
- package/dist/controllers/progress_controller.js.map +1 -1
- package/dist/controllers/radio_group_controller.d.ts +3 -0
- package/dist/controllers/radio_group_controller.js.map +1 -1
- package/dist/controllers/rating_controller.d.ts +2 -0
- package/dist/controllers/rating_controller.js +9 -5
- package/dist/controllers/rating_controller.js.map +1 -1
- package/dist/controllers/reading_progress_controller.d.ts +2 -0
- package/dist/controllers/reading_progress_controller.js.map +1 -1
- package/dist/controllers/resizable_controller.d.ts +2 -0
- package/dist/controllers/resizable_controller.js.map +1 -1
- package/dist/controllers/roving_controller.d.ts +2 -0
- package/dist/controllers/roving_controller.js.map +1 -1
- package/dist/controllers/scroll_area_controller.d.ts +23 -15
- package/dist/controllers/scroll_area_controller.js +462 -162
- package/dist/controllers/scroll_area_controller.js.map +1 -1
- package/dist/controllers/scroll_visibility_controller.d.ts +2 -0
- package/dist/controllers/scroll_visibility_controller.js.map +1 -1
- package/dist/controllers/scrollspy_controller.d.ts +2 -0
- package/dist/controllers/scrollspy_controller.js.map +1 -1
- package/dist/controllers/separator_controller.d.ts +54 -11
- package/dist/controllers/separator_controller.js +354 -38
- package/dist/controllers/separator_controller.js.map +1 -1
- package/dist/controllers/sidebar_controller.js +83 -10
- package/dist/controllers/sidebar_controller.js.map +1 -1
- package/dist/controllers/skeleton_controller.d.ts +2 -0
- package/dist/controllers/skeleton_controller.js.map +1 -1
- package/dist/controllers/slider_controller.d.ts +2 -0
- package/dist/controllers/slider_controller.js.map +1 -1
- package/dist/controllers/smart_sticky_header_controller.d.ts +2 -0
- package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
- package/dist/controllers/spinner_controller.d.ts +4 -1
- package/dist/controllers/spinner_controller.js +7 -5
- package/dist/controllers/spinner_controller.js.map +1 -1
- package/dist/controllers/step_indicator_controller.d.ts +2 -0
- package/dist/controllers/step_indicator_controller.js.map +1 -1
- package/dist/controllers/stepper_controller.d.ts +2 -0
- package/dist/controllers/stepper_controller.js.map +1 -1
- package/dist/controllers/stick_to_bottom_controller.d.ts +2 -0
- package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
- package/dist/controllers/sticky_observer_controller.d.ts +2 -0
- package/dist/controllers/sticky_observer_controller.js.map +1 -1
- package/dist/controllers/submit_once_controller.d.ts +98 -39
- package/dist/controllers/submit_once_controller.js +402 -122
- package/dist/controllers/submit_once_controller.js.map +1 -1
- package/dist/controllers/switch_controller.d.ts +2 -0
- package/dist/controllers/switch_controller.js.map +1 -1
- package/dist/controllers/tags_input_controller.d.ts +2 -0
- package/dist/controllers/tags_input_controller.js.map +1 -1
- package/dist/controllers/textarea_autosize_controller.d.ts +31 -9
- package/dist/controllers/textarea_autosize_controller.js +131 -3
- package/dist/controllers/textarea_autosize_controller.js.map +1 -1
- package/dist/controllers/theme_controller.d.ts +2 -0
- package/dist/controllers/theme_controller.js +8 -6
- package/dist/controllers/theme_controller.js.map +1 -1
- package/dist/controllers/time_picker_controller.d.ts +2 -0
- package/dist/controllers/time_picker_controller.js.map +1 -1
- package/dist/controllers/toast_controller.d.ts +4 -0
- package/dist/controllers/toast_controller.js.map +1 -1
- package/dist/controllers/toggle_group_controller.d.ts +2 -0
- package/dist/controllers/toggle_group_controller.js.map +1 -1
- package/dist/controllers/toolbar_controller.js.map +1 -1
- package/dist/controllers/transition_controller.d.ts +2 -0
- package/dist/controllers/transition_controller.js.map +1 -1
- package/dist/controllers/tree_view_controller.d.ts +2 -0
- package/dist/controllers/tree_view_controller.js +2 -1
- package/dist/controllers/tree_view_controller.js.map +1 -1
- package/dist/index.js +4293 -1447
- package/dist/index.js.map +1 -1
- package/dist/inspector/cli.d.ts +115 -4
- package/dist/inspector/cli.js +195 -15
- package/dist/inspector/cli.js.map +1 -1
- package/dist/inspector/cli_bin.js +257 -47
- package/dist/inspector/cli_bin.js.map +1 -1
- package/dist/inspector/examples.json +11 -11
- package/dist/inspector/manifest.json +615 -66
- package/dist/positioning/index.d.ts +2 -0
- package/dist/positioning/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -43,11 +43,11 @@
|
|
|
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,
|
|
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 (the autoplay Value is the intent it mirrors);\n demo.css swaps the glyph off it so the control visibly reflects play (❚❚) vs.\n paused (▶). The icons are decorative; the accessible name comes from aria-label\n above. %>\n <span class=\"carousel__play-icon carousel__play-icon--play\" aria-hidden=\"true\">▶</span>\n <span class=\"carousel__play-icon carousel__play-icon--pause\" aria-hidden=\"true\">❚❚</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 pause-on-hover / hard-stop-on-focus is understood as intentional (WCAG 2.2.2), not a bug.\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",
|
|
50
|
-
"source": "<%#
|
|
50
|
+
"source": "<%# Markup for the character-counter demo. The visible output updates on every\n keystroke, while the settled remaining count is debounced into the shared\n stimeo--announcer seated below. This demo's CSS styles the root's near/over\n hooks and the over-limit aria-invalid; watching the field needs no consumer\n JavaScript. %>\n<% announcement = t(\"components.character_counter.demo.announcement\") %>\n<div class=\"character-counter-demo\">\n <label class=\"character-counter-demo__label\" for=\"cc-message\">\n <%= t(\"components.character_counter.demo.label\") %>\n </label>\n <div\n class=\"character-counter\"\n data-controller=\"stimeo--character-counter\"\n data-stimeo--character-counter-max-value=\"140\"\n data-stimeo--character-counter-warn-at-value=\"20\"\n data-stimeo--character-counter-announce-text-value=\"<%= announcement %>\">\n <textarea\n id=\"cc-message\"\n class=\"character-counter__input\"\n rows=\"3\"\n data-stimeo--character-counter-target=\"input\"\n aria-describedby=\"cc-message-count\"\n placeholder=\"<%= t('components.character_counter.demo.placeholder') %>\"></textarea>\n <span\n id=\"cc-message-count\"\n class=\"character-counter__output\"\n data-stimeo--character-counter-target=\"output\"></span>\n <div data-controller=\"stimeo--announcer\">\n <div class=\"visually-hidden\"\n data-stimeo--announcer-target=\"polite\"\n aria-live=\"polite\"\n aria-atomic=\"true\"></div>\n </div>\n </div>\n</div>\n"
|
|
51
51
|
},
|
|
52
52
|
"stimeo--checkbox": {
|
|
53
53
|
"file": "examples/checkbox/_demo.html.erb",
|
|
@@ -111,11 +111,11 @@
|
|
|
111
111
|
},
|
|
112
112
|
"stimeo--direct-upload": {
|
|
113
113
|
"file": "examples/direct_upload/_demo.html.erb",
|
|
114
|
-
"source": "<%# Direct upload demo: there is no server, so demo.js fires the ActiveStorage\n direct-upload:* events to drive the rows. The library
|
|
114
|
+
"source": "<%# Direct upload demo: there is no server, so demo.js fires the ActiveStorage\n direct-upload:* events to drive the rows — including one upload that fails\n (error followed by end, the order ActiveStorage really uses). The library\n clones the row template per file, updates aria-valuenow / aria-valuetext /\n data-upload-state / the --stimeo--upload-progress var, and hands completion\n and failure announcements to the shared announcer below. This demo styles\n the bars. %>\n<% done_text = t(\"components.direct_upload.demo.done\") %>\n<% error_text = t(\"components.direct_upload.demo.error\") %>\n<div class=\"direct-upload-demo\">\n <button type=\"button\" class=\"demo-trigger\" data-direct-upload-start>\n <%= t(\"components.direct_upload.demo.start\") %>\n </button>\n <div\n class=\"direct-upload\"\n data-controller=\"stimeo--direct-upload\"\n data-stimeo--direct-upload-announce-done-text-value=\"<%= done_text %>\"\n data-stimeo--direct-upload-announce-error-text-value=\"<%= error_text %>\">\n <div class=\"direct-upload__list\" data-stimeo--direct-upload-target=\"list\"></div>\n <template data-stimeo--direct-upload-target=\"row\">\n <div class=\"direct-upload__row\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\">\n <span class=\"direct-upload__name\" data-field=\"name\"></span>\n <span class=\"direct-upload__track\"><span class=\"direct-upload__bar\"></span></span>\n <span class=\"direct-upload__percent\" data-field=\"percent\"></span>\n </div>\n </template>\n </div>\n <%# Shared announcer: completion and failure are the transitions worth reading;\n per-tick progress stays on each row's aria-valuenow. %>\n <div data-controller=\"stimeo--announcer\">\n <div class=\"visually-hidden\"\n data-stimeo--announcer-target=\"polite\" aria-live=\"polite\" aria-atomic=\"true\"></div>\n </div>\n</div>\n"
|
|
115
115
|
},
|
|
116
116
|
"stimeo--dirty-form": {
|
|
117
117
|
"file": "examples/dirty_form/_demo.html.erb",
|
|
118
|
-
"source": "<%# Dirty-form demo: edit
|
|
118
|
+
"source": "<%# Dirty-form demo: edit either field and its form gets data-dirty (shown as a badge).\n When both forms are dirty, one Turbo visit dispatches both guard events and opens\n one native confirm using the first eligible form in live DOM order. \"Save\" calls\n markClean for that form; this catalog has no server, so it stands in for a successful\n save. The library owns data-dirty and navigation coordination; the demo only styles\n the visible state. %>\n<div class=\"dirty-form-demo\">\n <form\n class=\"dirty-form\"\n data-controller=\"stimeo--dirty-form\"\n data-stimeo--dirty-form-message-value=\"<%= t('components.dirty_form.demo.first_message') %>\"\n aria-labelledby=\"dirty-form-first-title\"\n >\n <h3 id=\"dirty-form-first-title\" class=\"dirty-form__title\">\n <%= t(\"components.dirty_form.demo.first_title\") %>\n </h3>\n <label class=\"dirty-form__field\">\n <span><%= t(\"components.dirty_form.demo.first_label\") %></span>\n <input type=\"text\" name=\"title\" value=\"<%= t('components.dirty_form.demo.first_value') %>\">\n </label>\n <div class=\"dirty-form__bar\">\n <span class=\"dirty-form__badge\"><%= t(\"components.dirty_form.demo.unsaved\") %></span>\n <button type=\"button\" class=\"demo-trigger\" data-action=\"stimeo--dirty-form#markClean\">\n <%= t(\"components.dirty_form.demo.save\") %>\n </button>\n </div>\n </form>\n\n <form\n class=\"dirty-form\"\n data-controller=\"stimeo--dirty-form\"\n data-stimeo--dirty-form-message-value=\"<%= t('components.dirty_form.demo.second_message') %>\"\n aria-labelledby=\"dirty-form-second-title\"\n >\n <h3 id=\"dirty-form-second-title\" class=\"dirty-form__title\">\n <%= t(\"components.dirty_form.demo.second_title\") %>\n </h3>\n <label class=\"dirty-form__field\">\n <span><%= t(\"components.dirty_form.demo.second_label\") %></span>\n <input type=\"text\" name=\"summary\" value=\"<%= t('components.dirty_form.demo.second_value') %>\">\n </label>\n <div class=\"dirty-form__bar\">\n <span class=\"dirty-form__badge\"><%= t(\"components.dirty_form.demo.unsaved\") %></span>\n <button type=\"button\" class=\"demo-trigger\" data-action=\"stimeo--dirty-form#markClean\">\n <%= t(\"components.dirty_form.demo.save\") %>\n </button>\n </div>\n </form>\n</div>\n"
|
|
119
119
|
},
|
|
120
120
|
"stimeo--dismissible": {
|
|
121
121
|
"file": "examples/dismissible/_demo.html.erb",
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
},
|
|
140
140
|
"stimeo--file-dropzone": {
|
|
141
141
|
"file": "examples/file_dropzone/_demo.html.erb",
|
|
142
|
-
"source": "<%# Markup for the file-dropzone (file drag & drop / image preview) demo.\n Click or keyboard launches the native file input, and drag & drop also adds files.\n It validates accept / maxSize / count and shows image thumbnails via
|
|
142
|
+
"source": "<%# Markup for the file-dropzone (file drag & drop / image preview) demo.\n Click or keyboard launches the native file input, and drag & drop also adds files.\n It validates accept / maxSize / duplicates / count and shows image thumbnails via\n objectURL. The library handles the drop bridge, validation, preview create/revoke,\n focus handoff on removal, mirroring the accepted files back onto the native input,\n and the announcements read by the shared announcer seated below. Drag & drop is\n only an aid — selection is always possible via click / keyboard. %>\n<div class=\"file-dropzone\" data-controller=\"stimeo--file-dropzone\"\n data-stimeo--file-dropzone-max-size-value=\"5242880\"\n data-stimeo--file-dropzone-max-files-value=\"4\"\n data-stimeo--file-dropzone-announce-drag-text-value=\"<%= t(\n 'components.file_dropzone.demo.drag_label'\n ) %>\"\n data-stimeo--file-dropzone-announce-added-text-value=\"<%= t(\n 'components.file_dropzone.demo.announce_added'\n ) %>\"\n data-stimeo--file-dropzone-announce-removed-text-value=\"<%= t(\n 'components.file_dropzone.demo.announce_removed'\n ) %>\"\n data-stimeo--file-dropzone-announce-rejected-type-text-value=\"<%= t(\n 'components.file_dropzone.demo.announce_reject_type'\n ) %>\"\n data-stimeo--file-dropzone-announce-rejected-size-text-value=\"<%= t(\n 'components.file_dropzone.demo.announce_reject_size'\n ) %>\"\n data-stimeo--file-dropzone-announce-rejected-duplicate-text-value=\"<%= t(\n 'components.file_dropzone.demo.announce_reject_duplicate'\n ) %>\"\n data-stimeo--file-dropzone-announce-rejected-count-text-value=\"<%= t(\n 'components.file_dropzone.demo.announce_reject_count'\n ) %>\">\n <div\n class=\"file-dropzone__zone\"\n data-stimeo--file-dropzone-target=\"zone\"\n data-action=\"dragover->stimeo--file-dropzone#onDragOver\n dragleave->stimeo--file-dropzone#onDragLeave\n drop->stimeo--file-dropzone#onDrop\">\n <button\n type=\"button\"\n class=\"demo-trigger file-dropzone__trigger\"\n data-stimeo--file-dropzone-target=\"trigger\"\n data-action=\"click->stimeo--file-dropzone#openDialog\">\n <%= t(\"components.file_dropzone.demo.trigger\") %>\n </button>\n <input\n type=\"file\"\n accept=\"image/*\"\n multiple\n aria-label=\"<%= t('components.file_dropzone.demo.input_label') %>\"\n class=\"file-dropzone__input visually-hidden\"\n data-stimeo--file-dropzone-target=\"input\"\n data-action=\"change->stimeo--file-dropzone#onChange\" />\n </div>\n\n <ul\n class=\"file-dropzone__list\"\n aria-label=\"<%= t('components.file_dropzone.demo.list_label') %>\"\n data-stimeo--file-dropzone-target=\"list\"></ul>\n\n <%# Demo-only: the library accepts only unique images within the limits (5 MB / 4 files)\n and fires stimeo--file-dropzone:reject for the rest — accepted images get a thumbnail\n preview. The reason is already spoken by the shared announcer; this repeats it on\n screen so a rejected file (e.g. an over-size photo) is not mistaken for a broken\n preview. demo.js fills this from the reject event; the reason copy is localized here. %>\n <p class=\"file-dropzone__error\"\n data-file-dropzone-error\n hidden\n data-reason-type=\"<%= t('components.file_dropzone.demo.reject_type') %>\"\n data-reason-size=\"<%= t('components.file_dropzone.demo.reject_size') %>\"\n data-reason-duplicate=\"<%= t('components.file_dropzone.demo.reject_duplicate') %>\"\n data-reason-count=\"<%= t('components.file_dropzone.demo.reject_count') %>\"></p>\n\n <template data-stimeo--file-dropzone-target=\"itemTemplate\">\n <li class=\"file-dropzone__item\" data-stimeo--file-dropzone-target=\"item\">\n <img class=\"file-dropzone__thumb\" data-stimeo--file-dropzone-target=\"thumb\" alt=\"\" hidden />\n <span class=\"file-dropzone__name\" data-stimeo--file-dropzone-target=\"name\"></span>\n <%# Removal is handled by a delegated listener on the list container, so it\n works instantly without waiting on Stimulus wiring a data-action onto the\n dynamically-added button. The library keeps this aria-label and only\n expands {name}, so the accessible name stays in the page's language. %>\n <button\n type=\"button\"\n class=\"file-dropzone__remove\"\n aria-label=\"<%= t('components.file_dropzone.demo.remove_label') %>\"\n data-stimeo--file-dropzone-target=\"remove\">\n <%= t(\"components.file_dropzone.demo.remove\") %>\n </button>\n </li>\n </template>\n\n <%# Shared announcer: additions, rejections, removals, and the drag affordance are\n the transitions worth reading. The dropzone owns no live region of its own. %>\n <div data-controller=\"stimeo--announcer\">\n <div class=\"visually-hidden\"\n data-stimeo--announcer-target=\"polite\"\n aria-live=\"polite\"\n aria-atomic=\"true\"></div>\n </div>\n</div>\n"
|
|
143
143
|
},
|
|
144
144
|
"stimeo--filter": {
|
|
145
145
|
"file": "examples/filter/_demo.html.erb",
|
|
@@ -155,11 +155,11 @@
|
|
|
155
155
|
},
|
|
156
156
|
"stimeo--form-field": {
|
|
157
157
|
"file": "examples/form_field/_demo.html.erb",
|
|
158
|
-
"source": "<%# Markup for the form-field demo.\n Associates label / description / error with the control via aria-describedby /\n aria-invalid / aria-errormessage. Showing/clearing the error uses the action\n parameter (message) and #clearError. The look
|
|
158
|
+
"source": "<%# Markup for the form-field demo.\n Associates label / description / error with the control via aria-describedby /\n aria-invalid / aria-errormessage. Showing/clearing the error uses the action\n parameter (message) and #clearError. The look switches on\n data-stimeo--form-field-invalid and aria-invalid. %>\n<div class=\"form-field-demo\" data-controller=\"stimeo--form-field\"\n data-stimeo--form-field-focus-on-error-value=\"true\">\n <label class=\"form-field-demo__label\" for=\"ff-email\">\n <%= t(\"components.form_field.demo.label\") %>\n </label>\n\n <input class=\"form-field-demo__control\" id=\"ff-email\" type=\"email\" aria-invalid=\"false\"\n placeholder=\"<%= t('components.form_field.demo.placeholder') %>\"\n data-stimeo--form-field-target=\"control\" />\n\n <%# Helper description. It is assigned an id and linked into the control's\n aria-describedby. %>\n <p class=\"form-field-demo__description\" data-stimeo--form-field-target=\"description\">\n <%= t(\"components.form_field.demo.hint\") %>\n </p>\n\n <%# Note clarifying the demo's intent (this part only wires up the error state;\n it doesn't validate or clear the value). %>\n <p class=\"form-field-demo__note\"><%= t(\"components.form_field.demo.note\") %></p>\n\n <%# Visual error region. Starts hidden; speech is delegated to the shared\n announcer seated below. %>\n <p class=\"form-field-demo__error\" hidden\n data-stimeo--form-field-target=\"error\"></p>\n\n <div class=\"form-field-demo__actions\">\n <%# setError reads the message from the action parameter (no consumer JS needed). %>\n <button type=\"button\" class=\"demo-trigger\"\n data-stimeo--form-field-message-param=\"<%= t('components.form_field.demo.error') %>\"\n data-action=\"click->stimeo--form-field#setError\">\n <%= t(\"components.form_field.demo.validate\") %>\n </button>\n <button type=\"button\" class=\"demo-trigger\"\n data-action=\"click->stimeo--form-field#clearError\">\n <%= t(\"components.form_field.demo.clear\") %>\n </button>\n </div>\n\n <%# Helper region that subscribes to the validate event and shows the valid\n state only (updated by demo.js). %>\n <p class=\"form-field-demo__status\" id=\"ff-status\" aria-live=\"polite\"\n data-valid-text=\"<%= t('components.form_field.demo.valid') %>\"></p>\n\n <%# Assertive announcement target. It is seated in the accessibility tree ahead\n of the first error, which is what makes the message observable. %>\n <div data-controller=\"stimeo--announcer\">\n <div class=\"visually-hidden\" data-stimeo--announcer-target=\"assertive\"\n aria-live=\"assertive\" aria-atomic=\"true\"></div>\n </div>\n</div>\n"
|
|
159
159
|
},
|
|
160
160
|
"stimeo--form-validation": {
|
|
161
161
|
"file": "examples/form_validation/_demo.html.erb",
|
|
162
|
-
"source": "<%# Markup for the form-validation demo.\n stimeo--form-validation orchestrates WHEN native constraint validation runs\n (submit / blur / change / input) and routes each control's
|
|
162
|
+
"source": "<%# Markup for the form-validation demo.\n stimeo--form-validation orchestrates WHEN native constraint validation runs\n (submit / blur / change / input) and routes each control's message into its\n stimeo--form-field visual error — the ARIA wiring stays in form-field, and\n the speech goes to the shared announcer seated at the end of this form.\n Rules are plain markup attributes (required, type=\"email\", plus the\n declarative disallow=\"whitespace\"); the wording comes from localized\n data-stimeo--form-validation-message-* overrides rather than the browser, so\n the catalog reads the same in both locales. The plan listbox joins through a\n validatable mirror: <input type=\"text\" hidden required> — the hidden\n ATTRIBUTE, not type=\"hidden\", which is barred from constraint validation.\n The authored novalidate keeps the no-JS fallback graceful (the controller\n preserves it). Valid submissions are kept on the page by demo.js so the\n catalog can show a success status. %>\n<form class=\"form-validation-demo\" action=\"#\" method=\"get\" novalidate\n data-controller=\"stimeo--form-validation\"\n data-stimeo--form-validation-stimeo--form-field-outlet=\".form-validation-demo__field\">\n\n <div class=\"form-validation-demo__field\" data-controller=\"stimeo--form-field\">\n <label class=\"form-validation-demo__label\" for=\"fv-email\">\n <%= t(\"components.form_validation.demo.email_label\") %>\n </label>\n <input class=\"form-validation-demo__control\" id=\"fv-email\" name=\"email\" type=\"email\"\n required placeholder=\"<%= t('components.form_validation.demo.email_placeholder') %>\"\n data-stimeo--form-validation-message-value-missing=\n \"<%= t('components.form_validation.demo.messages.email_required') %>\"\n data-stimeo--form-validation-message-type-mismatch=\n \"<%= t('components.form_validation.demo.messages.email_type') %>\"\n data-stimeo--form-field-target=\"control\" />\n <%# Visual error only. Speech goes through the shared announcer seated below. %>\n <p class=\"form-validation-demo__error\" hidden\n data-stimeo--form-field-target=\"error\"></p>\n </div>\n\n <div class=\"form-validation-demo__field\" data-controller=\"stimeo--form-field\">\n <label class=\"form-validation-demo__label\" for=\"fv-name\">\n <%= t(\"components.form_validation.demo.name_label\") %>\n </label>\n <input class=\"form-validation-demo__control\" id=\"fv-name\" name=\"name\" type=\"text\"\n required placeholder=\"<%= t('components.form_validation.demo.name_placeholder') %>\"\n data-stimeo--form-validation-disallow=\"whitespace\"\n data-stimeo--form-validation-message-value-missing=\n \"<%= t('components.form_validation.demo.messages.name_required') %>\"\n data-stimeo--form-validation-message-whitespace=\n \"<%= t('components.form_validation.demo.messages.name_whitespace') %>\"\n data-stimeo--form-field-target=\"control\" />\n <p class=\"form-validation-demo__error\" hidden\n data-stimeo--form-field-target=\"error\"></p>\n </div>\n\n <%# The listbox keeps its committed value in the mirror below. The form-field\n control is the visible trigger, so aria-invalid and invalid focus land there. %>\n <div class=\"form-validation-demo__field listbox\"\n data-controller=\"stimeo--form-field stimeo--listbox\">\n <span id=\"fv-plan-label\" class=\"form-validation-demo__label\">\n <%= t(\"components.form_validation.demo.plan_label\") %>\n </span>\n <button\n type=\"button\"\n class=\"demo-trigger listbox__trigger\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded=\"false\"\n aria-controls=\"fv-plan-options\"\n aria-labelledby=\"fv-plan-label fv-plan-value\"\n data-stimeo--listbox-target=\"trigger\"\n data-stimeo--form-field-target=\"control\"\n data-action=\"click->stimeo--listbox#toggle keydown->stimeo--listbox#onTriggerKeydown\">\n <span id=\"fv-plan-value\" data-stimeo--listbox-target=\"value\">\n <%= t(\"components.form_validation.demo.plan_placeholder\") %>\n </span>\n <span class=\"listbox__chevron\" aria-hidden=\"true\">▾</span>\n </button>\n <ul id=\"fv-plan-options\" class=\"listbox__list\" role=\"listbox\"\n aria-labelledby=\"fv-plan-label\" hidden data-stimeo--listbox-target=\"list\">\n <% %w[free pro team].each_with_index do |plan, index| %>\n <li id=\"fv-plan-opt-<%= index %>\" class=\"listbox__option\" role=\"option\"\n aria-selected=\"false\" data-value=\"<%= plan %>\"\n data-stimeo--listbox-target=\"option\"\n data-action=\"click->stimeo--listbox#select\">\n <%= t(\"components.form_validation.demo.plans.#{plan}\") %>\n </li>\n <% end %>\n </ul>\n <%# Validatable mirror: the hidden attribute participates in constraint\n validation and submits with the form — type=\"hidden\" would do neither. %>\n <input type=\"text\" hidden required name=\"plan\"\n data-stimeo--form-validation-message-value-missing=\n \"<%= t('components.form_validation.demo.messages.plan_required') %>\"\n data-stimeo--listbox-target=\"field\" />\n <p class=\"form-validation-demo__error\" hidden\n data-stimeo--form-field-target=\"error\"></p>\n </div>\n\n <p class=\"form-validation-demo__note\"><%= t(\"components.form_validation.demo.note\") %></p>\n\n <button type=\"submit\" class=\"demo-trigger\">\n <%= t(\"components.form_validation.demo.submit\") %>\n </button>\n\n <%# Status line updated by demo.js; templates ride data-* so the copy stays bilingual. %>\n <p class=\"form-validation-demo__status\" id=\"fv-status\" aria-live=\"polite\"\n data-valid-text=\"<%= t('components.form_validation.demo.valid_status') %>\"\n data-invalid-template=\"<%= t('components.form_validation.demo.invalid_template') %>\"></p>\n\n <%# Assertive announcement target for the field errors form-field sets. One\n receiver serves every field, and it is seated in the accessibility tree\n ahead of the first error, which is what makes the message observable. %>\n <div data-controller=\"stimeo--announcer\">\n <div class=\"visually-hidden\" data-stimeo--announcer-target=\"assertive\"\n aria-live=\"assertive\" aria-atomic=\"true\"></div>\n </div>\n</form>\n"
|
|
163
163
|
},
|
|
164
164
|
"stimeo--frame-loading": {
|
|
165
165
|
"file": "examples/frame_loading/_demo.html.erb",
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
},
|
|
228
228
|
"stimeo--nested-form": {
|
|
229
229
|
"file": "examples/nested_form/_demo.html.erb",
|
|
230
|
-
"source": "<%# Markup for the nested / dynamic fields demo (
|
|
230
|
+
"source": "<%# Markup for the nested / dynamic fields demo (invoice-style line items).\n The controller clones the <template> row (renumbering __INDEX__), removes rows by\n dropping unsaved ones / flagging _destroy on persisted ones, enforces min/max, and\n announces the count through a shared stimeo--announcer. Remove buttons are handled\n by delegation, so cloned rows need no per-row wiring. %>\n<%\n item_label = t(\"components.nested_form.demo.item_label\")\n remove_label = t(\"components.nested_form.demo.remove\")\n count_message = t(\"components.nested_form.demo.count_message\")\n persisted_value = t(\"components.nested_form.demo.persisted_value\")\n%>\n<div class=\"nested-demo\" data-controller=\"stimeo--nested-form\"\n data-stimeo--nested-form-min-value=\"1\"\n data-stimeo--nested-form-max-value=\"5\"\n data-stimeo--nested-form-count-message-value=\"<%= count_message %>\">\n <div class=\"nested-demo__list\" data-stimeo--nested-form-target=\"list\">\n <fieldset class=\"nested-demo__row\">\n <label class=\"nested-demo__field\">\n <span><%= item_label %></span>\n <input type=\"text\" class=\"demo-input\" name=\"order[items_attributes][0][name]\">\n </label>\n <button type=\"button\" class=\"demo-trigger\"\n data-stimeo--nested-form-target=\"remove\"><%= remove_label %></button>\n </fieldset>\n <%# A persisted row: its _destroy flag makes Remove hide it instead of deleting it. %>\n <fieldset class=\"nested-demo__row\">\n <input type=\"hidden\" name=\"order[items_attributes][1][_destroy]\" value=\"0\"\n data-stimeo--nested-form-target=\"destroyFlag\">\n <label class=\"nested-demo__field\">\n <span><%= item_label %></span>\n <input type=\"text\" class=\"demo-input\" value=\"<%= persisted_value %>\"\n name=\"order[items_attributes][1][name]\">\n </label>\n <button type=\"button\" class=\"demo-trigger\"\n data-stimeo--nested-form-target=\"remove\"><%= remove_label %></button>\n </fieldset>\n </div>\n\n <template data-stimeo--nested-form-target=\"template\">\n <fieldset class=\"nested-demo__row\">\n <label class=\"nested-demo__field\">\n <span><%= item_label %></span>\n <input type=\"text\" class=\"demo-input\" name=\"order[items_attributes][__INDEX__][name]\">\n </label>\n <button type=\"button\" class=\"demo-trigger\"\n data-stimeo--nested-form-target=\"remove\"><%= remove_label %></button>\n </fieldset>\n </template>\n\n <button type=\"button\" class=\"demo-trigger\" data-stimeo--nested-form-target=\"add\"\n data-action=\"click->stimeo--nested-form#add\">\n <%= t(\"components.nested_form.demo.add\") %>\n </button>\n\n <%# Shared announcer: row count changes are read out without moving focus away. %>\n <div data-controller=\"stimeo--announcer\">\n <div class=\"visually-hidden\" data-stimeo--announcer-target=\"polite\"\n aria-live=\"polite\" aria-atomic=\"true\"></div>\n </div>\n</div>\n"
|
|
231
231
|
},
|
|
232
232
|
"stimeo--network-status": {
|
|
233
233
|
"file": "examples/network_status/_demo.html.erb",
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
},
|
|
244
244
|
"stimeo--otp": {
|
|
245
245
|
"file": "examples/otp/_demo.html.erb",
|
|
246
|
-
"source": "<%# Markup for the otp (OTP PIN passcode) demo.\n Provides auto-advance on entry in each field, Backspace to
|
|
246
|
+
"source": "<%# Markup for the otp (OTP PIN passcode) demo.\n Provides auto-advance on entry in each field, Backspace to clear, paste and\n autofill splitting, and value sync. The digit count is the number of fields. %>\n<div\n class=\"otp-demo\"\n id=\"otp-passcode\"\n data-controller=\"stimeo--otp\"\n data-stimeo--otp-pattern-value=\"[0-9]\"\n role=\"group\"\n aria-label=\"<%= t(\"components.otp.demo.label\") %>\"\n>\n\n <div class=\"otp-demo__label\"><%= t(\"components.otp.demo.label\") %></div>\n\n <div class=\"otp-demo__fields\">\n <% 6.times do |i| %>\n <input\n class=\"otp-demo__field\"\n type=\"text\"\n inputmode=\"numeric\"\n maxlength=\"1\"\n autocomplete=\"one-time-code\"\n data-stimeo--otp-target=\"field\"\n data-action=\"\n input->stimeo--otp#onInput\n keydown->stimeo--otp#onKeydown\n paste->stimeo--otp#onPaste\n pointerdown->stimeo--otp#onPointerDown\n \"\n aria-label=\"<%= t(\"components.otp.demo.digit_label\", position: i + 1) %>\"\n />\n <% end %>\n </div>\n\n <input\n type=\"hidden\"\n data-stimeo--otp-target=\"value\"\n name=\"otp\"\n />\n\n <%# Region for invalid-input / full-width-character warning messages. %>\n <div\n data-stimeo--otp-target=\"error\"\n id=\"otp-error-message\"\n class=\"otp-demo__error\"\n role=\"alert\"\n aria-live=\"polite\"\n hidden\n >\n <span class=\"otp-demo__error-badge\">!</span>\n <span class=\"otp-demo__error-text\">\n <%= t(\"components.otp.demo.invalid_msg\") %>\n </span>\n </div>\n\n <%# The completion message is shown by CSS reading data-state on the root, so the\n demo script only has to fill in the code itself. %>\n <div id=\"otp-complete-message\" class=\"otp-demo__message\">\n <span class=\"otp-demo__success-badge\">✓</span>\n <span class=\"otp-demo__success-text\">\n <%= t(\"components.otp.demo.complete_msg\") %>\n <strong id=\"otp-success-code\"></strong>\n </span>\n </div>\n\n <button type=\"button\" class=\"demo-trigger otp-demo__clear\" data-action=\"stimeo--otp#clear\">\n <%= t(\"components.otp.demo.clear\") %>\n </button>\n</div>\n"
|
|
247
247
|
},
|
|
248
248
|
"stimeo--overflow-indicator": {
|
|
249
249
|
"file": "examples/overflow_indicator/_demo.html.erb",
|
|
@@ -347,7 +347,7 @@
|
|
|
347
347
|
},
|
|
348
348
|
"stimeo--separator": {
|
|
349
349
|
"file": "examples/separator/_demo.html.erb",
|
|
350
|
-
"source": "<%#
|
|
350
|
+
"source": "<%# Separator demo markup. The first separator is decorative; the other two are\n focusable and value-bearing, dispatching change as the arrow keys adjust them.\n The consumer-owned demo.js and demo.css turn that value into pane sizes and\n the divider's appearance. %>\n<div class=\"separator-demo\">\n <p class=\"separator-demo__text\"><%= t(\"components.separator.demo.intro\") %></p>\n <div\n class=\"separator separator--horizontal\"\n data-controller=\"stimeo--separator\"\n data-stimeo--separator-orientation-value=\"horizontal\"></div>\n <p class=\"separator-demo__text\"><%= t(\"components.separator.demo.after\") %></p>\n\n <div class=\"separator-demo__split\">\n <%# The primary pane. Its width follows --separator-split, so the separator's\n Value reports this pane's size: ArrowRight raises the value while moving\n the vertical divider right. %>\n <div class=\"separator-demo__pane\" id=\"separator-demo-primary\">\n <%= t(\"components.separator.demo.left\") %>\n </div>\n <div\n class=\"separator separator--vertical\"\n <%# Reuse the primary pane's visible text as the separator's name. %>\n aria-labelledby=\"separator-demo-primary\"\n aria-controls=\"separator-demo-primary\"\n data-controller=\"stimeo--separator\"\n data-stimeo--separator-orientation-value=\"vertical\"\n data-stimeo--separator-focusable-value=\"true\"\n data-stimeo--separator-min-value=\"20\"\n data-stimeo--separator-max-value=\"80\"\n data-stimeo--separator-step-value=\"5\"\n data-stimeo--separator-value-value=\"50\"\n data-action=\"keydown->stimeo--separator#onKeydown\"></div>\n <div class=\"separator-demo__pane\"><%= t(\"components.separator.demo.right\") %></div>\n </div>\n\n <p class=\"separator-demo__text\"><%= t(\"components.separator.demo.after_horizontal\") %></p>\n\n <%# A horizontal separator takes ArrowUp and ArrowDown. demo.js maps the same\n --separator-split custom property onto the top / bottom pane ratio. %>\n <div class=\"separator-demo__split separator-demo__split--stacked\">\n <div class=\"separator-demo__pane\"><%= t(\"components.separator.demo.top\") %></div>\n <div\n class=\"separator separator--horizontal-handle\"\n aria-labelledby=\"separator-demo-primary-stacked\"\n aria-controls=\"separator-demo-primary-stacked\"\n data-controller=\"stimeo--separator\"\n data-stimeo--separator-orientation-value=\"horizontal\"\n data-stimeo--separator-focusable-value=\"true\"\n data-stimeo--separator-min-value=\"20\"\n data-stimeo--separator-max-value=\"80\"\n data-stimeo--separator-step-value=\"5\"\n data-stimeo--separator-value-value=\"50\"\n data-action=\"keydown->stimeo--separator#onKeydown\"></div>\n <%# Here the lower pane is the primary one. Flexing the last child from\n --separator-split makes ArrowUp raise the primary pane's value while\n moving the divider up. %>\n <div class=\"separator-demo__pane\" id=\"separator-demo-primary-stacked\">\n <%= t(\"components.separator.demo.bottom\") %>\n </div>\n </div>\n</div>\n"
|
|
351
351
|
},
|
|
352
352
|
"stimeo--sidebar": {
|
|
353
353
|
"file": "examples/sidebar/_demo.html.erb",
|
|
@@ -391,7 +391,7 @@
|
|
|
391
391
|
},
|
|
392
392
|
"stimeo--submit-once": {
|
|
393
393
|
"file": "examples/submit_once/_demo.html.erb",
|
|
394
|
-
"source": "<%# Submit-once demo
|
|
394
|
+
"source": "<%# Submit-once demo. A structured idle / busy target pair keeps the DOM the\n consumer authored while the button is disabled. This catalog has no server,\n so demo.js fires Turbo's start / end lifecycle around a short fake round\n trip. %>\n<% announce_start = t(\"components.submit_once.demo.announce_start\") %>\n<% announce_ready = t(\"components.submit_once.demo.announce_ready\") %>\n<% submit_label = t(\"components.submit_once.demo.submit\") %>\n<% busy_label = t(\"components.submit_once.demo.busy\") %>\n<div class=\"submit-once-demo\">\n <form\n data-controller=\"stimeo--submit-once\"\n data-stimeo--submit-once-announce-text-value=\"<%= announce_start %>\"\n data-stimeo--submit-once-announce-ready-text-value=\"<%= announce_ready %>\">\n <label class=\"submit-once-demo__field\">\n <span><%= t(\"components.submit_once.demo.label\") %></span>\n <input type=\"text\" name=\"title\" class=\"submit-once-demo__input\">\n </label>\n <button type=\"submit\" class=\"demo-trigger\" data-stimeo--submit-once-target=\"submit\">\n <span data-stimeo--submit-once-target=\"idle\"><%= submit_label %></span>\n <span data-stimeo--submit-once-target=\"busy\" hidden><%= busy_label %></span>\n </button>\n </form>\n\n <%# aria-busy exposes state that can be queried; this always-present region is\n what announces the transition itself, without moving focus. %>\n <div data-controller=\"stimeo--announcer\">\n <div class=\"visually-hidden\" data-stimeo--announcer-target=\"polite\"\n aria-live=\"polite\" aria-atomic=\"true\"></div>\n </div>\n</div>\n"
|
|
395
395
|
},
|
|
396
396
|
"stimeo--switch": {
|
|
397
397
|
"file": "examples/switch/_demo.html.erb",
|