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,81 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# poetry's editor hook, written by `bin/rails g poetry:editor`: runs
|
|
5
|
+
# `poetry check` on the app template an agent just edited and hands the
|
|
6
|
+
# findings straight back to the agent, so the check runs after EVERY edit
|
|
7
|
+
# instead of when the agent remembers to. Stdlib only; the check itself runs
|
|
8
|
+
# through bin/rails, so it sees the same registry, icon set, and charts the
|
|
9
|
+
# rake task sees.
|
|
10
|
+
#
|
|
11
|
+
# Two hook dialects, told apart by the payload:
|
|
12
|
+
# Claude Code (PostToolUse): errors -> exit 2 with the report on stderr (fed
|
|
13
|
+
# back to the agent); warnings -> exit 0 with additionalContext.
|
|
14
|
+
# Cursor (postToolUse): any findings -> exit 0 with additional_context.
|
|
15
|
+
# Anything that is not an app template exits 0 without booting Rails; a check
|
|
16
|
+
# that cannot run at all exits 1, so the loop fails open, never closed.
|
|
17
|
+
|
|
18
|
+
require "json"
|
|
19
|
+
require "open3"
|
|
20
|
+
|
|
21
|
+
payload = begin
|
|
22
|
+
JSON.parse($stdin.read)
|
|
23
|
+
rescue JSON::ParserError
|
|
24
|
+
{}
|
|
25
|
+
end
|
|
26
|
+
payload = {} unless payload.is_a?(Hash)
|
|
27
|
+
tool_input = payload["tool_input"].is_a?(Hash) ? payload["tool_input"] : {}
|
|
28
|
+
edited = tool_input["file_path"] || tool_input["path"] || payload["file_path"]
|
|
29
|
+
exit 0 unless edited.is_a?(String) && !edited.empty?
|
|
30
|
+
|
|
31
|
+
project = ENV["CLAUDE_PROJECT_DIR"] || Array(payload["workspace_roots"]).first || payload["cwd"] || Dir.pwd
|
|
32
|
+
root = File.expand_path(project)
|
|
33
|
+
full = File.expand_path(edited, root)
|
|
34
|
+
exit 0 unless full.start_with?("#{root}/app/") && full.end_with?(".html.erb") && File.file?(full)
|
|
35
|
+
template = full.delete_prefix("#{root}/")
|
|
36
|
+
|
|
37
|
+
cursor = payload.key?("conversation_id") || payload["hook_event_name"] == "postToolUse"
|
|
38
|
+
|
|
39
|
+
begin
|
|
40
|
+
stdout, stderr, status = Open3.capture3({ "POETRY_CHECK_JSON" => "1" }, "bin/rails", "poetry:check[#{template}]",
|
|
41
|
+
chdir: root)
|
|
42
|
+
rescue SystemCallError => e
|
|
43
|
+
warn "poetry check hook: could not run bin/rails (#{e.message})"
|
|
44
|
+
exit 1
|
|
45
|
+
end
|
|
46
|
+
findings = begin
|
|
47
|
+
JSON.parse(stdout)
|
|
48
|
+
rescue JSON::ParserError
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
unless findings.is_a?(Array)
|
|
52
|
+
warn "poetry check hook: poetry:check did not run (exit #{status.exitstatus})\n#{stderr.lines.last(10).join}"
|
|
53
|
+
exit 1
|
|
54
|
+
end
|
|
55
|
+
if findings.empty?
|
|
56
|
+
puts "{}" if cursor
|
|
57
|
+
exit 0
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
errors = findings.count { |finding| finding["severity"] == "error" }
|
|
61
|
+
warnings = findings.size - errors
|
|
62
|
+
lines = findings.map do |finding|
|
|
63
|
+
hint = finding["suggestion"] ? " (did you mean #{finding["suggestion"]}?)" : ""
|
|
64
|
+
"- [#{finding["severity"]}] line #{finding["line"]}: #{finding["message"]}#{hint}"
|
|
65
|
+
end
|
|
66
|
+
headline = if errors.positive?
|
|
67
|
+
"poetry check: #{errors} error(s), #{warnings} warning(s) in #{template} - " \
|
|
68
|
+
"an error raises or misrenders at render time; fix it, then re-run poetry check"
|
|
69
|
+
else
|
|
70
|
+
"poetry check: #{warnings} warning(s) in #{template} - advisory; fix unless the deviation is deliberate"
|
|
71
|
+
end
|
|
72
|
+
report = [headline, *lines].join("\n")
|
|
73
|
+
|
|
74
|
+
if cursor
|
|
75
|
+
puts JSON.generate("additional_context" => report)
|
|
76
|
+
elsif errors.positive?
|
|
77
|
+
warn report
|
|
78
|
+
exit 2
|
|
79
|
+
else
|
|
80
|
+
puts JSON.generate("hookSpecificOutput" => { "hookEventName" => "PostToolUse", "additionalContext" => report })
|
|
81
|
+
end
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require_relative "../agents_section"
|
|
5
|
+
require_relative "../skills_section"
|
|
6
|
+
|
|
7
|
+
module Poetry
|
|
8
|
+
# `rails g poetry:install` - wires poetry into a host app:
|
|
9
|
+
#
|
|
10
|
+
# app/assets/tailwind/poetry/tokens.css the design tokens (:root + .dark)
|
|
11
|
+
# app/assets/tailwind/poetry/theme.css the Tailwind v4 @theme mapping
|
|
12
|
+
# app/assets/tailwind/poetry/animate.css the vendored animation
|
|
13
|
+
# utility layer (Rails hosts
|
|
14
|
+
# have no npm)
|
|
15
|
+
# app/assets/tailwind/poetry/safelist.txt every dictionary + template class
|
|
16
|
+
# (so the host build never purges
|
|
17
|
+
# classes resolved in Ruby)
|
|
18
|
+
# config/initializers/poetry.rb commented configuration
|
|
19
|
+
# config/poetry_components.yml the copy-in manifest (empty)
|
|
20
|
+
#
|
|
21
|
+
# plus idempotent @import/@source injection into the host's Tailwind entry
|
|
22
|
+
# (append-unless-present - re-running install is always safe).
|
|
23
|
+
#
|
|
24
|
+
# `--charts` additionally wires poetry-charts (the gem must already be in
|
|
25
|
+
# the bundle - its engine merges the @poetry/charts importmap pins and the
|
|
26
|
+
# safelist pass picks the chart dictionaries up on its own; what a host
|
|
27
|
+
# still needs by hand is the motion stylesheet in the Tailwind entry and
|
|
28
|
+
# the Stimulus registration, and that is exactly what the flag does).
|
|
29
|
+
#
|
|
30
|
+
# @example
|
|
31
|
+
# bin/rails g poetry:install --theme vega
|
|
32
|
+
class InstallGenerator < Rails::Generators::Base
|
|
33
|
+
include Generators::AgentsSection
|
|
34
|
+
include Generators::SkillsSection
|
|
35
|
+
|
|
36
|
+
# The host's Tailwind entry stylesheet (import/@source injection).
|
|
37
|
+
TAILWIND_ENTRY = "app/assets/tailwind/application.css"
|
|
38
|
+
# The theme slot: --theme swaps its CONTENT, the filename stays put.
|
|
39
|
+
STYLE_SLOT = "app/assets/tailwind/poetry/style-default.css"
|
|
40
|
+
# Every shipped fragment opens with `/* poetry <name> theme` - the sniff
|
|
41
|
+
# reads the slot's first line back so a plain re-run keeps the theme.
|
|
42
|
+
THEME_HEADER = %r{\A/\* poetry ([a-z0-9-]+) theme\b}
|
|
43
|
+
|
|
44
|
+
class_option :charts, type: :boolean, default: false,
|
|
45
|
+
desc: %(Also wire poetry-charts (requires gem "poetry-charts" in the bundle))
|
|
46
|
+
|
|
47
|
+
# Install-time theme selection. Every themes/<name>.css fragment is
|
|
48
|
+
# a complete visual theme; the chosen one fills the style-default.css
|
|
49
|
+
# slot (the SLOT filename never changes - that keeps ENTRY_LINES
|
|
50
|
+
# idempotent and makes switching themes a re-run with a different
|
|
51
|
+
# --theme, overwriting in place). One theme per build; the multi-theme
|
|
52
|
+
# .style-<name> wrapper arrives with the docs switcher, not here.
|
|
53
|
+
#
|
|
54
|
+
# The upgrade-path contract: the default is nil, not "default" -
|
|
55
|
+
# a plain re-run sniffs the theme already in the slot and keeps it, so
|
|
56
|
+
# upgrading (bundle update + re-run) never swaps an app's design. An
|
|
57
|
+
# explicit --theme always wins; only a first install falls to "default".
|
|
58
|
+
class_option :theme, type: :string, default: nil,
|
|
59
|
+
desc: "Visual theme fragment to install (a themes/<name>.css shipped by poetry-ui); " \
|
|
60
|
+
"defaults to the theme already installed, or \"default\" on a first install"
|
|
61
|
+
|
|
62
|
+
# Injected line by line (not as one block) so a re-run after an upgrade
|
|
63
|
+
# appends any line a previous poetry version didn't know about.
|
|
64
|
+
ENTRY_LINES = [
|
|
65
|
+
%(@import "./poetry/tokens.css";),
|
|
66
|
+
%(@import "./poetry/theme.css";),
|
|
67
|
+
%(@import "./poetry/animate.css";),
|
|
68
|
+
%(@import "./poetry/utilities.css";),
|
|
69
|
+
%(@import "./poetry/aliases.css";),
|
|
70
|
+
%(@import "./poetry/style-default.css" layer(base);),
|
|
71
|
+
%(@import "./poetry/base.css";),
|
|
72
|
+
%(@import "./poetry/typeset.css";),
|
|
73
|
+
%(@source "./poetry/safelist.txt";)
|
|
74
|
+
].freeze
|
|
75
|
+
|
|
76
|
+
# The base layer (upstream's init writes the same defaults into the
|
|
77
|
+
# host stylesheet):
|
|
78
|
+
# without it body/border/outline don't ride the tokens and dark mode
|
|
79
|
+
# only flips the components. Seeded once,
|
|
80
|
+
# user-owned - re-install never overwrites.
|
|
81
|
+
BASE_CSS = <<~CSS
|
|
82
|
+
/* poetry base layer (source-parity defaults) - yours to edit. */
|
|
83
|
+
@layer base {
|
|
84
|
+
* {
|
|
85
|
+
border-color: var(--border);
|
|
86
|
+
outline-color: color-mix(in oklab, var(--ring) 50%, transparent);
|
|
87
|
+
}
|
|
88
|
+
body {
|
|
89
|
+
background-color: var(--background);
|
|
90
|
+
color: var(--foreground);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
CSS
|
|
94
|
+
|
|
95
|
+
desc "Install poetry: tokens, Tailwind theme, safelist, initializer, and the component manifest"
|
|
96
|
+
|
|
97
|
+
# Fails fast BEFORE any file lands: --charts against a bundle without
|
|
98
|
+
# the gem would otherwise half-install (css copied, dead registration).
|
|
99
|
+
# @api private
|
|
100
|
+
def verify_charts_gem
|
|
101
|
+
return if !options[:charts] || charts_available?
|
|
102
|
+
|
|
103
|
+
raise Thor::Error, "--charts needs poetry-charts in the bundle - add " \
|
|
104
|
+
'`gem "poetry-charts"` to the Gemfile, bundle, and re-run'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Same fail-fast for --theme: an unknown name (or one poetry-charts
|
|
108
|
+
# doesn't ship when --charts is on) must not half-install.
|
|
109
|
+
# @api private
|
|
110
|
+
def verify_theme_choice
|
|
111
|
+
unless ui_theme_path.exist?
|
|
112
|
+
available = Dir[Poetry::Ui.root.join("themes/*.css").to_s].map { |f| File.basename(f, ".css") }.sort
|
|
113
|
+
raise Thor::Error, "unknown poetry theme #{resolved_theme.inspect} - poetry-ui ships: #{available.join(", ")}"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
return if !options[:charts] || !charts_available? || charts_theme_path.exist?
|
|
117
|
+
|
|
118
|
+
raise Thor::Error, "poetry-charts does not ship theme #{resolved_theme.inspect} - " \
|
|
119
|
+
"every installed poetry gem must provide themes/#{resolved_theme}.css"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Step: copies tokens, the Tailwind theme mapping, the vendored css,
|
|
123
|
+
# and the theme slot.
|
|
124
|
+
# @api private
|
|
125
|
+
def copy_tokens_and_theme
|
|
126
|
+
create_file "app/assets/tailwind/poetry/tokens.css",
|
|
127
|
+
Poetry::Core.root.join("tokens/tokens.css").read, force: true
|
|
128
|
+
create_file "app/assets/tailwind/poetry/theme.css",
|
|
129
|
+
Poetry::Core.root.join("tokens/tailwind-theme.css").read, force: true
|
|
130
|
+
create_file "app/assets/tailwind/poetry/animate.css",
|
|
131
|
+
Poetry::Core.root.join("vendor/tw-animate-css/tw-animate.css").read, force: true
|
|
132
|
+
# The upstream first-party utility layer (shimmer / scroll-fade
|
|
133
|
+
# families + the chat-set keyframes), vendored verbatim at a pinned
|
|
134
|
+
# SHA - provenance in THIRD_PARTY_NOTICES.md (host filename stays
|
|
135
|
+
# utilities.css).
|
|
136
|
+
create_file "app/assets/tailwind/poetry/utilities.css",
|
|
137
|
+
Poetry::Core.root.join("vendor/shadcn-tailwind/tailwind.css").read, force: true
|
|
138
|
+
create_file "app/assets/tailwind/poetry/aliases.css",
|
|
139
|
+
Poetry::Core.root.join("tokens/aliases.css").read, force: true
|
|
140
|
+
# The cn-* theme layer: the named-class design source, imported
|
|
141
|
+
# layer(base) so host utilities always win. Vendored like tokens
|
|
142
|
+
# (force) - a host restyles by overriding .cn-* rules in its OWN css
|
|
143
|
+
# (any utilities-layer or unlayered rule beats layer(base)), never by
|
|
144
|
+
# editing this file, so theme updates keep flowing on re-install.
|
|
145
|
+
# --theme swaps the CONTENT; the slot filename stays put.
|
|
146
|
+
create_file "app/assets/tailwind/poetry/style-default.css",
|
|
147
|
+
ui_theme_path.read, force: true
|
|
148
|
+
create_file "app/assets/tailwind/poetry/base.css", BASE_CSS, skip: true
|
|
149
|
+
# poetry/typeset (the vendored prose-styling port - provenance in
|
|
150
|
+
# THIRD_PARTY_NOTICES.md): prose styling for
|
|
151
|
+
# rendered markdown. App-OWNED like base.css (skip, never force) -
|
|
152
|
+
# the whole point of the artifact is that the file is yours to tune.
|
|
153
|
+
create_file "app/assets/tailwind/poetry/typeset.css",
|
|
154
|
+
Poetry::Ui.root.join("typeset/typeset.css").read, skip: true
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Step: writes the dictionary + template-class safelist.
|
|
158
|
+
# @api private
|
|
159
|
+
def generate_safelist
|
|
160
|
+
# Style.descendants is empty until the component classes load - under
|
|
161
|
+
# `rails g` nothing has autoloaded them (the fresh-app proof caught
|
|
162
|
+
# this; the dummy suite masked it by eager-loading first).
|
|
163
|
+
Rails.application.eager_load!
|
|
164
|
+
styles = Poetry::Core::Style.descendants.select(&:name)
|
|
165
|
+
# Template-static classes (sr-only, animate-spin) come from the
|
|
166
|
+
# COMMITTED list - herb-extracted and drift-gated in poetry's CI,
|
|
167
|
+
# never required in a host (the browser pass caught the live-scan
|
|
168
|
+
# skip purging them).
|
|
169
|
+
safelist = Poetry::Core::CSS::Safelist.new(style_classes: styles,
|
|
170
|
+
template_classes: Poetry::Ui.template_classes)
|
|
171
|
+
create_file "app/assets/tailwind/poetry/safelist.txt", safelist.text, force: true
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Step: injects the poetry @import/@source lines into the host's
|
|
175
|
+
# Tailwind entry.
|
|
176
|
+
# @api private
|
|
177
|
+
def wire_tailwind_entry
|
|
178
|
+
unless File.exist?(File.join(destination_root, TAILWIND_ENTRY))
|
|
179
|
+
create_file TAILWIND_ENTRY, %(@import "tailwindcss";\n)
|
|
180
|
+
end
|
|
181
|
+
ENTRY_LINES.each { |line| inject_unless_present(TAILWIND_ENTRY, line) }
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Step: writes the commented configuration initializer.
|
|
185
|
+
# @api private
|
|
186
|
+
def create_initializer
|
|
187
|
+
create_file "config/initializers/poetry.rb", <<~RUBY, skip: true
|
|
188
|
+
# frozen_string_literal: true
|
|
189
|
+
|
|
190
|
+
# poetry configuration. Defaults shown commented.
|
|
191
|
+
#
|
|
192
|
+
# Poetry::Core::Config.current.css_mode = :tailwind # or :bem (bring your own CSS)
|
|
193
|
+
# Poetry::Core::Config.current.icon_library = :lucide
|
|
194
|
+
RUBY
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Step: writes the empty copy-in manifest.
|
|
198
|
+
# @api private
|
|
199
|
+
def create_manifest
|
|
200
|
+
create_file "config/poetry_components.yml", "components: {}\n", skip: true
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Pins alone don't register controllers: without this call every poetry
|
|
204
|
+
# controller is dead JS (the browser pass caught the dialog trigger
|
|
205
|
+
# doing nothing in a fresh host).
|
|
206
|
+
# @api private
|
|
207
|
+
def register_controllers
|
|
208
|
+
index = "app/javascript/controllers/index.js"
|
|
209
|
+
unless File.exist?(File.join(destination_root, index))
|
|
210
|
+
say_status :note, "no #{index} - register poetry's controllers yourself: " \
|
|
211
|
+
"registerPoetryControllers(application) from \"@poetry/controllers\" " \
|
|
212
|
+
"(and registerPoetryAgent(application) from \"@poetry/agent\" " \
|
|
213
|
+
"when poetry-agent is bundled)", :yellow
|
|
214
|
+
return
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
inject_unless_present(index, <<~JS.strip)
|
|
218
|
+
import { registerPoetryControllers } from "@poetry/controllers"
|
|
219
|
+
registerPoetryControllers(application)
|
|
220
|
+
JS
|
|
221
|
+
register_agent_runtime(index)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# --charts: the two host-side wires the charts engine cannot do itself.
|
|
225
|
+
# The motion stylesheet is COPIED (tailwindcss-rails compiles standalone;
|
|
226
|
+
# a gem-path @import would not resolve) - vendored artifact, force like
|
|
227
|
+
# tokens; the entry @import and the Stimulus registration ride the same
|
|
228
|
+
# idempotent primitives as the core wiring.
|
|
229
|
+
# @api private
|
|
230
|
+
def wire_charts
|
|
231
|
+
return unless options[:charts]
|
|
232
|
+
|
|
233
|
+
create_file "app/assets/tailwind/poetry/charts.css",
|
|
234
|
+
Poetry::Charts.root.join("app/assets/stylesheets/poetry-charts.css").read,
|
|
235
|
+
force: true
|
|
236
|
+
inject_unless_present(TAILWIND_ENTRY, %(@import "./poetry/charts.css";))
|
|
237
|
+
# The charts cn-* theme fragment - vendored like style-default,
|
|
238
|
+
# same --theme selection.
|
|
239
|
+
create_file "app/assets/tailwind/poetry/style-charts.css",
|
|
240
|
+
charts_theme_path.read, force: true
|
|
241
|
+
inject_unless_present(TAILWIND_ENTRY, %(@import "./poetry/style-charts.css" layer(base);))
|
|
242
|
+
|
|
243
|
+
index = "app/javascript/controllers/index.js"
|
|
244
|
+
unless File.exist?(File.join(destination_root, index))
|
|
245
|
+
say_status :note, "no #{index} - register the chart controllers yourself: " \
|
|
246
|
+
"registerPoetryChartsControllers(application) from \"@poetry/charts\"", :yellow
|
|
247
|
+
return
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
inject_unless_present(index, <<~JS.strip)
|
|
251
|
+
import { registerPoetryChartsControllers } from "@poetry/charts"
|
|
252
|
+
registerPoetryChartsControllers(application)
|
|
253
|
+
JS
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# The llms.txt / llms-full.txt agent docs are engine routes - without
|
|
257
|
+
# the mount they are unreachable (the fresh-app proof caught this).
|
|
258
|
+
# @api private
|
|
259
|
+
def mount_engine
|
|
260
|
+
routes = File.join(destination_root, "config/routes.rb")
|
|
261
|
+
return unless File.exist?(routes)
|
|
262
|
+
return if File.read(routes).include?("Poetry::Ui::Engine")
|
|
263
|
+
|
|
264
|
+
route %(mount Poetry::Ui::Engine => "/poetry" # llms.txt + llms-full.txt (agent-facing docs))
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# The AGENTS.md pointer section - marker-bounded so a re-run
|
|
268
|
+
# refreshes it in place. Standalone refresh: `rails g poetry:agents`.
|
|
269
|
+
# @api private
|
|
270
|
+
def write_agents_md
|
|
271
|
+
apply_agents_section
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# The Claude Code skills - part of the standard
|
|
275
|
+
# install surface, like AGENTS.md. Standalone refresh:
|
|
276
|
+
# `rails g poetry:skill` (re-run after updating poetry gems).
|
|
277
|
+
# @api private
|
|
278
|
+
def write_skills
|
|
279
|
+
apply_poetry_skills
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Dark mode is one layout line, but nothing else in the install touches
|
|
283
|
+
# the layout - without the pointer the theme never applies before first
|
|
284
|
+
# paint and hosts rediscover the flash-of-light-mode pothole.
|
|
285
|
+
# @api private
|
|
286
|
+
def announce_color_scheme
|
|
287
|
+
say_status :note, "dark mode: render <%= poetry_color_scheme_script %> in your layout <head> " \
|
|
288
|
+
"(the Theming guide, \"Color scheme\")", :cyan
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# poetry_optimistic_form reconciles failures via a Turbo refresh, which
|
|
292
|
+
# must MORPH to be seamless - two layout metas the install cannot add
|
|
293
|
+
# for the host (the redirect trap and server contract live in
|
|
294
|
+
# the doc).
|
|
295
|
+
# @api private
|
|
296
|
+
def announce_optimistic_form
|
|
297
|
+
say_status :note, "optimistic forms: add <meta name=\"turbo-refresh-method\" content=\"morph\"> " \
|
|
298
|
+
"+ <meta name=\"turbo-refresh-scroll\" content=\"preserve\"> to your layout " \
|
|
299
|
+
"<head> before using poetry_optimistic_form (the Optimistic Forms guide)", :cyan
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
private
|
|
303
|
+
|
|
304
|
+
def resolved_theme
|
|
305
|
+
@resolved_theme ||= options[:theme] || installed_theme || "default"
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Which theme fills the slot right now. Unreadable header (a
|
|
309
|
+
# hand-edited file, or an install predating theme selection) falls back
|
|
310
|
+
# to "default" WITH a warning - never silently.
|
|
311
|
+
def installed_theme
|
|
312
|
+
path = File.join(destination_root, STYLE_SLOT)
|
|
313
|
+
return nil unless File.exist?(path)
|
|
314
|
+
|
|
315
|
+
name = File.foreach(path).first.to_s[THEME_HEADER, 1]
|
|
316
|
+
if name.nil?
|
|
317
|
+
say_status :theme, "could not identify the installed theme from #{STYLE_SLOT} - " \
|
|
318
|
+
"installing \"default\" (pass --theme <name> to keep yours)", :yellow
|
|
319
|
+
elsif name != "default"
|
|
320
|
+
say_status :theme, "keeping installed theme #{name.inspect} (pass --theme to switch)", :cyan
|
|
321
|
+
end
|
|
322
|
+
name
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def charts_available?
|
|
326
|
+
defined?(Poetry::Charts::Engine) ? true : false
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def agent_available?
|
|
330
|
+
defined?(Poetry::Agent::Engine) ? true : false
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# poetry-agent's WebMCP runtime registers beside the controllers when
|
|
334
|
+
# the gem is bundled (the engine already pins @poetry/agent); without
|
|
335
|
+
# it, `webmcp:` opt-ins have nothing to register with. Private: Thor
|
|
336
|
+
# would otherwise expose an argument-taking method as a command.
|
|
337
|
+
def register_agent_runtime(index)
|
|
338
|
+
return unless agent_available?
|
|
339
|
+
|
|
340
|
+
inject_unless_present(index, <<~JS.strip)
|
|
341
|
+
import { registerPoetryAgent } from "@poetry/agent"
|
|
342
|
+
registerPoetryAgent(application)
|
|
343
|
+
JS
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def ui_theme_path
|
|
347
|
+
Poetry::Ui.root.join("themes/#{resolved_theme}.css")
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def charts_theme_path
|
|
351
|
+
Poetry::Charts.root.join("themes/#{resolved_theme}.css")
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# The idempotency lives in the file-mutation primitive, not the
|
|
355
|
+
# generator: appending is a no-op when
|
|
356
|
+
# the line is already present.
|
|
357
|
+
def inject_unless_present(relative, line)
|
|
358
|
+
path = File.join(destination_root, relative)
|
|
359
|
+
return if File.exist?(path) && File.read(path).include?(line)
|
|
360
|
+
|
|
361
|
+
append_to_file relative, "#{line}\n"
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module Poetry
|
|
6
|
+
module Generators
|
|
7
|
+
# `rails g poetry:pagination [kaminari|pagy|will_paginate]` - copies a
|
|
8
|
+
# poetry adapter for the host's paginator(s) as OWNED host-app code
|
|
9
|
+
# (the copied-source doctrine; poetry:diff tracks drift). No argument:
|
|
10
|
+
# every paginator loaded in this app gets its adapter.
|
|
11
|
+
#
|
|
12
|
+
# The doctrine baked into every adapter: poetry owns the window
|
|
13
|
+
# (siblings/edges compute the visible pages) - the paginator's own
|
|
14
|
+
# window options deliberately do not apply, so pagination looks the
|
|
15
|
+
# same whichever gem drives it.
|
|
16
|
+
#
|
|
17
|
+
# @example
|
|
18
|
+
# bin/rails g poetry:pagination pagy
|
|
19
|
+
class PaginationGenerator < Rails::Generators::Base
|
|
20
|
+
source_root File.expand_path("templates", __dir__)
|
|
21
|
+
|
|
22
|
+
# Per-paginator adapter wiring: how to detect the gem, which
|
|
23
|
+
# template to copy, and where it lands.
|
|
24
|
+
ADAPTERS = {
|
|
25
|
+
"kaminari" => { detect: -> { defined?(::Kaminari) },
|
|
26
|
+
template: "kaminari_paginator.html.erb",
|
|
27
|
+
destination: "app/views/kaminari/_paginator.html.erb" },
|
|
28
|
+
"pagy" => { detect: -> { defined?(::Pagy) },
|
|
29
|
+
template: "poetry_pagy_helper.rb",
|
|
30
|
+
destination: "app/helpers/poetry_pagy_helper.rb" },
|
|
31
|
+
"will_paginate" => { detect: -> { defined?(::WillPaginate) },
|
|
32
|
+
template: "poetry_link_renderer.rb",
|
|
33
|
+
destination: "app/lib/poetry_link_renderer.rb" }
|
|
34
|
+
}.freeze
|
|
35
|
+
|
|
36
|
+
argument :paginator, type: :string, required: false,
|
|
37
|
+
banner: "kaminari|pagy|will_paginate",
|
|
38
|
+
desc: "the paginator to adapt (omit to detect every installed one)"
|
|
39
|
+
|
|
40
|
+
# Step: copies the adapter(s) for the requested or detected
|
|
41
|
+
# paginator(s).
|
|
42
|
+
# @api private
|
|
43
|
+
def install_adapters
|
|
44
|
+
names = requested_adapters
|
|
45
|
+
if names.empty?
|
|
46
|
+
say_status :skip, "no paginator detected (kaminari / pagy / will_paginate) - " \
|
|
47
|
+
"add one to the Gemfile first, or name it explicitly", :yellow
|
|
48
|
+
return
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
names.each do |name|
|
|
52
|
+
spec = ADAPTERS.fetch(name)
|
|
53
|
+
copy_file spec[:template], spec[:destination]
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def requested_adapters
|
|
60
|
+
if paginator.present?
|
|
61
|
+
unless ADAPTERS.key?(paginator)
|
|
62
|
+
raise Thor::Error, "unknown paginator #{paginator.inspect} - " \
|
|
63
|
+
"one of: #{ADAPTERS.keys.join(", ")}"
|
|
64
|
+
end
|
|
65
|
+
unless ADAPTERS.fetch(paginator)[:detect].call
|
|
66
|
+
raise Thor::Error, "#{paginator} is not loaded in this app - add the gem, bundle, and re-run"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
[paginator]
|
|
70
|
+
else
|
|
71
|
+
ADAPTERS.select { |_name, spec| spec[:detect].call }.keys
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<%# generated by `bin/rails g poetry:pagination kaminari` - this file is
|
|
2
|
+
yours: edit freely. ONE monolithic template replaces kaminari's seven
|
|
3
|
+
theme partials. page_url_for (via a bare Tag) honors param_name (incl.
|
|
4
|
+
nested), the canonical param-less page 1, and kaminari's param
|
|
5
|
+
blocklist. (No paginator.render block here: its method_missing
|
|
6
|
+
delegation drops Ruby keyword arguments - call helpers directly.)
|
|
7
|
+
|
|
8
|
+
Doctrine: poetry owns the window - kaminari's window:/outer_window:
|
|
9
|
+
options do not apply. Pass poetry options straight through paginate:
|
|
10
|
+
paginate @records, siblings: 2, edges: :arrows
|
|
11
|
+
(unrecognized paginate options arrive here as locals). The
|
|
12
|
+
total_pages guard mirrors kaminari's own nil-at-one-page behavior. %>
|
|
13
|
+
<% if total_pages > 1 %>
|
|
14
|
+
<%# URL duty rides a bare Tag (the abstract base with public
|
|
15
|
+
page_url_for): released kaminari's Paginator skips Tag#initialize,
|
|
16
|
+
so page_url_for only works on the Paginator on unreleased master.
|
|
17
|
+
The Tag inherits param_name/params from the paginate call's options
|
|
18
|
+
(they arrive here as locals). %>
|
|
19
|
+
<% url_tag = Kaminari::Helpers::Tag.new(
|
|
20
|
+
self, **{ params: local_assigns[:params],
|
|
21
|
+
param_name: local_assigns[:param_name] }.compact) %>
|
|
22
|
+
<%= poetry_pagination(
|
|
23
|
+
current: current_page.to_i,
|
|
24
|
+
total: total_pages,
|
|
25
|
+
path: ->(page) { url_tag.page_url_for(page) },
|
|
26
|
+
**local_assigns.slice(:siblings, :edges, :pages, :current_variant,
|
|
27
|
+
:label, :previous_label, :next_label).compact
|
|
28
|
+
) %>
|
|
29
|
+
<% end %>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# generated by `bin/rails g poetry:pagination will_paginate` - this file is
|
|
4
|
+
# yours: edit freely. Usage (the renderer: option per call - will_paginate
|
|
5
|
+
# deprecates the global default):
|
|
6
|
+
#
|
|
7
|
+
# <%= will_paginate @records, renderer: PoetryLinkRenderer %>
|
|
8
|
+
#
|
|
9
|
+
# to_html is replaced wholesale (the upstream comment invites it); the
|
|
10
|
+
# inherited url(page) keeps will_paginate's GET-param merging and nested
|
|
11
|
+
# param_name support. Doctrine: poetry owns the window - inner_window/
|
|
12
|
+
# outer_window do not apply; will_paginate's container options are
|
|
13
|
+
# absorbed by poetry's own <nav> landmark. Upstream behavior kept: the
|
|
14
|
+
# helper returns nil when total_pages <= 1 (this class is never called).
|
|
15
|
+
#
|
|
16
|
+
# Note: will_paginate itself is in maintenance mode (no new features or
|
|
17
|
+
# releases since mid-2024). This adapter supports apps that already use
|
|
18
|
+
# it; for a new project, prefer kaminari or pagy.
|
|
19
|
+
|
|
20
|
+
# will_paginate wires its ActionView integration on_load(:action_view);
|
|
21
|
+
# eager-loading contexts (generators, some rake tasks) can autoload this
|
|
22
|
+
# class before that hook fires, so pull the superclass in explicitly.
|
|
23
|
+
require "will_paginate/view_helpers/action_view"
|
|
24
|
+
|
|
25
|
+
class PoetryLinkRenderer < WillPaginate::ActionView::LinkRenderer
|
|
26
|
+
def to_html
|
|
27
|
+
@template.poetry_pagination(
|
|
28
|
+
current: @collection.current_page.to_i,
|
|
29
|
+
total: @collection.total_pages,
|
|
30
|
+
path: ->(page) { url(page) },
|
|
31
|
+
**(@options[:poetry] || {})
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# generated by `bin/rails g poetry:pagination pagy` - this file is yours:
|
|
4
|
+
# edit freely. Usage, anywhere a view holds a @pagy:
|
|
5
|
+
#
|
|
6
|
+
# <%= poetry_pagy_nav(@pagy) %>
|
|
7
|
+
#
|
|
8
|
+
# Doctrine: poetry owns the window (siblings:/edges: options here) -
|
|
9
|
+
# pagy's slots: does not apply. Mirrors the other paginators' behavior of
|
|
10
|
+
# rendering nothing at a single page. Needs pagy >= 43 (the leap-version
|
|
11
|
+
# redesign: instance-method navs, page_url); pagy's *_js navs are
|
|
12
|
+
# deliberately not adapted - their token protocol couples to pagy.js.
|
|
13
|
+
module PoetryPagyHelper
|
|
14
|
+
def poetry_pagy_nav(pagy, **options)
|
|
15
|
+
unless Pagy::VERSION.to_i >= 43
|
|
16
|
+
raise "poetry_pagy_nav needs pagy >= 43 (found #{Pagy::VERSION}) - " \
|
|
17
|
+
"the pre-43 extras API is a different world"
|
|
18
|
+
end
|
|
19
|
+
return "".html_safe if pagy.last <= 1
|
|
20
|
+
|
|
21
|
+
poetry_pagination(
|
|
22
|
+
current: pagy.page.to_i,
|
|
23
|
+
total: pagy.last,
|
|
24
|
+
path: ->(page) { pagy.page_url(page) },
|
|
25
|
+
**options
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
end
|