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,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# A streaming-aware chat transcript scroller.
|
|
6
|
+
module MessageScroller
|
|
7
|
+
# A scrollable chat transcript that follows the newest message
|
|
8
|
+
# while streaming, releases when the reader scrolls up, and offers
|
|
9
|
+
# a jump-to-latest button. Without JavaScript it is a plain
|
|
10
|
+
# scrollable region, fully readable.
|
|
11
|
+
#
|
|
12
|
+
# The content element is the Turbo Stream append target (stable
|
|
13
|
+
# dom id "<id>-messages"); rows are poetry_message_scroller_item
|
|
14
|
+
# wrappers keyed by message id. History prepends keep the reading
|
|
15
|
+
# position; a row rendered with anchor: true becomes the held
|
|
16
|
+
# reading line.
|
|
17
|
+
#
|
|
18
|
+
# @example A chat transcript
|
|
19
|
+
# render Poetry::Ui::MessageScroller::Component.new(id: "chat") do
|
|
20
|
+
# # poetry_message_scroller_item rows
|
|
21
|
+
# end
|
|
22
|
+
class Component < Poetry::Core::Component
|
|
23
|
+
# The closed vocabulary for the default_scroll_position axis.
|
|
24
|
+
SCROLL_POSITIONS = %i[start end last-anchor].freeze
|
|
25
|
+
|
|
26
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
27
|
+
AGENT_RULES = [
|
|
28
|
+
"Stream by UPDATING a row's text (morph/replace) - appending nodes per token re-announces the row to AT.",
|
|
29
|
+
"Rows are poetry_message_scroller_item(id: message.id) - the id is how anchoring and Streams find them.",
|
|
30
|
+
"Append new turns with a Turbo Stream targeting the content element's dom id.",
|
|
31
|
+
"History loads PREPEND into the content element - the controller preserves the reading position.",
|
|
32
|
+
"Never nest a second scroll container inside the viewport."
|
|
33
|
+
].freeze
|
|
34
|
+
|
|
35
|
+
use_stimulus do
|
|
36
|
+
on :root do
|
|
37
|
+
controller :message_scroller do
|
|
38
|
+
register
|
|
39
|
+
value :auto_scroll
|
|
40
|
+
value :default_scroll_position
|
|
41
|
+
value :preserve_scroll_on_prepend
|
|
42
|
+
value :track_visibility
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
on :viewport do
|
|
46
|
+
controller(:message_scroller) { target :viewport }
|
|
47
|
+
end
|
|
48
|
+
on :content do
|
|
49
|
+
controller(:message_scroller) { target :content }
|
|
50
|
+
end
|
|
51
|
+
on :spacer do
|
|
52
|
+
controller(:message_scroller) { target :spacer }
|
|
53
|
+
end
|
|
54
|
+
# The jump affordance: a bare descriptor (element-default click)
|
|
55
|
+
# plus the button target, forwarded into Button kwargs.
|
|
56
|
+
on :jump_button do
|
|
57
|
+
controller :message_scroller do
|
|
58
|
+
target :button
|
|
59
|
+
action :scroll_to_end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
option :id, :string, required: true,
|
|
65
|
+
doc: "The transcript's stable identifier - the content element renders dom id " \
|
|
66
|
+
"\"<id>-messages\" for Turbo Streams to target."
|
|
67
|
+
option :auto_scroll, :boolean, default: true,
|
|
68
|
+
doc: "Follows the newest message while the reader sits at the bottom; " \
|
|
69
|
+
"scrolling up releases the follow."
|
|
70
|
+
option :default_scroll_position, :symbol, default: :end,
|
|
71
|
+
doc: "Where the viewport lands on connect: the newest message " \
|
|
72
|
+
"(:end), the oldest (:start), or the last anchor: true row " \
|
|
73
|
+
"(:\"last-anchor\")."
|
|
74
|
+
option :preserve_scroll_on_prepend, :boolean, default: true,
|
|
75
|
+
doc: "Keeps the reading position stable when history prepends " \
|
|
76
|
+
"into the content element."
|
|
77
|
+
option :track_visibility, :boolean, default: false,
|
|
78
|
+
doc: "Opt-in observation of which rows are on screen - emits a " \
|
|
79
|
+
"visibility event as the visible set changes."
|
|
80
|
+
option :jump_button, :boolean, default: true,
|
|
81
|
+
doc: "Renders the floating jump-to-latest button (shown once the reader " \
|
|
82
|
+
"leaves the bottom)."
|
|
83
|
+
|
|
84
|
+
validates :default_scroll_position, inclusion: { in: SCROLL_POSITIONS }
|
|
85
|
+
|
|
86
|
+
part "message-scroller", "The transcript root the controller drives - runtime " \
|
|
87
|
+
"scroll state is mirrored here",
|
|
88
|
+
states: {
|
|
89
|
+
"data-mode" => { condition: "always once connected - the 4-state machine",
|
|
90
|
+
values: %w[following-bottom free-scrolling
|
|
91
|
+
anchored-to-message settling-jump] },
|
|
92
|
+
"data-scrollable" => "overflow exists - carries which edges have room " \
|
|
93
|
+
"(start, end, or both as a space-separated pair)",
|
|
94
|
+
"data-autoscrolling" => "a programmatic scroll is settling - the " \
|
|
95
|
+
"follow-bottom release is suppressed while set"
|
|
96
|
+
}
|
|
97
|
+
part "message-scroller-viewport", "The native scroll region (role=region, " \
|
|
98
|
+
"focusable) - the controller mirrors the same " \
|
|
99
|
+
"runtime attributes here",
|
|
100
|
+
states: {
|
|
101
|
+
"data-scrollable" => "overflow exists - the same edge tokens as the root",
|
|
102
|
+
"data-autoscrolling" => "a programmatic scroll is settling"
|
|
103
|
+
}
|
|
104
|
+
part "message-scroller-content", "The row container and Turbo Stream append target " \
|
|
105
|
+
"(stable dom id <id>-messages); role=log announces " \
|
|
106
|
+
"additions"
|
|
107
|
+
part "message-scroller-item", "One transcript row (poetry_message_scroller_item) - " \
|
|
108
|
+
"the id is how anchoring and Streams find it",
|
|
109
|
+
states: {
|
|
110
|
+
"data-message-id" => "always - the row's message id",
|
|
111
|
+
"data-scroll-anchor" => "anchor: true - the turn the controller holds at " \
|
|
112
|
+
"the reading line"
|
|
113
|
+
}
|
|
114
|
+
part "message-scroller-spacer", "Tail spacer faking scroll room below a short " \
|
|
115
|
+
"anchored turn - hidden at height 0"
|
|
116
|
+
|
|
117
|
+
# @api private
|
|
118
|
+
def root_attributes
|
|
119
|
+
html_attributes.merge_if_not_set(
|
|
120
|
+
{ "data-slot" => "message-scroller" }
|
|
121
|
+
.merge(stimulus_attributes_for(:root))
|
|
122
|
+
.merge(component_data_attributes)
|
|
123
|
+
)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# @api private
|
|
127
|
+
def viewport_attributes
|
|
128
|
+
{
|
|
129
|
+
"class" => css(:viewport), "data-slot" => "message-scroller-viewport",
|
|
130
|
+
"role" => "region", "tabindex" => "0",
|
|
131
|
+
"aria-label" => t("poetry.message_scroller.region")
|
|
132
|
+
}.merge(stimulus_attributes_for(:viewport))
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# @api private
|
|
136
|
+
def content_attributes
|
|
137
|
+
{
|
|
138
|
+
"id" => "#{id}-messages", "class" => css(:content),
|
|
139
|
+
"data-slot" => "message-scroller-content",
|
|
140
|
+
"role" => "log", "aria-relevant" => "additions"
|
|
141
|
+
}.merge(stimulus_attributes_for(:content))
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# @api private
|
|
145
|
+
def spacer_attributes
|
|
146
|
+
{ "data-slot" => "message-scroller-spacer", "aria-hidden" => "true", "hidden" => true }
|
|
147
|
+
.merge(stimulus_attributes_for(:spacer))
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# @api private
|
|
151
|
+
def button_attributes
|
|
152
|
+
{
|
|
153
|
+
class: css(:button),
|
|
154
|
+
data: { slot: "message-scroller-button", direction: "end", active: "false" },
|
|
155
|
+
tabindex: "-1"
|
|
156
|
+
}.merge(stimulus_attributes_for(:jump_button))
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
private :root_attributes, :viewport_attributes, :content_attributes, :spacer_attributes, :button_attributes
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module MessageScroller
|
|
6
|
+
# The MessageScroller preview - a bounded transcript frame (the
|
|
7
|
+
# geometry behaviors need the browser loop; previews cover markup).
|
|
8
|
+
class Preview < Poetry::Core::Preview::Base
|
|
9
|
+
def default
|
|
10
|
+
render_component(id: "demo", class: "h-80 rounded-lg border") do
|
|
11
|
+
safe_join(Array.new(12) { |i| item("m#{i}") { row(i) } })
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def without_jump_button
|
|
16
|
+
render_component(id: "plain", jump_button: false, class: "h-60 rounded-lg border") do
|
|
17
|
+
item("only") { row(0) }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def item(id, &)
|
|
24
|
+
tag.div(class: Style.css(:item), data: { slot: "message-scroller-item", "message-id": id }, &)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def row(index)
|
|
28
|
+
tag.div("Message #{index + 1}", class: "rounded-xl bg-muted px-3 py-2 w-fit")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module MessageScroller
|
|
6
|
+
# Re-expressed through the cn-* theme layer - minimally: the
|
|
7
|
+
# 4-state scroll machine's whole surface is machinery (viewport
|
|
8
|
+
# containment/scrollbar choreography, row content-visibility, the
|
|
9
|
+
# jump button's show/hide translate dance - upstream keeps every one
|
|
10
|
+
# of those inline too). Only the row rhythm is design: gap-8 rides
|
|
11
|
+
# .cn-message-scroller-content.
|
|
12
|
+
class Style < Poetry::Core::Style
|
|
13
|
+
# Source also stamps a group/message-scroller named-group marker;
|
|
14
|
+
# dropped until a dictionary consumer references it - an unconsumed
|
|
15
|
+
# named group never reaches the compiled CSS, and the verify gate
|
|
16
|
+
# (rightly) rejects classes no build can produce.
|
|
17
|
+
base "relative flex size-full min-h-0 flex-col overflow-hidden group/message-scroller"
|
|
18
|
+
|
|
19
|
+
element :viewport, "size-full min-h-0 min-w-0 scroll-fade-b scrollbar-thin scrollbar-gutter-stable " \
|
|
20
|
+
"overflow-y-auto overscroll-contain contain-content data-autoscrolling:scrollbar-none"
|
|
21
|
+
|
|
22
|
+
element :content, "cn-message-scroller-content flex h-max min-h-full flex-col"
|
|
23
|
+
|
|
24
|
+
element :item, "min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]"
|
|
25
|
+
|
|
26
|
+
element :button, "absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground " \
|
|
27
|
+
"transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground " \
|
|
28
|
+
"data-[active=false]:pointer-events-none data-[active=false]:scale-95 " \
|
|
29
|
+
"data-[active=false]:opacity-0 data-[active=false]:duration-400 " \
|
|
30
|
+
"data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] " \
|
|
31
|
+
"data-[active=true]:translate-y-0 data-[active=true]:scale-100 " \
|
|
32
|
+
"data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] " \
|
|
33
|
+
"data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full " \
|
|
34
|
+
"data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full " \
|
|
35
|
+
"rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Labeled facts about one record, as a description list.
|
|
6
|
+
module MetadataList
|
|
7
|
+
# Labeled facts about one record - a real description list (<dl>)
|
|
8
|
+
# for detail pages, in one or more columns, with each label above
|
|
9
|
+
# its value (vertical) or beside it (horizontal). Values compose
|
|
10
|
+
# freely: text, a Badge, a Link, a Timestamp.
|
|
11
|
+
#
|
|
12
|
+
# @example A record's fact sheet
|
|
13
|
+
# render Poetry::Ui::MetadataList::Component.new(columns: :two) do |list|
|
|
14
|
+
# list.with_item(label: "Status") { "Active" }
|
|
15
|
+
# list.with_item(label: "Owner") { "Ada Lovelace" }
|
|
16
|
+
# end
|
|
17
|
+
class Component < Poetry::Core::Component
|
|
18
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
19
|
+
AGENT_RULES = [
|
|
20
|
+
"Record facts on a detail page belong in a MetadataList - never a hand-rolled grid of " \
|
|
21
|
+
"label/value divs (this is the <dl> the page owes its readers).",
|
|
22
|
+
"Each with_item takes label: and the value as its block - values compose freely " \
|
|
23
|
+
"(text, a Badge, a Link, a Timestamp).",
|
|
24
|
+
"columns: :two / :three spread the facts on wide viewports; orientation: :horizontal " \
|
|
25
|
+
"puts labels beside values (the classic key/value sheet) - pick one per surface.",
|
|
26
|
+
"For editable facts pair each value with its edit affordance inside the item block; " \
|
|
27
|
+
"the list itself stays read-only vocabulary."
|
|
28
|
+
].freeze
|
|
29
|
+
|
|
30
|
+
# Slots the component cannot render without; static checks read this without rendering.
|
|
31
|
+
REQUIRED_SLOTS = { item: "at least one item (label: plus the value block)" }.freeze
|
|
32
|
+
|
|
33
|
+
renders_many :items,
|
|
34
|
+
doc: "The facts. Each takes label: (the fact's name, the <dt>) and the value as its block (the " \
|
|
35
|
+
"<dd>).",
|
|
36
|
+
renders: lambda { |label:, **options, &block|
|
|
37
|
+
# class: merges through the dictionary (caller classes win on
|
|
38
|
+
# conflicts) - a plain hash merge would REPLACE css(:item).
|
|
39
|
+
item_class = css(:item, class: options.delete(:class))
|
|
40
|
+
content_tag(:div, { "data-slot" => "metadata-list-item", class: item_class }.merge(options)) do
|
|
41
|
+
safe_join([
|
|
42
|
+
content_tag(:dt, label, "data-slot" => "metadata-list-label", class: css(:label)),
|
|
43
|
+
content_tag(:dd, { "data-slot" => "metadata-list-value", class: css(:value) },
|
|
44
|
+
&block)
|
|
45
|
+
])
|
|
46
|
+
end
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
style :orientation, default: :vertical, variants: %i[vertical horizontal],
|
|
50
|
+
doc: "Label placement - above the value, or beside it for the classic key/value sheet."
|
|
51
|
+
style :columns, default: :one, variants: %i[one two three],
|
|
52
|
+
doc: "How many columns the facts spread across on wide viewports."
|
|
53
|
+
|
|
54
|
+
part "metadata-list", "The <dl> root - the record's fact sheet",
|
|
55
|
+
states: {
|
|
56
|
+
"data-orientation" => { condition: "always - label placement",
|
|
57
|
+
values: %w[vertical horizontal] },
|
|
58
|
+
"data-columns" => { condition: "always - the column count word",
|
|
59
|
+
values: %w[one two three] }
|
|
60
|
+
}
|
|
61
|
+
part "metadata-list-item", "One fact group (a <div> holding its <dt>/<dd> pair)"
|
|
62
|
+
part "metadata-list-label", "The fact's name (<dt>) - muted, small"
|
|
63
|
+
part "metadata-list-value", "The fact's value (<dd>) - composes text, badges, links"
|
|
64
|
+
|
|
65
|
+
# Enforces the required item slot.
|
|
66
|
+
# @api private
|
|
67
|
+
def before_render
|
|
68
|
+
raise ArgumentError, "MetadataList requires at least one with_item" unless items?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @api private
|
|
72
|
+
def call
|
|
73
|
+
content_tag(:dl, safe_join(items.map(&:to_s)), **root_attributes.to_attributes)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @api private
|
|
77
|
+
def root_attributes
|
|
78
|
+
html_attributes.merge_if_not_set(
|
|
79
|
+
{ "data-slot" => "metadata-list", "data-orientation" => orientation,
|
|
80
|
+
"data-columns" => columns }.merge(component_data_attributes)
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private :root_attributes
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module MetadataList
|
|
6
|
+
class Preview < Poetry::Core::Preview::Base
|
|
7
|
+
def default
|
|
8
|
+
render_component do |list|
|
|
9
|
+
list.with_item(label: "Status") { "Active" }
|
|
10
|
+
list.with_item(label: "Owner") { "Ada Lovelace" }
|
|
11
|
+
list.with_item(label: "Created") { "June 12, 2026" }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def two_columns
|
|
16
|
+
render_component(columns: :two) do |list|
|
|
17
|
+
list.with_item(label: "Invoice") { "INV-0042" }
|
|
18
|
+
list.with_item(label: "Amount") { "$1,250.00" }
|
|
19
|
+
list.with_item(label: "Due") { "July 31, 2026" }
|
|
20
|
+
list.with_item(label: "Method") { "ACH transfer" }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def horizontal
|
|
25
|
+
render_component(orientation: :horizontal) do |list|
|
|
26
|
+
list.with_item(label: "Environment") { "production" }
|
|
27
|
+
list.with_item(label: "Region") { "us-east-1" }
|
|
28
|
+
list.with_item(label: "Version") { "2.14.0" }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def three_columns
|
|
33
|
+
render_component(columns: :three) do |list|
|
|
34
|
+
list.with_item(label: "CPU") { "42%" }
|
|
35
|
+
list.with_item(label: "Memory") { "3.1 GB" }
|
|
36
|
+
list.with_item(label: "Disk") { "58%" }
|
|
37
|
+
list.with_item(label: "Region") { "us-east-1" }
|
|
38
|
+
list.with_item(label: "Uptime") { "14 days" }
|
|
39
|
+
list.with_item(label: "Status") { "Healthy" }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Values compose: a status Badge inside the <dd>.
|
|
44
|
+
def composed_values
|
|
45
|
+
render_component(columns: :two) do |list|
|
|
46
|
+
list.with_item(label: "Status") do
|
|
47
|
+
embed(Poetry::Ui::Badge::Component.new(variant: :success).with_content("Fulfilled"))
|
|
48
|
+
end
|
|
49
|
+
list.with_item(label: "Tracking") { "1Z 999 AA1 01" }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module MetadataList
|
|
6
|
+
# Utility-only (the Separator/Spinner rule): no upstream cn hook
|
|
7
|
+
# exists for a description list, so the surface is structural
|
|
8
|
+
# utilities on semantic tokens; data-slot selectors are the restyle
|
|
9
|
+
# seam. The horizontal orientation restyles the ITEMS from the root
|
|
10
|
+
# (a root descendant utility outranks the item's own class), so one
|
|
11
|
+
# attribute flip re-lays the whole sheet.
|
|
12
|
+
class Style < Poetry::Core::Style
|
|
13
|
+
base "grid gap-x-8 gap-y-4"
|
|
14
|
+
|
|
15
|
+
variant :columns, {
|
|
16
|
+
one: "grid-cols-1",
|
|
17
|
+
two: "grid-cols-1 sm:grid-cols-2",
|
|
18
|
+
three: "grid-cols-1 sm:grid-cols-3"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
variant :orientation, {
|
|
22
|
+
vertical: "",
|
|
23
|
+
horizontal: "[&_[data-slot=metadata-list-item]]:grid " \
|
|
24
|
+
"[&_[data-slot=metadata-list-item]]:grid-cols-[minmax(0,8rem)_1fr] " \
|
|
25
|
+
"[&_[data-slot=metadata-list-item]]:items-baseline " \
|
|
26
|
+
"[&_[data-slot=metadata-list-item]]:gap-x-4"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
element :item, "flex min-w-0 flex-col gap-1"
|
|
30
|
+
element :label, "text-sm text-muted-foreground"
|
|
31
|
+
element :value, "min-w-0 text-sm font-medium break-words"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# A quantity within a known range.
|
|
6
|
+
module Meter
|
|
7
|
+
# A QUANTITY within a known range - battery, disk usage, seats
|
|
8
|
+
# taken, password strength - never the progress of an operation
|
|
9
|
+
# over time (that is Progress; a meter has no indeterminate
|
|
10
|
+
# state). Renders role=meter with a visible caption (label:), a
|
|
11
|
+
# readout, and a filled track; visually it shares Progress's
|
|
12
|
+
# chrome, so themes style both together.
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# render Poetry::Ui::Meter::Component.new(value: 62, label: "Storage used")
|
|
16
|
+
class Component < Poetry::Core::Component
|
|
17
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
18
|
+
AGENT_RULES = [
|
|
19
|
+
"A quantity within a range is a Meter (disk, seats, strength); an operation's " \
|
|
20
|
+
"completion over time is Progress. There is NO indeterminate meter - unknown " \
|
|
21
|
+
"duration means Spinner.",
|
|
22
|
+
"label: is REQUIRED - the meter's accessible name and visible caption.",
|
|
23
|
+
"value_text: replaces the visible readout verbatim (\"3 of 4 seats\"); without it " \
|
|
24
|
+
"the readout shows the percentage of the RANGE. No aria-valuetext - ARIA 1.2 " \
|
|
25
|
+
"deprecated it on role=meter; aria-valuenow carries the value."
|
|
26
|
+
].freeze
|
|
27
|
+
|
|
28
|
+
option :value, :integer, required: true, doc: "The measured quantity, clamped into min:..max:."
|
|
29
|
+
option :min, :integer, default: 0, doc: "The range's lower bound."
|
|
30
|
+
option :max, :integer, default: 100, doc: "The range's upper bound - must exceed min:."
|
|
31
|
+
option :label, :string, required: true, doc: "The meter's accessible name and visible caption."
|
|
32
|
+
option :value_text, :string,
|
|
33
|
+
doc: "Verbatim human-readable value (\"3 of 4 seats\") replacing the percentage readout. Visible " \
|
|
34
|
+
"readout only - ARIA 1.2 deprecated aria-valuetext on role=meter, so aria-valuenow carries the " \
|
|
35
|
+
"value."
|
|
36
|
+
option :show_value, :boolean, default: true, doc: "Set false to hide the visible readout."
|
|
37
|
+
|
|
38
|
+
part "meter", "Root (role=meter, aria-value*, and the accessible name); label, " \
|
|
39
|
+
"readout, and track stack here"
|
|
40
|
+
part "meter-label", "The visible caption span (label:)"
|
|
41
|
+
part "meter-value", "The readout - value_text: verbatim, else the range percentage; " \
|
|
42
|
+
"renders unless show_value: false"
|
|
43
|
+
part "meter-track", "The full-width rail (Progress's cn chrome)"
|
|
44
|
+
part "meter-indicator", "The filled bar - inline width percentage of the range"
|
|
45
|
+
|
|
46
|
+
# Enforces the required label and a coherent range.
|
|
47
|
+
# @api private
|
|
48
|
+
def before_render
|
|
49
|
+
raise ArgumentError, "Meter requires label: (the meter's accessible name)" if label.blank?
|
|
50
|
+
raise ArgumentError, "Meter max: must exceed min:" unless max > min
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @api private
|
|
54
|
+
def call
|
|
55
|
+
content_tag(:div, root_attributes.to_attributes) do
|
|
56
|
+
safe_join([label_part, value_part, track].compact)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The fraction of the RANGE - (value - min)/(max - min), never the
|
|
61
|
+
# raw value.
|
|
62
|
+
# @api private
|
|
63
|
+
def percent
|
|
64
|
+
((clamped - min).to_f / (max - min) * 100).clamp(0, 100)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @api private
|
|
68
|
+
def readout
|
|
69
|
+
value_text.presence || "#{percent.round}%"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# The role is the single token "meter" - a two-token fallback
|
|
73
|
+
# ("meter progressbar") makes checkers treat the element as generic
|
|
74
|
+
# and flag every aria-value* attribute.
|
|
75
|
+
# @api private
|
|
76
|
+
def root_attributes
|
|
77
|
+
html_attributes.merge_if_not_set(
|
|
78
|
+
{
|
|
79
|
+
"data-slot" => "meter", "role" => "meter",
|
|
80
|
+
# No aria-valuetext: ARIA 1.2 deprecated it on role=meter -
|
|
81
|
+
# the visible readout carries the human string, aria-valuenow
|
|
82
|
+
# the value.
|
|
83
|
+
"aria-valuemin" => min, "aria-valuemax" => max, "aria-valuenow" => clamped,
|
|
84
|
+
"aria-label" => label
|
|
85
|
+
}.merge(component_data_attributes)
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
def clamped
|
|
92
|
+
value.clamp(min, max)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def label_part
|
|
96
|
+
content_tag(:span, label, "data-slot" => "meter-label", class: Progress::Style.css(:label))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def value_part
|
|
100
|
+
return unless show_value
|
|
101
|
+
|
|
102
|
+
content_tag(:span, readout, "data-slot" => "meter-value", class: Progress::Style.css(:value))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def track
|
|
106
|
+
content_tag(:div, "data-slot" => "meter-track", class: Progress::Style.css(:track)) do
|
|
107
|
+
content_tag(:div, nil, "data-slot" => "meter-indicator",
|
|
108
|
+
class: Progress::Style.css(:indicator),
|
|
109
|
+
style: "width: #{percent.round(4)}%")
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private :percent, :readout, :root_attributes
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Meter
|
|
6
|
+
class Preview < Poetry::Core::Preview::Base
|
|
7
|
+
def default
|
|
8
|
+
render_component(value: 62, label: "Storage used")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# value_text: replaces the readout AND aria-valuetext verbatim.
|
|
12
|
+
def with_value_text
|
|
13
|
+
render_component(value: 3, max: 4, label: "Seats", value_text: "3 of 4 seats")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# A non-zero minimum: the readout is the fraction of the RANGE.
|
|
17
|
+
def with_range
|
|
18
|
+
render_component(value: 210, min: 100, max: 300, label: "Battery voltage",
|
|
19
|
+
value_text: "210 V")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def without_readout
|
|
23
|
+
render_component(value: 45, label: "Password strength", show_value: false)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Meter
|
|
6
|
+
# Progress's chrome verbatim (the NumberField composition precedent):
|
|
7
|
+
# the template calls Progress::Style.css for track/indicator/label/
|
|
8
|
+
# value, so the themes' cn-progress-* rules dress meters too - zero
|
|
9
|
+
# new theme CSS, and a theme that restyles progress restyles meters
|
|
10
|
+
# with it. The root only stacks.
|
|
11
|
+
class Style < Poetry::Core::Style
|
|
12
|
+
base "flex flex-wrap gap-3"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|