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,154 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# ClipboardText family: a read-only value with one copy affordance.
|
|
6
|
+
module ClipboardText
|
|
7
|
+
# A read-only value with one copy affordance - API keys, install
|
|
8
|
+
# commands, resource IDs. The value renders in a readonly monospace
|
|
9
|
+
# input (selectable, never editable) with a trailing copy button.
|
|
10
|
+
# A successful copy stamps data-copied on the root for a moment, so
|
|
11
|
+
# the stacked copy/check glyphs swap in CSS, and announces itself
|
|
12
|
+
# to screen readers; the fallback copy path restores the user's own
|
|
13
|
+
# selection and focus.
|
|
14
|
+
#
|
|
15
|
+
# @example An install command with a copy button
|
|
16
|
+
# render Poetry::Ui::ClipboardText::Component.new(value: "gem install poetry-ui",
|
|
17
|
+
# label: "Install command")
|
|
18
|
+
class Component < Poetry::Core::Component
|
|
19
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
20
|
+
AGENT_RULES = [
|
|
21
|
+
"A read-only value with one copy affordance (poetry_clipboard_text) - API keys, install " \
|
|
22
|
+
"commands, IDs. Editable text is an Input; a secret that needs masking is a SensitiveInput.",
|
|
23
|
+
"value: is what SHOWS; text_to_copy: overrides what lands on the clipboard when the " \
|
|
24
|
+
"display truncates - never truncate the copied text itself.",
|
|
25
|
+
"Give it label: (or compose under a Field/Label) - the readonly input still needs its " \
|
|
26
|
+
"accessible name."
|
|
27
|
+
].freeze
|
|
28
|
+
|
|
29
|
+
use_stimulus do
|
|
30
|
+
on :root do
|
|
31
|
+
controller :clipboard_text do
|
|
32
|
+
register
|
|
33
|
+
value :message, from: :copied_message_text
|
|
34
|
+
value :text, from: :text_to_copy, if: -> { text_to_copy.present? }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
on :input do
|
|
38
|
+
controller(:clipboard_text) { target :input }
|
|
39
|
+
end
|
|
40
|
+
on :copy_button do
|
|
41
|
+
controller(:clipboard_text) { action :copy, on: :click }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
option :value, :string, required: true,
|
|
46
|
+
doc: "The displayed text - also what copies, unless text_to_copy: overrides it."
|
|
47
|
+
option :text_to_copy, :string,
|
|
48
|
+
doc: "Overrides what lands on the clipboard when the displayed value truncates: display short, copy " \
|
|
49
|
+
"full."
|
|
50
|
+
option :id, :string,
|
|
51
|
+
doc: "The readonly input's DOM id (auto-generated when omitted) - the Field/Label for= target."
|
|
52
|
+
option :label, :string, doc: "The readonly input's accessible name when no Label/Field association exists."
|
|
53
|
+
option :described_by, :string, doc: "Ids for the input's aria-describedby (hint or error text)."
|
|
54
|
+
option :disabled, :boolean, default: false, doc: "Disables the input and the copy button together."
|
|
55
|
+
|
|
56
|
+
part "clipboard-text", "Root - the controller rides here",
|
|
57
|
+
states: {
|
|
58
|
+
"data-copied" => "stamped for a beat after a successful copy (the stacked " \
|
|
59
|
+
"copy/check glyphs swap off it)"
|
|
60
|
+
}
|
|
61
|
+
part "clipboard-text-group", "The bordered field surface - InputGroup's chrome"
|
|
62
|
+
part "input-group-control", "The readonly mono <input> showing the value - selectable, " \
|
|
63
|
+
"never editable; InputGroup's control slot"
|
|
64
|
+
part "input-group-addon", "The trailing cell holding the copy affordance - InputGroup's " \
|
|
65
|
+
"addon vocabulary",
|
|
66
|
+
states: {
|
|
67
|
+
"data-align" => { condition: "always - inline-end holds the copy button",
|
|
68
|
+
values: %w[inline-end] }
|
|
69
|
+
}
|
|
70
|
+
# The copy affordance renders as a composed ghost Button carrying
|
|
71
|
+
# data-slot=clipboard-text-copy on Button's root - ownership
|
|
72
|
+
# attributes it to Button (the NumberField stepper precedent), so it
|
|
73
|
+
# is documented here in prose only: a REAL tab stop (copying is the
|
|
74
|
+
# component's primary action), aria-controls to the input, stacked
|
|
75
|
+
# copy/check glyphs inside.
|
|
76
|
+
|
|
77
|
+
# The readonly input's id (given or auto-generated).
|
|
78
|
+
# @api private
|
|
79
|
+
def control_id
|
|
80
|
+
@control_id ||= id.presence || poetry_instance_id("poetry-clipboard-text")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Attributes for the root wrapper.
|
|
84
|
+
# @api private
|
|
85
|
+
def root_attributes
|
|
86
|
+
attrs = {
|
|
87
|
+
"data-slot" => "clipboard-text",
|
|
88
|
+
"class" => css
|
|
89
|
+
}.merge(component_data_attributes)
|
|
90
|
+
html_attributes.merge_if_not_set(attrs.merge(stimulus_attributes_for(:root)))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Attributes for the bordered field surface.
|
|
94
|
+
# @api private
|
|
95
|
+
def group_attributes
|
|
96
|
+
{
|
|
97
|
+
"role" => "group",
|
|
98
|
+
"data-slot" => "clipboard-text-group",
|
|
99
|
+
"class" => InputGroup::Style.css
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Attributes for the trailing addon cell.
|
|
104
|
+
# @api private
|
|
105
|
+
def addon_attributes
|
|
106
|
+
{
|
|
107
|
+
"data-slot" => "input-group-addon",
|
|
108
|
+
"data-align" => "inline-end",
|
|
109
|
+
"class" => InputGroup::Style.css(:addon, class: InputGroup::Style.css(:addon_inline_end))
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Attributes for the readonly value input.
|
|
114
|
+
# @api private
|
|
115
|
+
def input_attributes
|
|
116
|
+
attrs = Poetry::Core::HTML::Attributes.new(
|
|
117
|
+
"type" => "text",
|
|
118
|
+
"readonly" => "",
|
|
119
|
+
"id" => control_id,
|
|
120
|
+
"value" => value,
|
|
121
|
+
"data-slot" => "input-group-control",
|
|
122
|
+
"class" => "#{Input::Style.css(class: InputGroup::Style.css(:control_input))} #{css(:input)}",
|
|
123
|
+
"autocomplete" => "off",
|
|
124
|
+
"spellcheck" => "false"
|
|
125
|
+
)
|
|
126
|
+
attrs["aria-label"] = label if label.present?
|
|
127
|
+
attrs["aria-describedby"] = described_by if described_by.present?
|
|
128
|
+
attrs["disabled"] = "" if disabled
|
|
129
|
+
attrs.merge!(stimulus_attributes_for(:input))
|
|
130
|
+
attrs
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# The copy affordance: a ghost icon Button, a real tab stop (it IS
|
|
134
|
+
# the component's action).
|
|
135
|
+
# @api private
|
|
136
|
+
def copy_button
|
|
137
|
+
Button::Component.new({
|
|
138
|
+
variant: :ghost, size: :"icon-xs", disabled: disabled,
|
|
139
|
+
label: t("poetry.clipboard_text.copy"),
|
|
140
|
+
class: InputGroup::Style.css(:button, class: InputGroup::Style.css(:button_icon_xs)),
|
|
141
|
+
"data-slot" => "clipboard-text-copy",
|
|
142
|
+
"aria-controls" => control_id
|
|
143
|
+
}.compact.merge(stimulus_attributes_for(:copy_button)))
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
private
|
|
147
|
+
|
|
148
|
+
def copied_message_text = t("poetry.clipboard_text.copied")
|
|
149
|
+
|
|
150
|
+
private :control_id, :root_attributes, :group_attributes, :addon_attributes, :input_attributes, :copy_button
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module ClipboardText
|
|
6
|
+
class Preview < Poetry::Core::Preview::Base
|
|
7
|
+
def default
|
|
8
|
+
render_component(value: "gem install poetry-ui", label: "Install command")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Display truncates, the clipboard gets the FULL value via
|
|
12
|
+
# text_to_copy (the ported source's textToCopy contract).
|
|
13
|
+
def truncated_copy
|
|
14
|
+
render_component(value: "pk_live_51Nx…9fQ2", label: "API key",
|
|
15
|
+
text_to_copy: "pk_live_51NxAbCdEfGhIjKlMnOpQrStUvWxYz0123456789fQ2")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def disabled
|
|
19
|
+
render_component(value: "rotated-out-key", label: "API key", disabled: true)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module ClipboardText
|
|
6
|
+
# Utility-only: InputGroup + Input + Button wear the chrome (the
|
|
7
|
+
# SearchField composition - zero new theme CSS). The input goes mono
|
|
8
|
+
# for value legibility; the stacked copy/check glyphs swap on the
|
|
9
|
+
# root's data-copied stamp (structural visibility, not design).
|
|
10
|
+
class Style < Poetry::Core::Style
|
|
11
|
+
base "flex w-full flex-col"
|
|
12
|
+
|
|
13
|
+
element :input, "font-mono"
|
|
14
|
+
|
|
15
|
+
element :icon_stack, "relative flex size-4 items-center justify-center"
|
|
16
|
+
element :icon_copy, "absolute inset-0 m-auto transition-all duration-200 " \
|
|
17
|
+
"[[data-copied]_&]:scale-0 [[data-copied]_&]:opacity-0"
|
|
18
|
+
element :icon_check, "absolute inset-0 m-auto scale-0 opacity-0 transition-all duration-200 " \
|
|
19
|
+
"[[data-copied]_&]:scale-100 [[data-copied]_&]:opacity-100"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<%# The pre/code nesting stays on one line - literal template whitespace
|
|
2
|
+
inside <pre> would render. %>
|
|
3
|
+
<%= content_tag(:div, **root_attributes.to_attributes) do %>
|
|
4
|
+
<%= content_tag(:pre, content_tag(:code, highlighted || code, **code_attributes.to_attributes), **Poetry::Core::HTML::Attributes.new(pre_attributes).to_attributes) %>
|
|
5
|
+
<% if copy %>
|
|
6
|
+
<%= render copy_button do %>
|
|
7
|
+
<span class="<%= css(:icon_stack) %>">
|
|
8
|
+
<%= render Poetry::Ui::Icon::Component.new(name: :copy, class: css(:icon_copy)) %>
|
|
9
|
+
<%= render Poetry::Ui::Icon::Component.new(name: :check, class: css(:icon_check)) %>
|
|
10
|
+
</span>
|
|
11
|
+
<% end %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% end %>
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# CodeBlock family: the server-highlighted code panel.
|
|
6
|
+
module CodeBlock
|
|
7
|
+
# A highlighted code panel rendered entirely at request time via
|
|
8
|
+
# the rouge gem. Rouge is a SOFT dependency - without it the same
|
|
9
|
+
# markup ships with plain escaped code. Line numbers are CSS
|
|
10
|
+
# counters, so they are excluded from selection and from copied
|
|
11
|
+
# text by construction; highlight_lines: tints rows via the
|
|
12
|
+
# theme's highlight hook; the syntax palette is seven --syntax-*
|
|
13
|
+
# vars each theme owns. copy: adds a copy button reading the
|
|
14
|
+
# rendered code itself.
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
# render Poetry::Ui::CodeBlock::Component.new(
|
|
18
|
+
# code: "puts \"hello\"", language: "ruby"
|
|
19
|
+
# )
|
|
20
|
+
class Component < Poetry::Core::Component
|
|
21
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
22
|
+
AGENT_RULES = [
|
|
23
|
+
"Blocks of code are a CodeBlock (poetry_code_block) - never a hand-rolled pre/code " \
|
|
24
|
+
"with utility classes; the syntax palette, line counters, and copy affordance ride it.",
|
|
25
|
+
"Highlighting needs `gem \"rouge\"` in the host Gemfile - without it the block renders " \
|
|
26
|
+
"plain (same markup, no colors). Inline code stays plain <code> typography.",
|
|
27
|
+
"highlight_lines: takes 1-based line numbers; line numbers are CSS counters and never " \
|
|
28
|
+
"pollute copied text."
|
|
29
|
+
].freeze
|
|
30
|
+
|
|
31
|
+
# The whole copy surface is copy:-gated - element conditions keep
|
|
32
|
+
# the wiring out of copy: false renders entirely.
|
|
33
|
+
use_stimulus do
|
|
34
|
+
on :root, if: :copy do
|
|
35
|
+
controller :clipboard_text do
|
|
36
|
+
register
|
|
37
|
+
value :message, from: :copied_message_text
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
on :source, if: :copy do
|
|
41
|
+
controller(:clipboard_text) { target :source }
|
|
42
|
+
end
|
|
43
|
+
on :copy_button do
|
|
44
|
+
controller(:clipboard_text) { action :copy, on: :click }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
option :code, :string, required: true, doc: "The source text to highlight - required."
|
|
49
|
+
option :language, :string, default: "text",
|
|
50
|
+
doc: "The lexer name (\"ruby\", \"js\", ...); unknown languages fall back to " \
|
|
51
|
+
"plain text."
|
|
52
|
+
option :label, :string,
|
|
53
|
+
doc: "The scroll region's accessible name; defaults to the localized \"Code\" (a focusable scrollable " \
|
|
54
|
+
"region must be named - axe)."
|
|
55
|
+
option :line_numbers, :boolean, default: false,
|
|
56
|
+
doc: "Renders CSS-counter line numbers - never part of selection or copied " \
|
|
57
|
+
"text."
|
|
58
|
+
option :highlight_lines, ActiveModel::Type::Value.new,
|
|
59
|
+
doc: "1-based line numbers to tint via the theme's highlight hook."
|
|
60
|
+
option :copy, :boolean, default: true, doc: "Renders the copy button in the panel's corner."
|
|
61
|
+
|
|
62
|
+
part "code-block", "Root - the syntax-palette surface (cn-code-block)",
|
|
63
|
+
states: {
|
|
64
|
+
"data-language" => "always - the lexer name, a styling/tooling hook",
|
|
65
|
+
"data-line-numbers" => "line_numbers: - turns on the ::before CSS counters",
|
|
66
|
+
"data-copied" => "copy: only - stamped for a beat after a successful copy " \
|
|
67
|
+
"(the clipboard-text engine)"
|
|
68
|
+
}
|
|
69
|
+
part "code-block-pre", "The scroll container - tabindex 0 + role region + label " \
|
|
70
|
+
"(a scrollable region must be keyboard-reachable and named)"
|
|
71
|
+
part "code-block-code", "The code element - rouge's .line/.hll spans and the seven " \
|
|
72
|
+
"--syntax-* token maps live under it; the copy affordance " \
|
|
73
|
+
"reads ITS textContent"
|
|
74
|
+
# The copy affordance renders as a composed ghost Button carrying
|
|
75
|
+
# data-slot=clipboard-text-copy on Button's root (the ClipboardText
|
|
76
|
+
# anatomy, prose not part): top-right of the panel, a real tab stop,
|
|
77
|
+
# stacked copy/check glyphs swapping on data-copied.
|
|
78
|
+
|
|
79
|
+
# The rouge-rendered (or plain-escaped) markup.
|
|
80
|
+
# @api private
|
|
81
|
+
def highlighted
|
|
82
|
+
@highlighted ||= CodeBlockHighlighter.highlight(
|
|
83
|
+
code, language: language, highlight_lines: highlight_lines || []
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Attributes for the panel root.
|
|
88
|
+
# @api private
|
|
89
|
+
def root_attributes
|
|
90
|
+
attrs = {
|
|
91
|
+
"data-slot" => "code-block",
|
|
92
|
+
"data-language" => language,
|
|
93
|
+
"class" => css
|
|
94
|
+
}.merge(component_data_attributes)
|
|
95
|
+
attrs["data-line-numbers"] = "" if line_numbers
|
|
96
|
+
html_attributes.merge_if_not_set(attrs.merge(stimulus_attributes_for(:root)))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Attributes for the scrollable <pre> region.
|
|
100
|
+
# @api private
|
|
101
|
+
def pre_attributes
|
|
102
|
+
{
|
|
103
|
+
"data-slot" => "code-block-pre",
|
|
104
|
+
"tabindex" => "0",
|
|
105
|
+
"role" => "region",
|
|
106
|
+
"aria-label" => label.presence || t("poetry.code_block.label"),
|
|
107
|
+
"class" => css(:pre)
|
|
108
|
+
}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Attributes for the <code> element.
|
|
112
|
+
# @api private
|
|
113
|
+
def code_attributes
|
|
114
|
+
attrs = Poetry::Core::HTML::Attributes.new(
|
|
115
|
+
"data-slot" => "code-block-code",
|
|
116
|
+
"class" => css(:code)
|
|
117
|
+
)
|
|
118
|
+
attrs.merge!(stimulus_attributes_for(:source))
|
|
119
|
+
attrs
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# The corner copy affordance: a ghost icon Button.
|
|
123
|
+
# @api private
|
|
124
|
+
def copy_button
|
|
125
|
+
Button::Component.new({
|
|
126
|
+
variant: :ghost, size: :"icon-xs",
|
|
127
|
+
label: t("poetry.clipboard_text.copy"),
|
|
128
|
+
class: css(:copy),
|
|
129
|
+
"data-slot" => "clipboard-text-copy"
|
|
130
|
+
}.merge(stimulus_attributes_for(:copy_button)))
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
private
|
|
134
|
+
|
|
135
|
+
def copied_message_text = t("poetry.clipboard_text.copied")
|
|
136
|
+
|
|
137
|
+
private :highlighted, :root_attributes, :pre_attributes, :code_attributes, :copy_button
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module CodeBlock
|
|
6
|
+
# The CodeBlock preview: highlighted Ruby, line numbers with .hll
|
|
7
|
+
# tints, and the copy-less variant.
|
|
8
|
+
class Preview < Poetry::Core::Preview::Base
|
|
9
|
+
RUBY_SAMPLE = <<~RUBY
|
|
10
|
+
class Invoice < ApplicationRecord
|
|
11
|
+
belongs_to :customer
|
|
12
|
+
|
|
13
|
+
# Only settled invoices count toward revenue.
|
|
14
|
+
scope :settled, -> { where(status: "settled") }
|
|
15
|
+
|
|
16
|
+
def total
|
|
17
|
+
line_items.sum(&:amount)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
RUBY
|
|
21
|
+
|
|
22
|
+
def default
|
|
23
|
+
render_component(code: RUBY_SAMPLE, language: "ruby", label: "Invoice model")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# CSS-counter line numbers (never in copied text) + .hll tints on
|
|
27
|
+
# the named lines.
|
|
28
|
+
def numbered_and_highlighted
|
|
29
|
+
render_component(code: RUBY_SAMPLE, language: "ruby", label: "Invoice model",
|
|
30
|
+
line_numbers: true, highlight_lines: [5, 7, 8, 9])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def without_copy
|
|
34
|
+
render_component(code: %(export POETRY_THEME=vega\nbin/rake test:visual), language: "shell",
|
|
35
|
+
label: "Gate commands", copy: false)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module CodeBlock
|
|
6
|
+
# The panel look, syntax palette values, .hll tint, and line-number
|
|
7
|
+
# chrome are theme-owned (cn-code-block + descendant rules, all nine
|
|
8
|
+
# themes); the dictionary carries the STRUCTURE - scroll container,
|
|
9
|
+
# counters, and the token map wiring rouge's classes to the seven
|
|
10
|
+
# --syntax-* vars the theme defines.
|
|
11
|
+
class Style < Poetry::Core::Style
|
|
12
|
+
base "cn-code-block group/code relative"
|
|
13
|
+
|
|
14
|
+
element :pre, "overflow-x-auto p-4 [counter-reset:line]"
|
|
15
|
+
|
|
16
|
+
# The token map: rouge's short classes -> the theme's syntax vars.
|
|
17
|
+
# .line blocks make .hll tints span the full row.
|
|
18
|
+
element :code, "block min-w-max font-mono text-sm [&_.line]:block " \
|
|
19
|
+
"[&_:is(.k,.kd,.kn,.kp,.kr,.kt,.kv)]:text-(--syntax-keyword) " \
|
|
20
|
+
"[&_:is(.kc,.l,.ld,.m,.mb,.mf,.mh,.mi,.il,.mo,.mx)]:text-(--syntax-constant) " \
|
|
21
|
+
"[&_:is(.sb,.bp,.ne,.nl,.py,.nv,.vc,.vg,.vi,.vm,.o,.ow)]:text-(--syntax-constant) " \
|
|
22
|
+
"[&_:is(.s,.sa,.sc,.dl,.sd,.s2,.se,.sh,.sx,.s1,.ss)]:text-(--syntax-string) " \
|
|
23
|
+
"[&_:is(.nb,.nc,.no,.nn)]:text-(--syntax-entity) " \
|
|
24
|
+
"[&_:is(.na,.nt,.sr)]:text-(--syntax-markup) " \
|
|
25
|
+
"[&_:is(.nd,.nf,.fm)]:text-(--syntax-function) " \
|
|
26
|
+
"[&_:is(.c,.ch,.cd,.cm,.cp,.cpf,.c1,.cs)]:text-(--syntax-comment)"
|
|
27
|
+
|
|
28
|
+
element :copy, "absolute top-2 end-2"
|
|
29
|
+
|
|
30
|
+
element :icon_stack, "relative flex size-4 items-center justify-center"
|
|
31
|
+
element :icon_copy, "absolute inset-0 m-auto transition-all duration-200 " \
|
|
32
|
+
"[[data-copied]_&]:scale-0 [[data-copied]_&]:opacity-0"
|
|
33
|
+
element :icon_check, "absolute inset-0 m-auto scale-0 opacity-0 transition-all duration-200 " \
|
|
34
|
+
"[[data-copied]_&]:scale-100 [[data-copied]_&]:opacity-100"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Collapsible family: the plain show/hide disclosure.
|
|
6
|
+
module Collapsible
|
|
7
|
+
# A disclosure: a trigger button that shows and hides one content
|
|
8
|
+
# panel. The server renders the initial open/closed state, the
|
|
9
|
+
# trigger mirrors aria-expanded, and closed content stays in the
|
|
10
|
+
# DOM (hidden) so it survives re-renders and stays findable -
|
|
11
|
+
# exit animations are awaited before hiding.
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# render Poetry::Ui::Collapsible::Component.new do |collapsible|
|
|
15
|
+
# collapsible.with_trigger { "Show details" }
|
|
16
|
+
# tag.div("Hidden until disclosed.")
|
|
17
|
+
# end
|
|
18
|
+
class Component < Poetry::Core::Component
|
|
19
|
+
include Poetry::Ui::ComposableTrigger
|
|
20
|
+
|
|
21
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
22
|
+
AGENT_RULES = [
|
|
23
|
+
ComposableTrigger::AGENT_RULE,
|
|
24
|
+
"The trigger is with_trigger { \"label\" } - a real button, wired for you (aria-expanded/controls).",
|
|
25
|
+
"Server-render the initial state via open: - never toggle data-open/data-closed by hand.",
|
|
26
|
+
"Content stays in the DOM when closed (hidden) - do not conditionally render it.",
|
|
27
|
+
"For URL-controlled disclosure without JS, render open: from params - the same markup serves both."
|
|
28
|
+
].freeze
|
|
29
|
+
|
|
30
|
+
# The required slots, stated statically so static checks can flag
|
|
31
|
+
# a missing trigger without rendering.
|
|
32
|
+
REQUIRED_SLOTS = { trigger: "the disclosure control" }.freeze
|
|
33
|
+
|
|
34
|
+
renders_one :trigger,
|
|
35
|
+
doc: "The disclosure control - a real button, wired for you (aria-expanded, aria-controls); " \
|
|
36
|
+
"options merge onto it.",
|
|
37
|
+
renders: lambda { |**options, &block|
|
|
38
|
+
attrs = {
|
|
39
|
+
type: "button", "data-slot" => "collapsible-trigger",
|
|
40
|
+
"aria-expanded" => open.to_s, "aria-controls" => content_id
|
|
41
|
+
}.merge(stimulus_attributes_for(:trigger))
|
|
42
|
+
composed_trigger(attrs, options, &block) ||
|
|
43
|
+
content_tag(:button, Poetry::Core::HTML::Attributes.merged(attrs, options), &block)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
use_stimulus do
|
|
47
|
+
on :root do
|
|
48
|
+
controller(:state) { register }
|
|
49
|
+
end
|
|
50
|
+
on :trigger do
|
|
51
|
+
controller :state do
|
|
52
|
+
target :trigger
|
|
53
|
+
action :toggle, on: :click
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
on :content do
|
|
57
|
+
controller(:state) { target :content }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
option :open, :boolean, default: false,
|
|
62
|
+
doc: "The server-rendered initial state; the trigger toggles it client-side."
|
|
63
|
+
|
|
64
|
+
part "collapsible", "The disclosure root - the state controller flips the pair here",
|
|
65
|
+
states: {
|
|
66
|
+
"data-open" => "expanded (server-rendered from open:; the controller flips the pair at runtime)",
|
|
67
|
+
"data-closed" => "collapsed (the server-rendered default)"
|
|
68
|
+
}
|
|
69
|
+
part "collapsible-trigger", "The disclosure button - mirrors aria-expanded",
|
|
70
|
+
states: {
|
|
71
|
+
"data-panel-open" => "its content is open (controller-written; " \
|
|
72
|
+
"absent while closed)"
|
|
73
|
+
}
|
|
74
|
+
part "collapsible-content", "The disclosure panel - stays in the DOM when closed (hidden) " \
|
|
75
|
+
"and rides the presence helper on exit",
|
|
76
|
+
states: {
|
|
77
|
+
"data-open" => "content is open or entering",
|
|
78
|
+
"data-closed" => "content is closed or animating out (hidden lands after the exit finishes)"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# A missing body yields a trigger disclosing an empty panel.
|
|
82
|
+
requires_content "the disclosed panel body"
|
|
83
|
+
|
|
84
|
+
# Enforces the required trigger and panel body.
|
|
85
|
+
# @api private
|
|
86
|
+
def before_render
|
|
87
|
+
raise ArgumentError, "Collapsible requires with_trigger (the disclosure control)" unless trigger?
|
|
88
|
+
|
|
89
|
+
ensure_content!
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# The state word behind the data-* stamps.
|
|
93
|
+
# @api private
|
|
94
|
+
def state
|
|
95
|
+
open ? "open" : "closed"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# The panel's id - the trigger's aria-controls target.
|
|
99
|
+
# @api private
|
|
100
|
+
def content_id
|
|
101
|
+
@content_id ||= "#{instance_id}-content"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Attributes for the disclosure root.
|
|
105
|
+
# @api private
|
|
106
|
+
def root_attributes
|
|
107
|
+
html_attributes.merge_if_not_set(
|
|
108
|
+
{ "data-slot" => "collapsible", "data-#{state}" => "" }
|
|
109
|
+
.merge(stimulus_attributes_for(:root))
|
|
110
|
+
.merge(component_data_attributes)
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Attributes for the content panel.
|
|
115
|
+
# @api private
|
|
116
|
+
def content_attributes
|
|
117
|
+
attrs = {
|
|
118
|
+
"id" => content_id, "data-slot" => "collapsible-content", "data-#{state}" => ""
|
|
119
|
+
}.merge(stimulus_attributes_for(:content))
|
|
120
|
+
attrs["hidden"] = true unless open
|
|
121
|
+
attrs
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
|
|
126
|
+
def instance_id
|
|
127
|
+
@instance_id ||= poetry_instance_id("poetry-collapsible")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private :state, :content_id, :root_attributes, :content_attributes
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Collapsible
|
|
6
|
+
# The Collapsible preview matrix.
|
|
7
|
+
class Preview < Poetry::Core::Preview::Base
|
|
8
|
+
def default
|
|
9
|
+
render_component do |collapsible|
|
|
10
|
+
collapsible.with_trigger(class: "text-sm font-medium underline-offset-4 hover:underline") { "Show details" }
|
|
11
|
+
tag.div("Hidden until disclosed.", class: "pt-2 text-sm text-muted-foreground")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initially_open
|
|
16
|
+
render_component(open: true) do |collapsible|
|
|
17
|
+
collapsible.with_trigger(class: "text-sm font-medium") { "Hide details" }
|
|
18
|
+
tag.div("Server-rendered open.", class: "pt-2 text-sm text-muted-foreground")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<%# The option union renders FIRST (into a capture) so the shared
|
|
2
|
+
OptionSet is populated - server-stable option ids assigned, the
|
|
3
|
+
initial highlight decided - before the native <select>, the trigger's
|
|
4
|
+
value display, and the input's aria-activedescendant derive from it:
|
|
5
|
+
one server-side truth, four surfaces (the Select + Command capture
|
|
6
|
+
patterns fused). %>
|
|
7
|
+
<% list_body = capture do %>
|
|
8
|
+
<% items.each do |item| %><%= item %><% end %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<%= content_tag(:div, **root_attributes.to_attributes) do %>
|
|
11
|
+
<%= native_select %>
|
|
12
|
+
<% if show_clear %>
|
|
13
|
+
<%# The clear anchor shrink-wraps the trigger (the root is full-width
|
|
14
|
+
block); the X rides as the trigger's IMMEDIATE next sibling - the
|
|
15
|
+
chevron-swap CSS keys on that adjacency. %>
|
|
16
|
+
<span class="<%= css(:clear_anchor) %>"><%= trigger_button %><%= clear_button %></span>
|
|
17
|
+
<% else %>
|
|
18
|
+
<%= multiple ? chips_frame : trigger_button %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<%= content_tag(:div, **Poetry::Core::HTML::Attributes.new(content_attributes).to_attributes) do %>
|
|
21
|
+
<% if multiple %>
|
|
22
|
+
<%# MULTIPLE: the popup holds ONLY the listbox (the input lives
|
|
23
|
+
inline in the chips frame; the command engine rides the ROOT so
|
|
24
|
+
it scopes over both - no command part in here). %>
|
|
25
|
+
<%= content_tag(:div, **Poetry::Core::HTML::Attributes.new(list_attributes).to_attributes) do %>
|
|
26
|
+
<%= empty_part %>
|
|
27
|
+
<%= loading_part %>
|
|
28
|
+
<%= list_body %>
|
|
29
|
+
<% end %>
|
|
30
|
+
<%= status_part %>
|
|
31
|
+
<% else %>
|
|
32
|
+
<%# The EMBEDDED Command anatomy (Command::Style + the engine
|
|
33
|
+
controller reused verbatim; chrome flattened - rounded/border ride
|
|
34
|
+
the content). %>
|
|
35
|
+
<%= content_tag(:div, **Poetry::Core::HTML::Attributes.new(command_attributes).to_attributes) do %>
|
|
36
|
+
<div data-slot="combobox-input-wrapper" class="<%= Poetry::Ui::Command::Style.css(:input_wrapper) %>">
|
|
37
|
+
<span data-slot="combobox-search-icon"><%= render(Poetry::Ui::Icon::Component.new(name: :search, class: Poetry::Ui::Command::Style.css(:search_icon))) %></span>
|
|
38
|
+
<%= tag.input(**Poetry::Core::HTML::Attributes.new(input_attributes).to_attributes) %>
|
|
39
|
+
</div>
|
|
40
|
+
<%= content_tag(:div, **Poetry::Core::HTML::Attributes.new(list_attributes).to_attributes) do %>
|
|
41
|
+
<%= empty_part %>
|
|
42
|
+
<%= loading_part %>
|
|
43
|
+
<%= list_body %>
|
|
44
|
+
<% end %>
|
|
45
|
+
<%= status_part %>
|
|
46
|
+
<% end %>
|
|
47
|
+
<% end %>
|
|
48
|
+
<% end %>
|
|
49
|
+
<% end %>
|