poetry-ui 0.0.2
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.
- checksums.yaml +7 -0
- data/.gitattributes +6 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +87 -0
- data/THIRD_PARTY_NOTICES.md +201 -0
- data/app/components/poetry/ui/accordion/component.html.erb +3 -0
- data/app/components/poetry/ui/accordion/component.rb +197 -0
- data/app/components/poetry/ui/accordion/preview.rb +39 -0
- data/app/components/poetry/ui/accordion/style.rb +37 -0
- data/app/components/poetry/ui/alert/component.html.erb +6 -0
- data/app/components/poetry/ui/alert/component.rb +61 -0
- data/app/components/poetry/ui/alert/preview.rb +35 -0
- data/app/components/poetry/ui/alert/style.rb +24 -0
- data/app/components/poetry/ui/alert_dialog/component.html.erb +17 -0
- data/app/components/poetry/ui/alert_dialog/component.rb +208 -0
- data/app/components/poetry/ui/alert_dialog/preview.rb +48 -0
- data/app/components/poetry/ui/alert_dialog/style.rb +46 -0
- data/app/components/poetry/ui/aspect_ratio/component.rb +63 -0
- data/app/components/poetry/ui/aspect_ratio/preview.rb +29 -0
- data/app/components/poetry/ui/aspect_ratio/style.rb +13 -0
- data/app/components/poetry/ui/attachment/component.html.erb +13 -0
- data/app/components/poetry/ui/attachment/component.rb +139 -0
- data/app/components/poetry/ui/attachment/preview.rb +83 -0
- data/app/components/poetry/ui/attachment/style.rb +59 -0
- data/app/components/poetry/ui/autocomplete/component.html.erb +16 -0
- data/app/components/poetry/ui/autocomplete/component.rb +193 -0
- data/app/components/poetry/ui/autocomplete/preview.rb +39 -0
- data/app/components/poetry/ui/autocomplete/style.rb +18 -0
- data/app/components/poetry/ui/avatar/component.rb +103 -0
- data/app/components/poetry/ui/avatar/group_preview.html.erb +11 -0
- data/app/components/poetry/ui/avatar/preview.rb +50 -0
- data/app/components/poetry/ui/avatar/style.rb +34 -0
- data/app/components/poetry/ui/badge/component.rb +73 -0
- data/app/components/poetry/ui/badge/preview.rb +54 -0
- data/app/components/poetry/ui/badge/style.rb +35 -0
- data/app/components/poetry/ui/breadcrumb/component.html.erb +32 -0
- data/app/components/poetry/ui/breadcrumb/component.rb +102 -0
- data/app/components/poetry/ui/breadcrumb/dropdown_crumb_preview.html.erb +21 -0
- data/app/components/poetry/ui/breadcrumb/preview.rb +45 -0
- data/app/components/poetry/ui/breadcrumb/style.rb +25 -0
- data/app/components/poetry/ui/bubble/component.html.erb +4 -0
- data/app/components/poetry/ui/bubble/component.rb +106 -0
- data/app/components/poetry/ui/bubble/preview.rb +62 -0
- data/app/components/poetry/ui/bubble/style.rb +47 -0
- data/app/components/poetry/ui/button/component.html.erb +14 -0
- data/app/components/poetry/ui/button/component.rb +168 -0
- data/app/components/poetry/ui/button/preview.rb +94 -0
- data/app/components/poetry/ui/button/style.rb +41 -0
- data/app/components/poetry/ui/button_group/component.rb +70 -0
- data/app/components/poetry/ui/button_group/popup_triggers_preview.html.erb +21 -0
- data/app/components/poetry/ui/button_group/preview.rb +46 -0
- data/app/components/poetry/ui/button_group/style.rb +27 -0
- data/app/components/poetry/ui/button_group/text_prefix_preview.html.erb +7 -0
- data/app/components/poetry/ui/calendar/component.html.erb +72 -0
- data/app/components/poetry/ui/calendar/component.rb +366 -0
- data/app/components/poetry/ui/calendar/preview.rb +55 -0
- data/app/components/poetry/ui/calendar/style.rb +55 -0
- data/app/components/poetry/ui/card/component.html.erb +11 -0
- data/app/components/poetry/ui/card/component.rb +90 -0
- data/app/components/poetry/ui/card/preview.rb +29 -0
- data/app/components/poetry/ui/card/style.rb +23 -0
- data/app/components/poetry/ui/carousel/component.html.erb +17 -0
- data/app/components/poetry/ui/carousel/component.rb +179 -0
- data/app/components/poetry/ui/carousel/preview.rb +67 -0
- data/app/components/poetry/ui/carousel/style.rb +39 -0
- data/app/components/poetry/ui/checkbox/component.html.erb +22 -0
- data/app/components/poetry/ui/checkbox/component.rb +179 -0
- data/app/components/poetry/ui/checkbox/preview.rb +68 -0
- data/app/components/poetry/ui/checkbox/style.rb +28 -0
- data/app/components/poetry/ui/clipboard_text/component.html.erb +15 -0
- data/app/components/poetry/ui/clipboard_text/component.rb +154 -0
- data/app/components/poetry/ui/clipboard_text/preview.rb +24 -0
- data/app/components/poetry/ui/clipboard_text/style.rb +23 -0
- data/app/components/poetry/ui/code_block/component.html.erb +13 -0
- data/app/components/poetry/ui/code_block/component.rb +141 -0
- data/app/components/poetry/ui/code_block/preview.rb +40 -0
- data/app/components/poetry/ui/code_block/style.rb +38 -0
- data/app/components/poetry/ui/collapsible/component.html.erb +4 -0
- data/app/components/poetry/ui/collapsible/component.rb +134 -0
- data/app/components/poetry/ui/collapsible/preview.rb +24 -0
- data/app/components/poetry/ui/combobox/component.html.erb +49 -0
- data/app/components/poetry/ui/combobox/component.rb +1086 -0
- data/app/components/poetry/ui/combobox/preview.rb +164 -0
- data/app/components/poetry/ui/combobox/style.rb +148 -0
- data/app/components/poetry/ui/command/component.html.erb +20 -0
- data/app/components/poetry/ui/command/component.rb +526 -0
- data/app/components/poetry/ui/command/dialog_component.html.erb +14 -0
- data/app/components/poetry/ui/command/dialog_component.rb +206 -0
- data/app/components/poetry/ui/command/dialog_preview.rb +39 -0
- data/app/components/poetry/ui/command/preview.rb +121 -0
- data/app/components/poetry/ui/command/style.rb +78 -0
- data/app/components/poetry/ui/composable_trigger.rb +63 -0
- data/app/components/poetry/ui/context_menu/component.html.erb +6 -0
- data/app/components/poetry/ui/context_menu/component.rb +358 -0
- data/app/components/poetry/ui/context_menu/preview.rb +111 -0
- data/app/components/poetry/ui/context_menu/style.rb +59 -0
- data/app/components/poetry/ui/data_table/component.html.erb +78 -0
- data/app/components/poetry/ui/data_table/component.rb +277 -0
- data/app/components/poetry/ui/data_table/preview.rb +68 -0
- data/app/components/poetry/ui/data_table/state.rb +115 -0
- data/app/components/poetry/ui/data_table/style.rb +42 -0
- data/app/components/poetry/ui/date_field/component.html.erb +7 -0
- data/app/components/poetry/ui/date_field/component.rb +209 -0
- data/app/components/poetry/ui/date_field/preview.rb +42 -0
- data/app/components/poetry/ui/date_field/style.rb +35 -0
- data/app/components/poetry/ui/date_picker/component.html.erb +23 -0
- data/app/components/poetry/ui/date_picker/component.rb +242 -0
- data/app/components/poetry/ui/date_picker/preview.rb +31 -0
- data/app/components/poetry/ui/date_picker/style.rb +25 -0
- data/app/components/poetry/ui/deferred/component.html.erb +16 -0
- data/app/components/poetry/ui/deferred/component.rb +90 -0
- data/app/components/poetry/ui/deferred/preview.rb +24 -0
- data/app/components/poetry/ui/dialog/component.html.erb +21 -0
- data/app/components/poetry/ui/dialog/component.rb +194 -0
- data/app/components/poetry/ui/dialog/preview.rb +33 -0
- data/app/components/poetry/ui/dialog/style.rb +30 -0
- data/app/components/poetry/ui/drawer/component.html.erb +16 -0
- data/app/components/poetry/ui/drawer/component.rb +207 -0
- data/app/components/poetry/ui/drawer/preview.rb +69 -0
- data/app/components/poetry/ui/drawer/style.rb +105 -0
- data/app/components/poetry/ui/dropdown_menu/component.html.erb +6 -0
- data/app/components/poetry/ui/dropdown_menu/component.rb +350 -0
- data/app/components/poetry/ui/dropdown_menu/preview.rb +101 -0
- data/app/components/poetry/ui/dropdown_menu/style.rb +60 -0
- data/app/components/poetry/ui/empty/component.html.erb +10 -0
- data/app/components/poetry/ui/empty/component.rb +79 -0
- data/app/components/poetry/ui/empty/preview.rb +27 -0
- data/app/components/poetry/ui/empty/style.rb +27 -0
- data/app/components/poetry/ui/family_identity.rb +52 -0
- data/app/components/poetry/ui/field/component.html.erb +19 -0
- data/app/components/poetry/ui/field/component.rb +183 -0
- data/app/components/poetry/ui/field/preview.html.erb +30 -0
- data/app/components/poetry/ui/field/preview.rb +72 -0
- data/app/components/poetry/ui/field/style.rb +68 -0
- data/app/components/poetry/ui/field_group/component.rb +61 -0
- data/app/components/poetry/ui/field_group/preview.html.erb +30 -0
- data/app/components/poetry/ui/field_group/preview.rb +20 -0
- data/app/components/poetry/ui/field_group/style.rb +25 -0
- data/app/components/poetry/ui/field_separator/component.rb +70 -0
- data/app/components/poetry/ui/field_separator/preview.rb +18 -0
- data/app/components/poetry/ui/field_separator/style.rb +20 -0
- data/app/components/poetry/ui/fieldset/component.rb +90 -0
- data/app/components/poetry/ui/fieldset/preview.html.erb +22 -0
- data/app/components/poetry/ui/fieldset/preview.rb +25 -0
- data/app/components/poetry/ui/fieldset/style.rb +18 -0
- data/app/components/poetry/ui/file_input/component.html.erb +14 -0
- data/app/components/poetry/ui/file_input/component.rb +188 -0
- data/app/components/poetry/ui/file_input/preview.rb +30 -0
- data/app/components/poetry/ui/file_input/style.rb +35 -0
- data/app/components/poetry/ui/hover_card/component.html.erb +6 -0
- data/app/components/poetry/ui/hover_card/component.rb +201 -0
- data/app/components/poetry/ui/hover_card/preview.rb +60 -0
- data/app/components/poetry/ui/hover_card/style.rb +17 -0
- data/app/components/poetry/ui/icon/component.rb +127 -0
- data/app/components/poetry/ui/icon/preview.rb +21 -0
- data/app/components/poetry/ui/input/component.rb +80 -0
- data/app/components/poetry/ui/input/preview.rb +35 -0
- data/app/components/poetry/ui/input/style.rb +18 -0
- data/app/components/poetry/ui/input_group/button_preview.html.erb +12 -0
- data/app/components/poetry/ui/input_group/component.rb +69 -0
- data/app/components/poetry/ui/input_group/preview.rb +23 -0
- data/app/components/poetry/ui/input_group/search_preview.html.erb +13 -0
- data/app/components/poetry/ui/input_group/style.rb +40 -0
- data/app/components/poetry/ui/input_group/textarea_preview.html.erb +10 -0
- data/app/components/poetry/ui/input_group_field.rb +61 -0
- data/app/components/poetry/ui/input_otp/component.html.erb +25 -0
- data/app/components/poetry/ui/input_otp/component.rb +250 -0
- data/app/components/poetry/ui/input_otp/preview.rb +91 -0
- data/app/components/poetry/ui/input_otp/style.rb +36 -0
- data/app/components/poetry/ui/item/component.html.erb +13 -0
- data/app/components/poetry/ui/item/component.rb +99 -0
- data/app/components/poetry/ui/item/group_preview.html.erb +15 -0
- data/app/components/poetry/ui/item/preview.rb +52 -0
- data/app/components/poetry/ui/item/style.rb +45 -0
- data/app/components/poetry/ui/kbd/component.rb +47 -0
- data/app/components/poetry/ui/kbd/group_preview.html.erb +4 -0
- data/app/components/poetry/ui/kbd/preview.rb +23 -0
- data/app/components/poetry/ui/kbd/style.rb +13 -0
- data/app/components/poetry/ui/label/component.rb +46 -0
- data/app/components/poetry/ui/label/preview.html.erb +5 -0
- data/app/components/poetry/ui/label/preview.rb +16 -0
- data/app/components/poetry/ui/label/style.rb +13 -0
- data/app/components/poetry/ui/link/component.rb +62 -0
- data/app/components/poetry/ui/link/preview.rb +31 -0
- data/app/components/poetry/ui/link/style.rb +20 -0
- data/app/components/poetry/ui/marker/component.html.erb +4 -0
- data/app/components/poetry/ui/marker/component.rb +81 -0
- data/app/components/poetry/ui/marker/preview.rb +43 -0
- data/app/components/poetry/ui/marker/style.rb +24 -0
- data/app/components/poetry/ui/menubar/component.html.erb +3 -0
- data/app/components/poetry/ui/menubar/component.rb +493 -0
- data/app/components/poetry/ui/menubar/preview.rb +164 -0
- data/app/components/poetry/ui/menubar/style.rb +71 -0
- data/app/components/poetry/ui/menus.rb +386 -0
- data/app/components/poetry/ui/message/component.html.erb +8 -0
- data/app/components/poetry/ui/message/component.rb +64 -0
- data/app/components/poetry/ui/message/preview.rb +33 -0
- data/app/components/poetry/ui/message/style.rb +29 -0
- data/app/components/poetry/ui/message_scroller/component.html.erb +15 -0
- data/app/components/poetry/ui/message_scroller/component.rb +163 -0
- data/app/components/poetry/ui/message_scroller/preview.rb +33 -0
- data/app/components/poetry/ui/message_scroller/style.rb +39 -0
- data/app/components/poetry/ui/metadata_list/component.rb +88 -0
- data/app/components/poetry/ui/metadata_list/preview.rb +55 -0
- data/app/components/poetry/ui/metadata_list/style.rb +35 -0
- data/app/components/poetry/ui/meter/component.rb +117 -0
- data/app/components/poetry/ui/meter/preview.rb +28 -0
- data/app/components/poetry/ui/meter/style.rb +16 -0
- data/app/components/poetry/ui/native_select/component.rb +124 -0
- data/app/components/poetry/ui/native_select/labelled_preview.html.erb +7 -0
- data/app/components/poetry/ui/native_select/preview.rb +20 -0
- data/app/components/poetry/ui/native_select/style.rb +22 -0
- data/app/components/poetry/ui/navigation_menu/bar_preview.html.erb +14 -0
- data/app/components/poetry/ui/navigation_menu/component.html.erb +25 -0
- data/app/components/poetry/ui/navigation_menu/component.rb +254 -0
- data/app/components/poetry/ui/navigation_menu/preview.rb +20 -0
- data/app/components/poetry/ui/navigation_menu/style.rb +73 -0
- data/app/components/poetry/ui/navigation_menu/viewport_preview.html.erb +23 -0
- data/app/components/poetry/ui/number_field/component.html.erb +19 -0
- data/app/components/poetry/ui/number_field/component.rb +263 -0
- data/app/components/poetry/ui/number_field/preview.rb +66 -0
- data/app/components/poetry/ui/number_field/style.rb +14 -0
- data/app/components/poetry/ui/pagination/component.html.erb +40 -0
- data/app/components/poetry/ui/pagination/component.rb +182 -0
- data/app/components/poetry/ui/pagination/preview.rb +47 -0
- data/app/components/poetry/ui/pagination/style.rb +27 -0
- data/app/components/poetry/ui/popover/component.html.erb +17 -0
- data/app/components/poetry/ui/popover/component.rb +203 -0
- data/app/components/poetry/ui/popover/preview.html.erb +29 -0
- data/app/components/poetry/ui/popover/preview.rb +66 -0
- data/app/components/poetry/ui/popover/style.rb +26 -0
- data/app/components/poetry/ui/popper_consumer.rb +69 -0
- data/app/components/poetry/ui/progress/component.rb +95 -0
- data/app/components/poetry/ui/progress/preview.rb +22 -0
- data/app/components/poetry/ui/progress/style.rb +19 -0
- data/app/components/poetry/ui/questionnaire/component.html.erb +80 -0
- data/app/components/poetry/ui/questionnaire/component.rb +396 -0
- data/app/components/poetry/ui/questionnaire/preview.rb +99 -0
- data/app/components/poetry/ui/questionnaire/style.rb +53 -0
- data/app/components/poetry/ui/radio_group/component.html.erb +4 -0
- data/app/components/poetry/ui/radio_group/component.rb +323 -0
- data/app/components/poetry/ui/radio_group/preview.rb +109 -0
- data/app/components/poetry/ui/radio_group/style.rb +53 -0
- data/app/components/poetry/ui/resizable/component.html.erb +10 -0
- data/app/components/poetry/ui/resizable/component.rb +178 -0
- data/app/components/poetry/ui/resizable/preview.rb +42 -0
- data/app/components/poetry/ui/resizable/style.rb +30 -0
- data/app/components/poetry/ui/scroll_area/component.rb +76 -0
- data/app/components/poetry/ui/scroll_area/preview.rb +35 -0
- data/app/components/poetry/ui/scroll_area/style.rb +19 -0
- data/app/components/poetry/ui/search_field/component.html.erb +15 -0
- data/app/components/poetry/ui/search_field/component.rb +137 -0
- data/app/components/poetry/ui/search_field/preview.rb +23 -0
- data/app/components/poetry/ui/search_field/style.rb +18 -0
- data/app/components/poetry/ui/select/component.html.erb +15 -0
- data/app/components/poetry/ui/select/component.rb +639 -0
- data/app/components/poetry/ui/select/preview.rb +113 -0
- data/app/components/poetry/ui/select/style.rb +58 -0
- data/app/components/poetry/ui/sensitive_input/component.html.erb +29 -0
- data/app/components/poetry/ui/sensitive_input/component.rb +274 -0
- data/app/components/poetry/ui/sensitive_input/preview.rb +40 -0
- data/app/components/poetry/ui/sensitive_input/style.rb +49 -0
- data/app/components/poetry/ui/separator/component.rb +57 -0
- data/app/components/poetry/ui/separator/preview.rb +19 -0
- data/app/components/poetry/ui/separator/style.rb +15 -0
- data/app/components/poetry/ui/sheet/component.html.erb +21 -0
- data/app/components/poetry/ui/sheet/component.rb +97 -0
- data/app/components/poetry/ui/sheet/preview.rb +57 -0
- data/app/components/poetry/ui/sheet/style.rb +47 -0
- data/app/components/poetry/ui/sidebar/component.html.erb +20 -0
- data/app/components/poetry/ui/sidebar/component.rb +249 -0
- data/app/components/poetry/ui/sidebar/preview.rb +21 -0
- data/app/components/poetry/ui/sidebar/shell_preview.html.erb +47 -0
- data/app/components/poetry/ui/sidebar/style.rb +139 -0
- data/app/components/poetry/ui/skeleton/component.rb +39 -0
- data/app/components/poetry/ui/skeleton/preview.rb +22 -0
- data/app/components/poetry/ui/skeleton/style.rb +13 -0
- data/app/components/poetry/ui/slider/component.html.erb +13 -0
- data/app/components/poetry/ui/slider/component.rb +360 -0
- data/app/components/poetry/ui/slider/preview.rb +73 -0
- data/app/components/poetry/ui/slider/style.rb +55 -0
- data/app/components/poetry/ui/spinner/component.rb +58 -0
- data/app/components/poetry/ui/spinner/preview.rb +22 -0
- data/app/components/poetry/ui/spinner/style.rb +12 -0
- data/app/components/poetry/ui/stat/component.html.erb +13 -0
- data/app/components/poetry/ui/stat/component.rb +102 -0
- data/app/components/poetry/ui/stat/preview.rb +47 -0
- data/app/components/poetry/ui/stat/style.rb +29 -0
- data/app/components/poetry/ui/switch/component.html.erb +15 -0
- data/app/components/poetry/ui/switch/component.rb +136 -0
- data/app/components/poetry/ui/switch/preview.rb +66 -0
- data/app/components/poetry/ui/switch/style.rb +22 -0
- data/app/components/poetry/ui/table/component.html.erb +3 -0
- data/app/components/poetry/ui/table/component.rb +93 -0
- data/app/components/poetry/ui/table/preview.rb +96 -0
- data/app/components/poetry/ui/table/style.rb +26 -0
- data/app/components/poetry/ui/tabs/component.html.erb +10 -0
- data/app/components/poetry/ui/tabs/component.rb +253 -0
- data/app/components/poetry/ui/tabs/preview.rb +43 -0
- data/app/components/poetry/ui/tabs/style.rb +49 -0
- data/app/components/poetry/ui/tag_group/component.html.erb +8 -0
- data/app/components/poetry/ui/tag_group/component.rb +203 -0
- data/app/components/poetry/ui/tag_group/preview.rb +43 -0
- data/app/components/poetry/ui/tag_group/style.rb +29 -0
- data/app/components/poetry/ui/textarea/component.rb +64 -0
- data/app/components/poetry/ui/textarea/preview.rb +75 -0
- data/app/components/poetry/ui/textarea/style.rb +18 -0
- data/app/components/poetry/ui/time_field/component.html.erb +6 -0
- data/app/components/poetry/ui/time_field/component.rb +85 -0
- data/app/components/poetry/ui/time_field/preview.rb +40 -0
- data/app/components/poetry/ui/time_field/style.rb +30 -0
- data/app/components/poetry/ui/timeline/component.rb +134 -0
- data/app/components/poetry/ui/timeline/preview.rb +61 -0
- data/app/components/poetry/ui/timeline/style.rb +54 -0
- data/app/components/poetry/ui/toast/component.html.erb +24 -0
- data/app/components/poetry/ui/toast/component.rb +178 -0
- data/app/components/poetry/ui/toast/preview.rb +69 -0
- data/app/components/poetry/ui/toast/style.rb +33 -0
- data/app/components/poetry/ui/toast_trigger/addressed_preview.html.erb +12 -0
- data/app/components/poetry/ui/toast_trigger/component.html.erb +3 -0
- data/app/components/poetry/ui/toast_trigger/component.rb +82 -0
- data/app/components/poetry/ui/toast_trigger/default_preview.html.erb +11 -0
- data/app/components/poetry/ui/toast_trigger/preview.rb +19 -0
- data/app/components/poetry/ui/toaster/component.html.erb +1 -0
- data/app/components/poetry/ui/toaster/component.rb +99 -0
- data/app/components/poetry/ui/toaster/positions_preview.html.erb +24 -0
- data/app/components/poetry/ui/toaster/preview.rb +46 -0
- data/app/components/poetry/ui/toaster/stamp_preview.html.erb +15 -0
- data/app/components/poetry/ui/toaster/style.rb +26 -0
- data/app/components/poetry/ui/toggle/component.rb +120 -0
- data/app/components/poetry/ui/toggle/preview.rb +79 -0
- data/app/components/poetry/ui/toggle/style.rb +33 -0
- data/app/components/poetry/ui/toggle_group/component.html.erb +4 -0
- data/app/components/poetry/ui/toggle_group/component.rb +252 -0
- data/app/components/poetry/ui/toggle_group/preview.rb +143 -0
- data/app/components/poetry/ui/toggle_group/style.rb +33 -0
- data/app/components/poetry/ui/toolbar/component.rb +125 -0
- data/app/components/poetry/ui/toolbar/preview.rb +41 -0
- data/app/components/poetry/ui/toolbar/style.rb +20 -0
- data/app/components/poetry/ui/tooltip/component.html.erb +20 -0
- data/app/components/poetry/ui/tooltip/component.rb +185 -0
- data/app/components/poetry/ui/tooltip/preview.rb +74 -0
- data/app/components/poetry/ui/tooltip/previews/provider_row.html.erb +25 -0
- data/app/components/poetry/ui/tooltip/style.rb +24 -0
- data/app/components/poetry/ui/tree/component.html.erb +32 -0
- data/app/components/poetry/ui/tree/component.rb +233 -0
- data/app/components/poetry/ui/tree/preview.rb +55 -0
- data/app/components/poetry/ui/tree/style.rb +29 -0
- data/app/components/poetry/ui/typeset/component.rb +73 -0
- data/app/components/poetry/ui/typeset/preview.rb +45 -0
- data/app/components/poetry/ui/typeset/style.rb +15 -0
- data/app/controllers/poetry/ui/llms_controller.rb +28 -0
- data/app/helpers/poetry/ui/components_helper.rb +1794 -0
- data/app/helpers/poetry/ui/form_builder/type_inference.rb +117 -0
- data/app/helpers/poetry/ui/form_builder.rb +916 -0
- data/app/helpers/poetry/ui/optimistic_form_builder.rb +55 -0
- data/app/helpers/poetry/ui/toast_stream_actions.rb +27 -0
- data/config/component_descriptions.yml +96 -0
- data/config/component_registry.yml +12257 -0
- data/config/locales/en.yml +93 -0
- data/config/routes.rb +8 -0
- data/config/template_classes.txt +113 -0
- data/lib/generators/poetry/add/add_generator.rb +218 -0
- data/lib/generators/poetry/agent_rules/agent_rules_generator.rb +91 -0
- data/lib/generators/poetry/agents/agents_generator.rb +24 -0
- data/lib/generators/poetry/agents_section.rb +148 -0
- data/lib/generators/poetry/block/block_generator.rb +67 -0
- data/lib/generators/poetry/block/templates/action_bar.html.erb +45 -0
- data/lib/generators/poetry/block/templates/app_shell.html.erb +139 -0
- data/lib/generators/poetry/block/templates/data_index.html.erb +85 -0
- data/lib/generators/poetry/block/templates/destructive_panel.html.erb +26 -0
- data/lib/generators/poetry/block/templates/page_header.html.erb +25 -0
- data/lib/generators/poetry/block/templates/section_card.html.erb +42 -0
- data/lib/generators/poetry/block/templates/stepper.html.erb +79 -0
- data/lib/generators/poetry/block/templates/top_nav.html.erb +44 -0
- data/lib/generators/poetry/diff/diff_generator.rb +135 -0
- data/lib/generators/poetry/editor/editor_generator.rb +344 -0
- data/lib/generators/poetry/editor/templates/poetry-check-hook +81 -0
- data/lib/generators/poetry/install/install_generator.rb +364 -0
- data/lib/generators/poetry/pagination/pagination_generator.rb +76 -0
- data/lib/generators/poetry/pagination/templates/kaminari_paginator.html.erb +29 -0
- data/lib/generators/poetry/pagination/templates/poetry_link_renderer.rb +34 -0
- data/lib/generators/poetry/pagination/templates/poetry_pagy_helper.rb +28 -0
- data/lib/generators/poetry/recipes/agent_embed/app/javascript/controllers/agent_demo_controller.js +131 -0
- data/lib/generators/poetry/recipes/screen_data_index/app/controllers/orders_controller.rb +15 -0
- data/lib/generators/poetry/recipes/screen_data_index/app/views/orders/index.html.erb +7 -0
- data/lib/generators/poetry/recipes/screen_data_index/test/system/orders_index_test.rb +16 -0
- data/lib/generators/poetry/recipes/screen_settings/app/controllers/settings_controller.rb +14 -0
- data/lib/generators/poetry/recipes/screen_settings/app/views/settings/show.html.erb +9 -0
- data/lib/generators/poetry/recipes/screen_settings/test/system/settings_show_test.rb +16 -0
- data/lib/generators/poetry/scaffold_templates/scaffold_templates_generator.rb +60 -0
- data/lib/generators/poetry/scaffold_templates/templates/_form.html.erb.tt +77 -0
- data/lib/generators/poetry/scaffold_templates/templates/controller.rb.tt +78 -0
- data/lib/generators/poetry/scaffold_templates/templates/edit.html.erb.tt +14 -0
- data/lib/generators/poetry/scaffold_templates/templates/index.html.erb.tt +24 -0
- data/lib/generators/poetry/scaffold_templates/templates/new.html.erb.tt +11 -0
- data/lib/generators/poetry/scaffold_templates/templates/partial.html.erb.tt +13 -0
- data/lib/generators/poetry/scaffold_templates/templates/show.html.erb.tt +18 -0
- data/lib/generators/poetry/skill/skill_generator.rb +34 -0
- data/lib/generators/poetry/skill/templates/poetry-component/SKILL.md +58 -0
- data/lib/generators/poetry/skill/templates/poetry-component/references/anatomy.md +152 -0
- data/lib/generators/poetry/skill/templates/poetry-component/references/checklist.md +67 -0
- data/lib/generators/poetry/skill/templates/poetry-component/references/documentation.md +137 -0
- data/lib/generators/poetry/skill/templates/poetry-design/SKILL.md +56 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/audit.md +123 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/compose.md +73 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/figma.md +68 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/paper.md +56 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/study.md +47 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/theme.md +70 -0
- data/lib/generators/poetry/skills_section.rb +58 -0
- data/lib/poetry/ui/chat.rb +283 -0
- data/lib/poetry/ui/code_block_highlighter.rb +60 -0
- data/lib/poetry/ui/engine.rb +55 -0
- data/lib/poetry/ui/recipes.rb +157 -0
- data/lib/poetry/ui/testing/combobox.rb +167 -0
- data/lib/poetry/ui/testing/dialog.rb +73 -0
- data/lib/poetry/ui/testing/menu.rb +127 -0
- data/lib/poetry/ui/testing/registration.rb +58 -0
- data/lib/poetry/ui/testing/select.rb +147 -0
- data/lib/poetry/ui/testing/tester.rb +130 -0
- data/lib/poetry/ui/testing.rb +130 -0
- data/lib/poetry/ui/themes.rb +109 -0
- data/lib/poetry/ui/version.rb +8 -0
- data/lib/poetry/ui/webmcp.rb +91 -0
- data/lib/poetry/ui.rb +285 -0
- data/lib/poetry-ui.rb +5 -0
- data/lib/tasks/poetry/check.rake +73 -0
- data/lib/tasks/poetry/design.rake +293 -0
- data/lib/tasks/poetry/verify.rake +36 -0
- data/themes/default.css +1793 -0
- data/themes/luma.css +1764 -0
- data/themes/lyra.css +1768 -0
- data/themes/maia.css +1768 -0
- data/themes/mira.css +1760 -0
- data/themes/nova.css +1755 -0
- data/themes/rhea.css +1771 -0
- data/themes/sera.css +1757 -0
- data/themes/vega.css +1775 -0
- data/typeset/typeset.css +499 -0
- metadata +502 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Removable-chip collections.
|
|
6
|
+
module TagGroup
|
|
7
|
+
# A collection of removable chips - recipients, filters, labels.
|
|
8
|
+
# The group is one Tab stop with grid semantics: arrow keys move
|
|
9
|
+
# between tags, Delete/Backspace removes the focused tag, each
|
|
10
|
+
# chip's remove button removes exactly its own, and focus recovers
|
|
11
|
+
# to a neighbor after a removal. With name: the group is a form
|
|
12
|
+
# value - one hidden name[] input submits per tag. Removal is
|
|
13
|
+
# cancelable via the poetry:tag-group:remove event, so a server
|
|
14
|
+
# (Turbo) re-render can own it instead.
|
|
15
|
+
#
|
|
16
|
+
# label: is required - it names the grid for assistive tech. Tags
|
|
17
|
+
# here are removal-only: toggling fixed choices is ToggleGroup,
|
|
18
|
+
# picking from options is Combobox multiple.
|
|
19
|
+
#
|
|
20
|
+
# @example Removable recipients that submit as recipients[]
|
|
21
|
+
# render Poetry::Ui::TagGroup::Component.new(label: "Recipients", name: "recipients") do |group|
|
|
22
|
+
# group.with_tag(value: "ada", label: "Ada")
|
|
23
|
+
# group.with_tag(value: "grace", label: "Grace")
|
|
24
|
+
# end
|
|
25
|
+
class Component < Poetry::Core::Component
|
|
26
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
27
|
+
AGENT_RULES = [
|
|
28
|
+
"Removable chips are a TagGroup - never hand-rolled badges with x buttons; removal " \
|
|
29
|
+
"keyboard (Delete/Backspace), focus recovery, and the live region ride the controller.",
|
|
30
|
+
"label: is REQUIRED (the grid's accessible name, rendered as a caption span).",
|
|
31
|
+
"name: turns the group into a form value - one hidden <name>[] input per tag " \
|
|
32
|
+
"submits; removing a tag removes its input.",
|
|
33
|
+
"Removal is cancelable: listen for poetry:tag-group:remove and preventDefault to " \
|
|
34
|
+
"own the removal server-side (Turbo re-render).",
|
|
35
|
+
"Choosing from options is Combobox multiple; toggling fixed choices is ToggleGroup - " \
|
|
36
|
+
"a TagGroup holds items that exist until removed."
|
|
37
|
+
].freeze
|
|
38
|
+
|
|
39
|
+
renders_many :tags,
|
|
40
|
+
doc: "Declares one chip. value: is its identity (and form value); label: is the accessible " \
|
|
41
|
+
"name and the visible text when no block is given; removable: false drops the remove " \
|
|
42
|
+
"button.",
|
|
43
|
+
renders: lambda { |value:, label: nil, disabled: false, removable: true, **options, &block|
|
|
44
|
+
tag_row(value: value, label: label, disabled: disabled, removable: removable, **options, &block)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Both controllers declare on the grid element: roving-focus owns
|
|
48
|
+
# the arrow keys, with the group's own keydown (removal keys)
|
|
49
|
+
# layered on the same event.
|
|
50
|
+
use_stimulus do
|
|
51
|
+
on :grid do
|
|
52
|
+
controller :tag_group do
|
|
53
|
+
register
|
|
54
|
+
action :keydown, on: :keydown
|
|
55
|
+
end
|
|
56
|
+
controller :roving_focus do
|
|
57
|
+
register
|
|
58
|
+
value :orientation, :horizontal
|
|
59
|
+
value :loop, true
|
|
60
|
+
action :keydown, on: :keydown
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
on :remove do
|
|
64
|
+
controller(:tag_group) { action :remove, on: :click }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
option :name, :string, doc: "Makes the group a form value: one hidden <name>[] input submits per tag."
|
|
69
|
+
option :label, :string, required: true, doc: "The grid's accessible name, rendered as a caption span. Required."
|
|
70
|
+
option :described_by, :string,
|
|
71
|
+
doc: "Space-separated hint/error ids for the GRID (the labelled element) - a raw aria-describedby in " \
|
|
72
|
+
"html_attributes would land on the outer wrapper div, unassociated for AT."
|
|
73
|
+
|
|
74
|
+
part "tag-group", "The labelled wrapper - caption span + grid stack here"
|
|
75
|
+
part "tag-group-label", "The caption span (label:), wired via aria-labelledby (a grid " \
|
|
76
|
+
"is not a labelable form control - never a <label>)"
|
|
77
|
+
part "tag-group-grid", "The tag collection (role=grid; role=group + the tab stop when " \
|
|
78
|
+
"empty) - roving focus, removal keys, and the focus-scoped " \
|
|
79
|
+
"live region ride here",
|
|
80
|
+
states: {
|
|
81
|
+
"data-empty" => "no tags remain (controller-kept after removals)"
|
|
82
|
+
}
|
|
83
|
+
part "tag-group-tag", "One chip (role=row > gridcell): content, the remove button, " \
|
|
84
|
+
"and - in form mode - the hidden name[] input",
|
|
85
|
+
states: {
|
|
86
|
+
"data-disabled" => "the tag is disabled (skipped by arrows and removal)",
|
|
87
|
+
"data-value" => { condition: "always - the tag's value (the remove event's " \
|
|
88
|
+
"detail and the hidden input's value)" }
|
|
89
|
+
}
|
|
90
|
+
part "tag-group-remove", "The per-tag remove button - tabbable (Tab steps from the " \
|
|
91
|
+
"row into it), removes exactly its own tag"
|
|
92
|
+
|
|
93
|
+
# @api private
|
|
94
|
+
def before_render
|
|
95
|
+
raise ArgumentError, "TagGroup requires label: (the grid's accessible name)" if label.blank?
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# One instance id (ladder: caller id -> key -> random); every
|
|
99
|
+
# inner id derives from it - so a keyed group's label AND rows are
|
|
100
|
+
# all morph-stable, and rows never touch a group-level allocator.
|
|
101
|
+
# @api private
|
|
102
|
+
def instance_id
|
|
103
|
+
@instance_id ||= poetry_instance_id("poetry-tag-group")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @api private
|
|
107
|
+
def label_id
|
|
108
|
+
"#{instance_id}-label"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @api private
|
|
112
|
+
def root_attributes
|
|
113
|
+
html_attributes.merge_if_not_set(
|
|
114
|
+
{ "data-slot" => "tag-group", "class" => css }.merge(component_data_attributes)
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# @api private
|
|
119
|
+
def grid_attributes
|
|
120
|
+
attrs = {
|
|
121
|
+
"role" => tags.any? ? "grid" : "group",
|
|
122
|
+
"data-slot" => "tag-group-grid",
|
|
123
|
+
"class" => css(:grid),
|
|
124
|
+
"aria-labelledby" => label_id,
|
|
125
|
+
**(described_by.present? ? { "aria-describedby" => described_by } : {}),
|
|
126
|
+
# Polite only while focus is within (controller-flipped): SRs
|
|
127
|
+
# hear tags added mid-work without spam from elsewhere.
|
|
128
|
+
"aria-live" => "off",
|
|
129
|
+
"aria-atomic" => "false",
|
|
130
|
+
"aria-relevant" => "additions"
|
|
131
|
+
}
|
|
132
|
+
attrs["data-empty"] = "" if tags.none?
|
|
133
|
+
attrs["tabindex"] = "0" if tags.none?
|
|
134
|
+
attrs.merge(stimulus_attributes_for(:grid))
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Built here (not in the template) so the slot lambda can compose
|
|
138
|
+
# the full row - content, remove button, hidden input - around the
|
|
139
|
+
# consumer's block.
|
|
140
|
+
# @api private
|
|
141
|
+
def tag_row(value:, label:, disabled:, removable:, **options, &block)
|
|
142
|
+
# Rows are the reorderable collection: identity derives from
|
|
143
|
+
# value: (the collection contract - unique within the group),
|
|
144
|
+
# namespaced under the group's instance id so two groups with
|
|
145
|
+
# the same tag values never collide.
|
|
146
|
+
row_id = options[:id].presence ||
|
|
147
|
+
"#{instance_id}-tag-#{Poetry::Core::StableId.key_token(value) || SecureRandom.hex(8)}"
|
|
148
|
+
attrs = {
|
|
149
|
+
"id" => row_id, "role" => "row", "data-slot" => "tag-group-tag",
|
|
150
|
+
"data-value" => value, "data-poetry-collection-item" => "",
|
|
151
|
+
"aria-label" => label || value.to_s,
|
|
152
|
+
"tabindex" => "-1", "class" => css(:tag)
|
|
153
|
+
}
|
|
154
|
+
attrs["data-disabled"] = "" if disabled
|
|
155
|
+
|
|
156
|
+
# Caller options ride along (they were silently discarded before);
|
|
157
|
+
# data-value is RESERVED - the row's collection identity comes
|
|
158
|
+
# from value:, any caller spelling loses.
|
|
159
|
+
options.delete(:"data-value")
|
|
160
|
+
options.delete("data-value")
|
|
161
|
+
merged = Poetry::Core::HTML::Attributes.merged(attrs, options.except(:id))
|
|
162
|
+
merged["data-value"] = value
|
|
163
|
+
|
|
164
|
+
content_tag(:div, merged) do
|
|
165
|
+
content_tag(:span, { "role" => "gridcell", "class" => css(:cell) }) do
|
|
166
|
+
safe_join([
|
|
167
|
+
# label: doubles as the visible content when no block is
|
|
168
|
+
# given (the builder's model-array path renders text-only).
|
|
169
|
+
block ? capture(&block) : label.to_s,
|
|
170
|
+
(remove_button(row_id, disabled: disabled) if removable),
|
|
171
|
+
(hidden_input(value) if name.present?)
|
|
172
|
+
].compact)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
private
|
|
178
|
+
|
|
179
|
+
def remove_button(row_id, disabled:)
|
|
180
|
+
button_id = "#{row_id}-remove"
|
|
181
|
+
attrs = {
|
|
182
|
+
"type" => "button", "id" => button_id,
|
|
183
|
+
"data-slot" => "tag-group-remove", "class" => css(:remove),
|
|
184
|
+
# labelledby chains button -> row: "Remove, <tag name>".
|
|
185
|
+
"aria-label" => t("poetry.tag_group.remove"),
|
|
186
|
+
"aria-labelledby" => "#{button_id} #{row_id}"
|
|
187
|
+
}
|
|
188
|
+
attrs["disabled"] = "" if disabled
|
|
189
|
+
|
|
190
|
+
content_tag(:button, attrs.merge(stimulus_attributes_for(:remove))) do
|
|
191
|
+
render(Icon::Component.new(name: :x))
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def hidden_input(value)
|
|
196
|
+
tag.input(type: "hidden", name: "#{name}[]", value: value)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
private :instance_id, :label_id, :root_attributes, :grid_attributes, :tag_row
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module TagGroup
|
|
6
|
+
class Preview < Poetry::Core::Preview::Base
|
|
7
|
+
def default
|
|
8
|
+
render_component(label: "Topics") do |group|
|
|
9
|
+
group.with_tag(value: "rails") { "Rails" }
|
|
10
|
+
group.with_tag(value: "hotwire") { "Hotwire" }
|
|
11
|
+
group.with_tag(value: "ruby") { "Ruby" }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Form mode: one hidden topics[] input per tag submits; removing a
|
|
16
|
+
# tag removes its input.
|
|
17
|
+
def as_form_value
|
|
18
|
+
render_component(name: "post[topics]", label: "Topics") do |group|
|
|
19
|
+
group.with_tag(value: "news") { "News" }
|
|
20
|
+
group.with_tag(value: "release") { "Release" }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def with_disabled
|
|
25
|
+
render_component(label: "Filters") do |group|
|
|
26
|
+
group.with_tag(value: "status") { "Status: open" }
|
|
27
|
+
group.with_tag(value: "locked", disabled: true) { "Locked" }
|
|
28
|
+
group.with_tag(value: "assignee") { "Assignee: me" }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# removable: false - display-only chips keep grid navigation but
|
|
33
|
+
# no removal affordance.
|
|
34
|
+
def without_removal
|
|
35
|
+
render_component(label: "Capabilities") do |group|
|
|
36
|
+
group.with_tag(value: "read", removable: false) { "Read" }
|
|
37
|
+
group.with_tag(value: "write", removable: false) { "Write" }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module TagGroup
|
|
6
|
+
# Utility-only (the Separator/Spinner rule): chips wear the secondary
|
|
7
|
+
# badge treatment in structural utilities on semantic tokens - no
|
|
8
|
+
# upstream cn hook exists for a tag group; data-slot selectors are
|
|
9
|
+
# the restyle seam. The grid carries a focus ring for its empty-state
|
|
10
|
+
# tab-stop role.
|
|
11
|
+
class Style < Poetry::Core::Style
|
|
12
|
+
base "flex w-fit flex-col gap-1.5"
|
|
13
|
+
|
|
14
|
+
element :label, "text-sm font-medium"
|
|
15
|
+
element :grid, "flex flex-wrap items-center gap-1.5 rounded-md outline-none " \
|
|
16
|
+
"focus-visible:ring-[3px] focus-visible:ring-ring/50"
|
|
17
|
+
element :tag, "inline-flex items-center gap-1 rounded-md border border-transparent " \
|
|
18
|
+
"bg-secondary px-2 py-0.5 text-xs font-medium text-secondary-foreground " \
|
|
19
|
+
"outline-none focus-visible:border-ring focus-visible:ring-[3px] " \
|
|
20
|
+
"focus-visible:ring-ring/50 " \
|
|
21
|
+
"data-disabled:pointer-events-none data-disabled:opacity-50"
|
|
22
|
+
element :cell, "contents"
|
|
23
|
+
element :remove, "-mr-0.5 inline-flex size-3.5 items-center justify-center rounded-sm " \
|
|
24
|
+
"opacity-60 outline-none hover:opacity-100 " \
|
|
25
|
+
"focus-visible:ring-2 focus-visible:ring-ring/50 [&_svg]:size-3"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Multiline free-text inputs.
|
|
6
|
+
module Textarea
|
|
7
|
+
# A multiline free-text input: the native <textarea> with the
|
|
8
|
+
# library's styling and zero JS. It auto-grows with its content via
|
|
9
|
+
# CSS (the field-sizing-content property); browsers without support
|
|
10
|
+
# keep the rows:/minimum-height sizing plus the native resize
|
|
11
|
+
# handle. Label pairing, description wiring, and error state flow
|
|
12
|
+
# in from the Field/FormBuilder layer - use Input for single-line
|
|
13
|
+
# text.
|
|
14
|
+
#
|
|
15
|
+
# @example A free-text field
|
|
16
|
+
# render Poetry::Ui::Textarea::Component.new(name: "bio", rows: 4,
|
|
17
|
+
# placeholder: "Tell us about yourself")
|
|
18
|
+
class Component < Poetry::Core::Component
|
|
19
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
20
|
+
AGENT_RULES = [
|
|
21
|
+
"Wire through Field/FormBuilder (control_attributes) - never hand-write the aria plumbing.",
|
|
22
|
+
"Placeholder is NOT a label - pair with Label/Field always.",
|
|
23
|
+
"Use Textarea for free text; Input for single-line; do not bolt a JS autosizer on " \
|
|
24
|
+
"(auto-grow is CSS).",
|
|
25
|
+
"Do not set native required - required flows as aria-required via Field."
|
|
26
|
+
].freeze
|
|
27
|
+
|
|
28
|
+
option :name, :string, doc: "The submitted field name."
|
|
29
|
+
option :value, :string, doc: "The initial text, rendered as the element's content."
|
|
30
|
+
option :placeholder, :string, doc: "Hint text shown while empty - never a substitute for a label."
|
|
31
|
+
option :rows, :integer,
|
|
32
|
+
doc: "The initial visual rows - the minimum height under CSS auto-grow, and the fixed size in " \
|
|
33
|
+
"browsers without it."
|
|
34
|
+
option :disabled, :boolean, default: false, doc: "Disables the control and forwards to the native element."
|
|
35
|
+
option :invalid, :boolean, default: false,
|
|
36
|
+
doc: "Marks the field errored (aria-invalid + the destructive ring); set by " \
|
|
37
|
+
"Field/FormBuilder from model errors."
|
|
38
|
+
|
|
39
|
+
part "textarea", "The <textarea> element itself - value renders as content; " \
|
|
40
|
+
"auto-grow is the field-sizing-content CSS property, zero JS"
|
|
41
|
+
|
|
42
|
+
# @api private
|
|
43
|
+
def call
|
|
44
|
+
# value as CONTENT (escaped by content_tag - the </textarea>
|
|
45
|
+
# injection surface).
|
|
46
|
+
content_tag(:textarea, value, **root_attributes.to_attributes)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @api private
|
|
50
|
+
def root_attributes
|
|
51
|
+
attrs = { "data-slot" => "textarea" }.merge(component_data_attributes)
|
|
52
|
+
attrs["name"] = name if name.present?
|
|
53
|
+
attrs["placeholder"] = placeholder if placeholder.present?
|
|
54
|
+
attrs["rows"] = rows if rows.present?
|
|
55
|
+
attrs["disabled"] = true if disabled
|
|
56
|
+
attrs["aria-invalid"] = true if invalid
|
|
57
|
+
html_attributes.merge_if_not_set(attrs)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private :root_attributes
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Textarea
|
|
6
|
+
# The Textarea preview matrix: the five ported examples (demo,
|
|
7
|
+
# disabled, with-label, with-text, with-button) plus the invalid
|
|
8
|
+
# state and long auto-grown content.
|
|
9
|
+
class Preview < Poetry::Core::Preview::Base
|
|
10
|
+
# @!group States
|
|
11
|
+
|
|
12
|
+
def default
|
|
13
|
+
render_component(placeholder: "Type your message here.")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def disabled
|
|
17
|
+
render_component(placeholder: "Type your message here.", disabled: true)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def invalid
|
|
21
|
+
render_component(placeholder: "Type your message here.", invalid: true,
|
|
22
|
+
value: "too short")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# field-sizing-content auto-grows with the content (Chromium);
|
|
26
|
+
# elsewhere: min-h-16 + the native resize handle.
|
|
27
|
+
def auto_grown
|
|
28
|
+
render_component("aria-label": "Notes", value: "Paragraph one.\n\nParagraph two keeps pushing the height - " \
|
|
29
|
+
"no JS autosizer, the CSS does it.\n\nParagraph three.")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def taller_start
|
|
33
|
+
render_component(rows: 8, placeholder: "Starts eight rows tall.")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @!endgroup
|
|
37
|
+
|
|
38
|
+
# @!group Recipes
|
|
39
|
+
|
|
40
|
+
# textarea-with-label parity (Label pairs by for=).
|
|
41
|
+
def with_label
|
|
42
|
+
render_component(Field::Component.new(id: "preview-message", label_text: "Your message")) do
|
|
43
|
+
embed(Component.new(name: "message", placeholder: "Type your message here.",
|
|
44
|
+
id: "preview-message"))
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# textarea-with-text parity: the hint wires via describedby.
|
|
49
|
+
def with_hint
|
|
50
|
+
field = Field::Component.new(
|
|
51
|
+
id: "preview-bio", label_text: "Bio",
|
|
52
|
+
hint: "Your message will be copied to the support team."
|
|
53
|
+
)
|
|
54
|
+
render_component(field) do
|
|
55
|
+
embed(Component.new(name: "bio", placeholder: "Tell us about yourself",
|
|
56
|
+
**field.control_attributes.transform_keys(&:to_sym)))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Model-error rendering: aria-invalid + error-before-hint.
|
|
61
|
+
def with_error
|
|
62
|
+
field = Field::Component.new(
|
|
63
|
+
id: "preview-report", label_text: "Report",
|
|
64
|
+
hint: "Markdown is supported.", error: "can't be blank", required: true
|
|
65
|
+
)
|
|
66
|
+
render_component(field) do
|
|
67
|
+
embed(Component.new(name: "report", **field.control_attributes.transform_keys(&:to_sym)))
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @!endgroup
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Textarea
|
|
6
|
+
# Re-expressed through the cn-* theme layer. The one behavioral
|
|
7
|
+
# novelty stays inline: field-sizing-content is CSS-only auto-grow
|
|
8
|
+
# (Chromium-first; other engines fall back to min-h-16 + the native
|
|
9
|
+
# resize handle - graceful, no polyfill, no JS autosizer ever).
|
|
10
|
+
# Placeholder color rides the theme (the rhea AA hold - see
|
|
11
|
+
# the Input dictionary note).
|
|
12
|
+
class Style < Poetry::Core::Style
|
|
13
|
+
base "cn-textarea flex field-sizing-content min-h-16 w-full outline-none " \
|
|
14
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<%# DateField's template verbatim: native input visible (and THE form
|
|
2
|
+
value) until the controller builds segments into the group. %>
|
|
3
|
+
<%= content_tag(:div, **root_attributes.to_attributes) do %>
|
|
4
|
+
<%= content_tag(:span, "", **Poetry::Core::HTML::Attributes.new(group_attributes).to_attributes) %>
|
|
5
|
+
<%= tag.input(**input_attributes.to_attributes) %>
|
|
6
|
+
<% end %>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Segmented time-of-day editors.
|
|
6
|
+
module TimeField
|
|
7
|
+
# A segmented time editor: hour, minute, and - with seconds: -
|
|
8
|
+
# second segments, each typed or stepped independently. The form
|
|
9
|
+
# value is a native <input type=time> submitting HH:MM[:SS], and
|
|
10
|
+
# without JS that native input simply renders, so the field always
|
|
11
|
+
# works. The user's locale decides 12- vs 24-hour editing (an
|
|
12
|
+
# AM/PM segment appears exactly when the locale is twelve-hour);
|
|
13
|
+
# hour_cycle: pins it explicitly.
|
|
14
|
+
#
|
|
15
|
+
# A TimeField is a DateField specialized to time-of-day - segments
|
|
16
|
+
# share the date-field-* part vocabulary.
|
|
17
|
+
#
|
|
18
|
+
# @example
|
|
19
|
+
# render Poetry::Ui::TimeField::Component.new(
|
|
20
|
+
# name: "starts_at", label: "Start time", value: "09:30"
|
|
21
|
+
# )
|
|
22
|
+
class Component < DateField::Component
|
|
23
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
24
|
+
AGENT_RULES = [
|
|
25
|
+
"Time entry is a TimeField (poetry_time_field / form.time_field) - never a masked " \
|
|
26
|
+
"Input or a pair of selects; params[<name>] is HH:MM (HH:MM:SS with seconds:).",
|
|
27
|
+
"12- vs 24-hour follows the user's locale automatically (the dayPeriod segment " \
|
|
28
|
+
"appears only under twelve-hour cycles); hour_cycle: pins it when a product must.",
|
|
29
|
+
"For a date AND a time, compose a DateField and a TimeField side by side - there " \
|
|
30
|
+
"is no datetime component by design."
|
|
31
|
+
].freeze
|
|
32
|
+
|
|
33
|
+
# EXTENDS DateField's root declaration (extend: true merges into
|
|
34
|
+
# the inherited element) - same date-field controller, two more
|
|
35
|
+
# values; group/input inherit untouched.
|
|
36
|
+
use_stimulus do
|
|
37
|
+
on :root, extend: true do
|
|
38
|
+
controller :date_field do
|
|
39
|
+
value :seconds, true, if: :seconds
|
|
40
|
+
value :hour_cycle, if: -> { hour_cycle.present? }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
option :seconds, :boolean, default: false, doc: "Adds the seconds segment; the wire format becomes HH:MM:SS."
|
|
46
|
+
option :hour_cycle, :string, doc: "Pins the hour cycle (h12/h23/h11/h24) instead of the locale's."
|
|
47
|
+
|
|
48
|
+
part "time-field", "Root - the controller and the enhanced/disabled surface ride " \
|
|
49
|
+
"here (segments inside share the date-field-* vocabulary)",
|
|
50
|
+
states: {
|
|
51
|
+
"data-enhanced" => "the controller connected and built segments (no JS = the " \
|
|
52
|
+
"native input, visible and styled)",
|
|
53
|
+
"data-disabled" => "disabled: is set",
|
|
54
|
+
"data-invalid" => "invalid: is set (the group wears the destructive ring)"
|
|
55
|
+
}
|
|
56
|
+
part "time-field-group", "The bordered segment row - hidden until enhancement, then " \
|
|
57
|
+
"the editing surface (cn-input chrome, focus-within ring)",
|
|
58
|
+
states: {
|
|
59
|
+
"data-disabled" => "disabled: is set (chrome dims, pointer events off)",
|
|
60
|
+
"data-invalid" => "invalid: is set (destructive border + ring)"
|
|
61
|
+
}
|
|
62
|
+
part "time-field-input", "The native <input type=time> - THE form value in both " \
|
|
63
|
+
"modes; tabindex -1 + aria-hidden once segments exist"
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def input_type
|
|
68
|
+
"time"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def slot_prefix
|
|
72
|
+
"time-field"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def iso(candidate)
|
|
76
|
+
candidate.respond_to?(:strftime) ? candidate.strftime("%H:%M#{":%S" if seconds}") : candidate.to_s
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def placeholder_iso
|
|
80
|
+
placeholder_value.present? ? iso(placeholder_value) : "12:00#{":00" if seconds}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module TimeField
|
|
6
|
+
# The TimeField preview: empty and valued fields, seconds, a pinned
|
|
7
|
+
# 24-hour cycle, disabled, and a pinned locale.
|
|
8
|
+
class Preview < Poetry::Core::Preview::Base
|
|
9
|
+
# Empty: hour/minute placeholders (plus AM/PM under twelve-hour
|
|
10
|
+
# locales) once enhanced; the styled native input before that.
|
|
11
|
+
def default
|
|
12
|
+
render_component(name: "meeting[at]", label: "Start time")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def with_value
|
|
16
|
+
render_component(name: "meeting[at]", value: "13:05", label: "Start time")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def with_seconds
|
|
20
|
+
render_component(name: "job[cutoff]", value: "09:30:15", seconds: true, label: "Cutoff")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# A pinned 24-hour cycle regardless of the page locale.
|
|
24
|
+
def twenty_four_hour
|
|
25
|
+
render_component(name: "shift[start]", value: "21:15", hour_cycle: "h23", label: "Shift start")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def disabled
|
|
29
|
+
render_component(name: "meeting[at]", value: "13:05", disabled: true, label: "Start time")
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# locale: pins the cycle AND the dayPeriod/label language instead
|
|
33
|
+
# of following the page locale.
|
|
34
|
+
def localized
|
|
35
|
+
render_component(name: "termin[um]", value: "14:30", locale: "de-DE", label: "Uhrzeit")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module TimeField
|
|
6
|
+
# DateField's style verbatim (one segment engine, two components) -
|
|
7
|
+
# including the group/date-field marker name, which the enhanced-
|
|
8
|
+
# input selector keys on. See date_field/style.rb for the rationale.
|
|
9
|
+
class Style < Poetry::Core::Style
|
|
10
|
+
base "group/date-field flex w-full flex-col"
|
|
11
|
+
|
|
12
|
+
element :group,
|
|
13
|
+
"cn-input hidden w-fit min-w-0 select-none items-center tabular-nums " \
|
|
14
|
+
"group-data-[enhanced]/date-field:flex " \
|
|
15
|
+
"focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50 " \
|
|
16
|
+
"data-invalid:border-destructive data-invalid:ring-destructive/20 " \
|
|
17
|
+
"dark:data-invalid:ring-destructive/40 " \
|
|
18
|
+
"data-disabled:pointer-events-none data-disabled:opacity-50 " \
|
|
19
|
+
"[&_[data-slot=date-field-segment]]:rounded-sm " \
|
|
20
|
+
"[&_[data-slot=date-field-segment]]:px-0.5 " \
|
|
21
|
+
"[&_[data-slot=date-field-segment]]:outline-none " \
|
|
22
|
+
"[&_[data-slot=date-field-segment]:focus]:bg-accent " \
|
|
23
|
+
"[&_[data-slot=date-field-segment]:focus]:text-accent-foreground " \
|
|
24
|
+
"[&_[data-slot=date-field-segment][data-placeholder]]:text-muted-foreground " \
|
|
25
|
+
"[&_[data-slot=date-field-literal]]:text-muted-foreground"
|
|
26
|
+
element :input, "group-data-[enhanced]/date-field:sr-only"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|