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,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# The FieldGroup family - the stacking container for Fields.
|
|
6
|
+
module FieldGroup
|
|
7
|
+
# The FieldGroup - the Field family's stacking container: fields,
|
|
8
|
+
# fieldsets, and separators stack with the
|
|
9
|
+
# theme's rhythm instead of hand-spaced flex columns. It is also the
|
|
10
|
+
# CSS `@container` scope responsive fields key on - Field's
|
|
11
|
+
# orientation: :responsive flips to a row only once ITS field-group
|
|
12
|
+
# container passes the md mark.
|
|
13
|
+
#
|
|
14
|
+
# @example Stacking fields with the theme's rhythm
|
|
15
|
+
# render Poetry::Ui::FieldGroup::Component.new do
|
|
16
|
+
# safe_join([
|
|
17
|
+
# render(Poetry::Ui::Field::Component.new) { ... },
|
|
18
|
+
# render(Poetry::Ui::FieldSeparator::Component.new),
|
|
19
|
+
# render(Poetry::Ui::Field::Component.new) { ... }
|
|
20
|
+
# ])
|
|
21
|
+
# end
|
|
22
|
+
class Component < Poetry::Core::Component
|
|
23
|
+
# The closed vocabulary for the variant axis.
|
|
24
|
+
VARIANTS = %i[default choices].freeze
|
|
25
|
+
|
|
26
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
27
|
+
AGENT_RULES = [
|
|
28
|
+
"Stack Fields (and Fieldsets) with poetry_field_group - the theme owns the rhythm; " \
|
|
29
|
+
"never hand-space a form column with gap utilities.",
|
|
30
|
+
"variant: :choices packs a run of horizontal checkbox/switch fields tighter (the " \
|
|
31
|
+
"choice-group form).",
|
|
32
|
+
"Field's orientation: :responsive is container-driven: it needs a FieldGroup " \
|
|
33
|
+
"ancestor to measure against - without one it stays stacked."
|
|
34
|
+
].freeze
|
|
35
|
+
|
|
36
|
+
style :variant, default: :default, required: true, variants: VARIANTS,
|
|
37
|
+
doc: ":choices packs a run of horizontal checkbox/switch fields tighter."
|
|
38
|
+
|
|
39
|
+
part "field-group", "The stacking container - fields, fieldsets, and separators " \
|
|
40
|
+
"render as direct children; also the @container responsive " \
|
|
41
|
+
"fields measure against"
|
|
42
|
+
|
|
43
|
+
# Renders the stacking container around the content.
|
|
44
|
+
# @api private
|
|
45
|
+
def call
|
|
46
|
+
content_tag(:div, content, **root_attributes.to_attributes)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The container's attributes.
|
|
50
|
+
# @api private
|
|
51
|
+
def root_attributes
|
|
52
|
+
html_attributes.merge_if_not_set(
|
|
53
|
+
{ "data-slot" => "field-group" }.merge(component_data_attributes)
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private :root_attributes
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<%# Shared template for the FieldGroup previews: default stacks wired
|
|
2
|
+
quartet fields around a separator; choices: packs horizontal
|
|
3
|
+
checkbox rows (the tighter run the variant exists for). %>
|
|
4
|
+
<div class="w-96 p-4">
|
|
5
|
+
<%= render component do %>
|
|
6
|
+
<% if local_assigns[:choices] %>
|
|
7
|
+
<%= render Poetry::Ui::Field::Component.new(id: "field-group-preview-disks", label_text: "Hard disks",
|
|
8
|
+
orientation: :horizontal) do |field| %>
|
|
9
|
+
<%= render Poetry::Ui::Checkbox::Component.new(name: "disks", checked: true,
|
|
10
|
+
**field.control_attributes.transform_keys(&:to_sym)) %>
|
|
11
|
+
<% end %>
|
|
12
|
+
<%= render Poetry::Ui::Field::Component.new(id: "field-group-preview-external", label_text: "External disks",
|
|
13
|
+
orientation: :horizontal) do |field| %>
|
|
14
|
+
<%= render Poetry::Ui::Checkbox::Component.new(name: "external",
|
|
15
|
+
**field.control_attributes.transform_keys(&:to_sym)) %>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% else %>
|
|
18
|
+
<%= render Poetry::Ui::Field::Component.new(id: "field-group-preview-email", label_text: "Email") do |field| %>
|
|
19
|
+
<%= render Poetry::Ui::Input::Component.new(type: "email", name: "email",
|
|
20
|
+
**field.control_attributes.transform_keys(&:to_sym)) %>
|
|
21
|
+
<% end %>
|
|
22
|
+
<%= render Poetry::Ui::FieldSeparator::Component.new.with_content("Or continue with") %>
|
|
23
|
+
<%= render Poetry::Ui::Field::Component.new(id: "field-group-preview-sso", label_text: "SSO domain",
|
|
24
|
+
hint: "Your identity provider's domain.") do |field| %>
|
|
25
|
+
<%= render Poetry::Ui::Input::Component.new(name: "sso",
|
|
26
|
+
**field.control_attributes.transform_keys(&:to_sym)) %>
|
|
27
|
+
<% end %>
|
|
28
|
+
<% end %>
|
|
29
|
+
<% end %>
|
|
30
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module FieldGroup
|
|
6
|
+
# The stacking container over real wired Fields - rendering rides
|
|
7
|
+
# the sidecar preview.html.erb (the Field preview precedent).
|
|
8
|
+
class Preview < Poetry::Core::Preview::Base
|
|
9
|
+
def default
|
|
10
|
+
render_with(component: Component.new)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# The tighter checkbox-run rhythm (upstream's checkbox-group form).
|
|
14
|
+
def choices
|
|
15
|
+
render_with(component: Component.new(variant: :choices), choices: true)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module FieldGroup
|
|
6
|
+
# Upstream FieldGroup structure: the named group/@container pair is
|
|
7
|
+
# what responsive fields and theme rhythm rules key on. The stack
|
|
8
|
+
# gap is design and rides the theme under cn-field-group; :choices
|
|
9
|
+
# emits its marker for the tighter checkbox-run rhythm (upstream
|
|
10
|
+
# overrides data-slot to checkbox-group for the same effect - poetry
|
|
11
|
+
# keeps the slot stable and mirrors the variant as a class, the
|
|
12
|
+
# drawer-direction marker pattern).
|
|
13
|
+
class Style < Poetry::Core::Style
|
|
14
|
+
base "cn-field-group group/field-group @container/field-group flex w-full flex-col"
|
|
15
|
+
|
|
16
|
+
# Default is the base state and emits nothing (the marker/core-X
|
|
17
|
+
# empty-variant precedent).
|
|
18
|
+
variant :variant, {
|
|
19
|
+
default: "",
|
|
20
|
+
choices: "cn-field-group-choices"
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# The FieldSeparator family - the divider row between stacked fields.
|
|
6
|
+
module FieldSeparator
|
|
7
|
+
# The FieldSeparator - the divider between stacked fields inside a
|
|
8
|
+
# FieldGroup: a Separator drawn across the
|
|
9
|
+
# row, with an optional inline caption riding on top ("Or continue
|
|
10
|
+
# with"). The caption is visual chrome on a decorative rule - the
|
|
11
|
+
# Separator inside stays aria-hidden either way.
|
|
12
|
+
#
|
|
13
|
+
# @example A captioned divider between stacked fields
|
|
14
|
+
# render Poetry::Ui::FieldSeparator::Component.new { "Or continue with" }
|
|
15
|
+
class Component < Poetry::Core::Component
|
|
16
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
17
|
+
AGENT_RULES = [
|
|
18
|
+
"Divides stacked fields inside a poetry_field_group - not a general-purpose rule " \
|
|
19
|
+
"(that is poetry_separator).",
|
|
20
|
+
"Pass a block for the inline caption form (\"Or continue with\") - the caption sits " \
|
|
21
|
+
"on the line, backed by the page background."
|
|
22
|
+
].freeze
|
|
23
|
+
|
|
24
|
+
part "field-separator", "The divider row - a decorative Separator drawn across it",
|
|
25
|
+
states: {
|
|
26
|
+
"data-content" => { condition: "always - whether the inline caption renders",
|
|
27
|
+
values: %w[true false] }
|
|
28
|
+
}
|
|
29
|
+
part "field-separator-content", "The inline caption span (block content) - sits on " \
|
|
30
|
+
"the line, backed by the page background"
|
|
31
|
+
|
|
32
|
+
# Renders the divider row (rule + optional caption).
|
|
33
|
+
# @api private
|
|
34
|
+
def call
|
|
35
|
+
content_tag(:div, **root_attributes.to_attributes) do
|
|
36
|
+
safe_join([rule, caption].compact)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The divider row's attributes.
|
|
41
|
+
# @api private
|
|
42
|
+
def root_attributes
|
|
43
|
+
html_attributes.merge_if_not_set(
|
|
44
|
+
# Normalized to "true"/"false": ViewComponent's content? is
|
|
45
|
+
# truthy/falsy, not boolean (defined?-strings, blocks), Rails
|
|
46
|
+
# drops false attribute values, and the declared-state
|
|
47
|
+
# contract wants the pair always visible.
|
|
48
|
+
{ "data-slot" => "field-separator", "data-content" => (content? ? "true" : "false") }
|
|
49
|
+
.merge(component_data_attributes)
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def rule
|
|
56
|
+
render(Separator::Component.new(class: css(:line)))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def caption
|
|
60
|
+
return unless content?
|
|
61
|
+
|
|
62
|
+
content_tag(:span, content, "data-slot" => "field-separator-content",
|
|
63
|
+
"class" => css(:content))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private :root_attributes
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module FieldSeparator
|
|
6
|
+
class Preview < Poetry::Core::Preview::Base
|
|
7
|
+
def default
|
|
8
|
+
render_component
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# The inline caption form - the line breaks around the text.
|
|
12
|
+
def with_caption
|
|
13
|
+
render_component { "Or continue with" }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module FieldSeparator
|
|
6
|
+
# Upstream FieldSeparator structure: the row is a positioning context
|
|
7
|
+
# for the absolute Separator; the caption floats centered on it,
|
|
8
|
+
# backed by the page background so the line breaks around the text.
|
|
9
|
+
# Height/margins/type ride the theme under cn-field-separator.
|
|
10
|
+
class Style < Poetry::Core::Style
|
|
11
|
+
base "cn-field-separator relative"
|
|
12
|
+
|
|
13
|
+
element :content, "cn-field-separator-content relative mx-auto block w-fit bg-background"
|
|
14
|
+
# The rule the content sits on (dictionary-resident for the
|
|
15
|
+
# safelist harvest).
|
|
16
|
+
element :line, "absolute inset-0 top-1/2"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# The Fieldset family - a named group of related fields.
|
|
6
|
+
module Fieldset
|
|
7
|
+
# The Fieldset - the Field family's GROUP layer: a run of related
|
|
8
|
+
# fields inside a
|
|
9
|
+
# real <fieldset>, named by a real <legend>. The native pair carries
|
|
10
|
+
# the group semantics assistive technology already understands - no
|
|
11
|
+
# aria wiring to
|
|
12
|
+
# hand-write, which is why legend: is required rather than optional
|
|
13
|
+
# chrome. legend_variant: :label renders the legend at label size
|
|
14
|
+
# while the group keeps its accessible name.
|
|
15
|
+
#
|
|
16
|
+
# @example A named group of address fields
|
|
17
|
+
# render Poetry::Ui::Fieldset::Component.new(legend: "Shipping address") do
|
|
18
|
+
# # poetry_field_group with the fields
|
|
19
|
+
# end
|
|
20
|
+
class Component < Poetry::Core::Component
|
|
21
|
+
# The closed vocabulary for the legend_variant axis.
|
|
22
|
+
LEGEND_VARIANTS = %i[legend label].freeze
|
|
23
|
+
|
|
24
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
25
|
+
AGENT_RULES = [
|
|
26
|
+
"A run of related fields gets poetry_fieldset with legend: - the group's accessible " \
|
|
27
|
+
"name (a bare <div> around fields tells AT nothing).",
|
|
28
|
+
"legend_variant: :label renders the legend at label size - use it when the group is " \
|
|
29
|
+
"one setting explained by its rows (checkbox/switch runs).",
|
|
30
|
+
"hint: is the muted description under the legend; per-field hints stay on the fields.",
|
|
31
|
+
"Stack the fields inside with poetry_field_group - never hand-spaced flex columns."
|
|
32
|
+
].freeze
|
|
33
|
+
|
|
34
|
+
option :legend, :string, required: true, doc: "The group's accessible name - renders as the real <legend>."
|
|
35
|
+
option :legend_variant, :symbol, default: :legend,
|
|
36
|
+
doc: ":label renders the legend at label size - for a group that is one " \
|
|
37
|
+
"setting explained by its rows (checkbox/switch runs)."
|
|
38
|
+
option :hint, :string, doc: "Muted description under the legend; per-field hints stay on the fields."
|
|
39
|
+
|
|
40
|
+
validates :legend_variant, inclusion: { in: LEGEND_VARIANTS }
|
|
41
|
+
|
|
42
|
+
part "field-set", "The <fieldset> root - legend, optional hint, then the fields"
|
|
43
|
+
part "field-legend", "The <legend> - the group's accessible name",
|
|
44
|
+
states: {
|
|
45
|
+
"data-variant" => { condition: "always - the legend's size treatment",
|
|
46
|
+
values: LEGEND_VARIANTS.map(&:to_s) }
|
|
47
|
+
}
|
|
48
|
+
part "field-set-hint", "Muted description under the legend (hint:)"
|
|
49
|
+
|
|
50
|
+
# Enforces the required legend before render.
|
|
51
|
+
# @api private
|
|
52
|
+
def before_render
|
|
53
|
+
raise ArgumentError, "Fieldset requires legend: (the group's accessible name)" if legend.blank?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Renders the <fieldset> (legend, optional hint, then the fields).
|
|
57
|
+
# @api private
|
|
58
|
+
def call
|
|
59
|
+
content_tag(:fieldset, **root_attributes.to_attributes) do
|
|
60
|
+
safe_join([legend_tag, hint_tag, content].compact)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The <fieldset> root's attributes.
|
|
65
|
+
# @api private
|
|
66
|
+
def root_attributes
|
|
67
|
+
html_attributes.merge_if_not_set(
|
|
68
|
+
{ "data-slot" => "field-set" }.merge(component_data_attributes)
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def legend_tag
|
|
75
|
+
content_tag(:legend, legend, "data-slot" => "field-legend",
|
|
76
|
+
"data-variant" => legend_variant,
|
|
77
|
+
"class" => css(:legend))
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def hint_tag
|
|
81
|
+
return if hint.blank?
|
|
82
|
+
|
|
83
|
+
content_tag(:p, hint, "data-slot" => "field-set-hint", "class" => css(:hint))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private :root_attributes
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<%# Shared template for the Fieldset previews: the legend/hint pair over a
|
|
2
|
+
FieldGroup of real wired Fields (the canonical composition). %>
|
|
3
|
+
<div class="w-96 p-4">
|
|
4
|
+
<%= render component do %>
|
|
5
|
+
<%= render Poetry::Ui::FieldGroup::Component.new do %>
|
|
6
|
+
<%= render Poetry::Ui::Field::Component.new(id: "fieldset-preview-street", label_text: "Street address") do |field| %>
|
|
7
|
+
<%= render Poetry::Ui::Input::Component.new(name: "street", placeholder: "123 Main St",
|
|
8
|
+
**field.control_attributes.transform_keys(&:to_sym)) %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<div class="grid grid-cols-2 gap-4">
|
|
11
|
+
<%= render Poetry::Ui::Field::Component.new(id: "fieldset-preview-city", label_text: "City") do |field| %>
|
|
12
|
+
<%= render Poetry::Ui::Input::Component.new(name: "city", placeholder: "New York",
|
|
13
|
+
**field.control_attributes.transform_keys(&:to_sym)) %>
|
|
14
|
+
<% end %>
|
|
15
|
+
<%= render Poetry::Ui::Field::Component.new(id: "fieldset-preview-zip", label_text: "Postal code") do |field| %>
|
|
16
|
+
<%= render Poetry::Ui::Input::Component.new(name: "zip", placeholder: "90502",
|
|
17
|
+
**field.control_attributes.transform_keys(&:to_sym)) %>
|
|
18
|
+
<% end %>
|
|
19
|
+
</div>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% end %>
|
|
22
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Fieldset
|
|
6
|
+
# The group layer over real nested Fields - rendering rides the
|
|
7
|
+
# sidecar preview.html.erb (nesting controls inside fields needs a
|
|
8
|
+
# real view context, the Field preview precedent).
|
|
9
|
+
class Preview < Poetry::Core::Preview::Base
|
|
10
|
+
def default
|
|
11
|
+
render_with(component: Component.new(legend: "Address information",
|
|
12
|
+
hint: "We need your address to deliver the order."))
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# The label-sized legend: the group is one setting explained by
|
|
16
|
+
# its rows (the checkbox/switch-run form).
|
|
17
|
+
def label_legend
|
|
18
|
+
render_with(component: Component.new(legend: "Show these items",
|
|
19
|
+
legend_variant: :label,
|
|
20
|
+
hint: "Pick what lands on the desktop."))
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Fieldset
|
|
6
|
+
# Upstream FieldSet/FieldLegend/FieldDescription structure; the
|
|
7
|
+
# group rhythm (gaps, legend margins, type scale) rides the theme.
|
|
8
|
+
# :hint wears cn-field-description - the same style hook as Field's
|
|
9
|
+
# hint, so one theme rule styles description text across the family.
|
|
10
|
+
class Style < Poetry::Core::Style
|
|
11
|
+
base "cn-field-set flex flex-col"
|
|
12
|
+
|
|
13
|
+
element :legend, "cn-field-legend"
|
|
14
|
+
element :hint, "cn-field-description"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<% if variant == :input %>
|
|
2
|
+
<%= render input_variant_component %>
|
|
3
|
+
<% else %>
|
|
4
|
+
<%= content_tag(:div, **root_attributes.to_attributes) do %>
|
|
5
|
+
<%= content_tag(:label, dropzone_attributes) do %>
|
|
6
|
+
<%= tag(:input, control_attributes) %>
|
|
7
|
+
<%= render Poetry::Ui::Icon::Component.new(name: :upload, class: css(:icon)) %>
|
|
8
|
+
<span data-slot="file-input-prompt" class="<%= css(:prompt) %>"><%= prompt_text %></span>
|
|
9
|
+
<% if hint.present? %><span data-slot="file-input-hint" class="<%= css(:hint) %>"><%= hint %></span><% end %>
|
|
10
|
+
<% end %>
|
|
11
|
+
<%= content_tag(:ul, "", list_attributes) %>
|
|
12
|
+
<%= content_tag(:button, t("poetry.file_input.clear"), clear_attributes) %>
|
|
13
|
+
<% end %>
|
|
14
|
+
<% end %>
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# The FileInput family - file selection as a plain control or a dropzone.
|
|
6
|
+
module FileInput
|
|
7
|
+
# The FileInput - file
|
|
8
|
+
# selection in two shapes. variant: :input is the plain styled native
|
|
9
|
+
# control (the Input component with type=file - zero JS, the browser
|
|
10
|
+
# shows the selection). variant: :dropzone is the drag-and-drop
|
|
11
|
+
# surface: a <label> wrapping a visually-hidden native input - so
|
|
12
|
+
# click-to-browse and keyboard access are the PLATFORM's - with JS
|
|
13
|
+
# adding only what HTML cannot
|
|
14
|
+
# (drop, the selection list, clear). The native input is always the
|
|
15
|
+
# form value; ActiveStorage direct upload rides it untouched
|
|
16
|
+
# (data: { direct_upload_url: ... } passes straight through).
|
|
17
|
+
#
|
|
18
|
+
# @example Drag-and-drop upload surface
|
|
19
|
+
# render Poetry::Ui::FileInput::Component.new(
|
|
20
|
+
# variant: :dropzone, name: "attachments[]", multiple: true,
|
|
21
|
+
# hint: "PDF or PNG, up to 10 MB"
|
|
22
|
+
# )
|
|
23
|
+
class Component < Poetry::Core::Component
|
|
24
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
25
|
+
AGENT_RULES = [
|
|
26
|
+
"File selection is a FileInput: variant: :input for compact forms, :dropzone when " \
|
|
27
|
+
"dragging is expected (uploads as the page's point) - never a hand-rolled drop div.",
|
|
28
|
+
"The native input is the form value: set name: (multiple: true wants a name ending " \
|
|
29
|
+
"in [] for Rails params); ActiveStorage direct upload attaches to it as usual.",
|
|
30
|
+
"The dropzone's selected-file list and clear button are controller-rendered - compose " \
|
|
31
|
+
"prompt:/hint: copy instead of adding your own list markup.",
|
|
32
|
+
"In a Field, prefer form.file_input (the builder wires id/label/errors); the bare " \
|
|
33
|
+
"component suits standalone dropzones."
|
|
34
|
+
].freeze
|
|
35
|
+
|
|
36
|
+
use_stimulus do
|
|
37
|
+
on :root do
|
|
38
|
+
controller :file_input do
|
|
39
|
+
register
|
|
40
|
+
value :multiple
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
on :dropzone do
|
|
44
|
+
controller :file_input do
|
|
45
|
+
action :dragenter, on: :dragenter
|
|
46
|
+
action :dragover, on: :dragover
|
|
47
|
+
action :dragleave, on: :dragleave
|
|
48
|
+
action :drop, on: :drop
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
on :control do
|
|
52
|
+
controller :file_input do
|
|
53
|
+
target :input
|
|
54
|
+
action :changed, on: :change
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
on :list do
|
|
58
|
+
controller(:file_input) { target :list }
|
|
59
|
+
end
|
|
60
|
+
on :clear do
|
|
61
|
+
controller :file_input do
|
|
62
|
+
target :clear
|
|
63
|
+
action :clear, on: :click
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
style :variant, default: :input, variants: %i[input dropzone],
|
|
69
|
+
doc: ":input is the compact native control; :dropzone the drag-and-drop surface."
|
|
70
|
+
|
|
71
|
+
option :name, :string,
|
|
72
|
+
doc: "The native input's name - the submitted param (multiple: true wants a name ending in [] for " \
|
|
73
|
+
"Rails params)."
|
|
74
|
+
option :id, :string, doc: "The native input's id (Field/FormBuilder wire it to the label)."
|
|
75
|
+
option :multiple, :boolean, default: false,
|
|
76
|
+
doc: "Allows selecting several files; forwarded to the native input."
|
|
77
|
+
option :accept, :string, doc: "The native accept filter (e.g. \"image/*,.pdf\")."
|
|
78
|
+
option :disabled, :boolean, default: false, doc: "Disables the native input and dims the dropzone."
|
|
79
|
+
option :invalid, :boolean, default: false,
|
|
80
|
+
doc: "Marks the control aria-invalid (set by Field/FormBuilder from model errors)."
|
|
81
|
+
option :described_by, :string, doc: "Ids for the native input's aria-describedby (Field wires this)."
|
|
82
|
+
option :prompt, :string, doc: "The dropzone's instruction line - overrides the translated default."
|
|
83
|
+
option :hint, :string, doc: "Muted constraints copy under the prompt (formats, size limits)."
|
|
84
|
+
|
|
85
|
+
part "file-input", "The dropzone root - wraps the zone, the selection list, and clear",
|
|
86
|
+
states: {
|
|
87
|
+
"data-variant" => { condition: "always on the dropzone root (the input variant " \
|
|
88
|
+
"renders the Input component instead)",
|
|
89
|
+
values: %w[dropzone] },
|
|
90
|
+
"data-dragging" => { condition: "a file drag is over the zone (controller-written, " \
|
|
91
|
+
"enter/leave counted)" },
|
|
92
|
+
"data-populated" => { condition: "the native input holds at least one file " \
|
|
93
|
+
"(controller-written)" }
|
|
94
|
+
}
|
|
95
|
+
part "file-input-dropzone", "The <label> drop surface - dashed, platform click-to-browse; " \
|
|
96
|
+
"its text is the control's accessible name"
|
|
97
|
+
part "file-input-control", "The native <input type=file> - visually hidden in the " \
|
|
98
|
+
"dropzone, THE form value in both variants"
|
|
99
|
+
part "file-input-prompt", "The zone's instruction line (prompt: overrides the default)"
|
|
100
|
+
part "file-input-hint", "Muted constraints copy under the prompt (hint: - formats, size)"
|
|
101
|
+
part "file-input-list", "The selected-file <ul> the controller fills (name + size per " \
|
|
102
|
+
"item; items are controller-built, not server parts)"
|
|
103
|
+
part "file-input-clear", "The clear affordance - hidden until populated; never re-opens " \
|
|
104
|
+
"the picker"
|
|
105
|
+
|
|
106
|
+
# Enforces visible prompt text on the dropzone variant.
|
|
107
|
+
# @api private
|
|
108
|
+
def before_render
|
|
109
|
+
# The dropzone announces itself through the label text; the input
|
|
110
|
+
# variant is named externally (Field/Label) like any Input.
|
|
111
|
+
return unless variant == :dropzone && prompt_text.blank?
|
|
112
|
+
|
|
113
|
+
raise ArgumentError, "FileInput dropzone requires visible prompt text"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# The resolved instruction line (prompt: or the translated default).
|
|
117
|
+
# @api private
|
|
118
|
+
def prompt_text
|
|
119
|
+
prompt.presence || t("poetry.file_input.prompt")
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# The input variant renders the Input component AS the whole
|
|
123
|
+
# surface, so the FileInput's own extra attributes (aria-label,
|
|
124
|
+
# class, data-*) must forward onto it - dropping them would strand
|
|
125
|
+
# the accessible name.
|
|
126
|
+
# @api private
|
|
127
|
+
def input_variant_component
|
|
128
|
+
Input::Component.new(
|
|
129
|
+
type: "file", name: name, disabled: disabled, invalid: invalid,
|
|
130
|
+
**{ "id" => id, "accept" => accept, "multiple" => multiple || nil,
|
|
131
|
+
"aria-describedby" => described_by }.compact,
|
|
132
|
+
**html_attributes.to_attributes.transform_keys(&:to_sym)
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# The hidden native input's attributes (dropzone variant).
|
|
137
|
+
# @api private
|
|
138
|
+
def control_attributes
|
|
139
|
+
attrs = {
|
|
140
|
+
"type" => "file", "class" => "sr-only", "data-slot" => "file-input-control",
|
|
141
|
+
"name" => name, "id" => id, "accept" => accept,
|
|
142
|
+
"aria-describedby" => described_by
|
|
143
|
+
}.compact
|
|
144
|
+
attrs["multiple"] = true if multiple
|
|
145
|
+
attrs["disabled"] = true if disabled
|
|
146
|
+
attrs["aria-invalid"] = "true" if invalid
|
|
147
|
+
attrs.merge(stimulus_attributes_for(:control))
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# The dropzone root's attributes.
|
|
151
|
+
# @api private
|
|
152
|
+
def root_attributes
|
|
153
|
+
html_attributes.merge_if_not_set(
|
|
154
|
+
{ "data-slot" => "file-input", "data-variant" => variant }
|
|
155
|
+
.merge(component_data_attributes).merge(stimulus_attributes_for(:root))
|
|
156
|
+
)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# The <label> drop surface's attributes.
|
|
160
|
+
# @api private
|
|
161
|
+
def dropzone_attributes
|
|
162
|
+
{
|
|
163
|
+
"data-slot" => "file-input-dropzone",
|
|
164
|
+
"class" => "#{css(:dropzone)}#{" #{css(:dropzone_disabled)}" if disabled}"
|
|
165
|
+
}.merge(stimulus_attributes_for(:dropzone))
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# The controller-filled selection list's attributes.
|
|
169
|
+
# @api private
|
|
170
|
+
def list_attributes
|
|
171
|
+
{ "data-slot" => "file-input-list", "class" => css(:list) }
|
|
172
|
+
.merge(stimulus_attributes_for(:list))
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# The clear button's attributes (hidden until files are selected).
|
|
176
|
+
# @api private
|
|
177
|
+
def clear_attributes
|
|
178
|
+
{ "type" => "button", "data-slot" => "file-input-clear", "hidden" => true,
|
|
179
|
+
"class" => css(:clear) }
|
|
180
|
+
.merge(stimulus_attributes_for(:clear))
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
private :prompt_text, :input_variant_component, :control_attributes, :root_attributes, :dropzone_attributes
|
|
184
|
+
private :list_attributes, :clear_attributes
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module FileInput
|
|
6
|
+
class Preview < Poetry::Core::Preview::Base
|
|
7
|
+
# The compact form control: the Input component with type=file -
|
|
8
|
+
# the browser renders the selection, no JS.
|
|
9
|
+
def default
|
|
10
|
+
render_component(name: "document", "aria-label": "Document")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def dropzone
|
|
14
|
+
render_component(variant: :dropzone, name: "attachments[]", multiple: true,
|
|
15
|
+
hint: "PNG, JPG or PDF, up to 10 MB each")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def dropzone_custom_prompt
|
|
19
|
+
render_component(variant: :dropzone, name: "avatar", accept: "image/*",
|
|
20
|
+
prompt: "Drop your avatar here", hint: "Square images look best")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def dropzone_disabled
|
|
24
|
+
render_component(variant: :dropzone, name: "evidence", disabled: true,
|
|
25
|
+
hint: "Uploads are locked while the case is closed")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|