shadcn_view_component 0.3.3
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/CHANGELOG.md +255 -0
- data/MIT-LICENSE +20 -0
- data/README.md +604 -0
- data/app/assets/stylesheets/shadcn-themes.css +1075 -0
- data/app/assets/stylesheets/shadcn.css +853 -0
- data/app/components/shadcn/accordion/component.rb +44 -0
- data/app/components/shadcn/accordion/content/component.rb +44 -0
- data/app/components/shadcn/accordion/item/component.rb +41 -0
- data/app/components/shadcn/accordion/preview.rb +16 -0
- data/app/components/shadcn/accordion/previews/default.html.erb +10 -0
- data/app/components/shadcn/accordion/previews/multiple.html.erb +13 -0
- data/app/components/shadcn/accordion/trigger/component.rb +52 -0
- data/app/components/shadcn/alert/component.rb +52 -0
- data/app/components/shadcn/alert/preview.rb +11 -0
- data/app/components/shadcn/alert/previews/default.html.erb +8 -0
- data/app/components/shadcn/alert.rb +17 -0
- data/app/components/shadcn/alert_dialog/action/component.rb +35 -0
- data/app/components/shadcn/alert_dialog/cancel/component.rb +16 -0
- data/app/components/shadcn/alert_dialog/component.rb +20 -0
- data/app/components/shadcn/alert_dialog/content/component.rb +55 -0
- data/app/components/shadcn/alert_dialog/header/component.rb +33 -0
- data/app/components/shadcn/alert_dialog/preview.rb +16 -0
- data/app/components/shadcn/alert_dialog/previews/default.html.erb +13 -0
- data/app/components/shadcn/alert_dialog/previews/small_with_media.html.erb +38 -0
- data/app/components/shadcn/alert_dialog.rb +32 -0
- data/app/components/shadcn/application_view_component.rb +225 -0
- data/app/components/shadcn/application_view_component_preview.rb +8 -0
- data/app/components/shadcn/aspect_ratio/component.rb +34 -0
- data/app/components/shadcn/aspect_ratio/preview.rb +16 -0
- data/app/components/shadcn/aspect_ratio/previews/default.html.erb +5 -0
- data/app/components/shadcn/aspect_ratio/previews/ratios.html.erb +12 -0
- data/app/components/shadcn/attachment/action/component.rb +19 -0
- data/app/components/shadcn/attachment/component.rb +76 -0
- data/app/components/shadcn/attachment/media/component.rb +56 -0
- data/app/components/shadcn/attachment/preview.rb +11 -0
- data/app/components/shadcn/attachment/previews/default.html.erb +80 -0
- data/app/components/shadcn/attachment/trigger/component.rb +31 -0
- data/app/components/shadcn/attachment.rb +42 -0
- data/app/components/shadcn/avatar/component.rb +43 -0
- data/app/components/shadcn/avatar/fallback/component.rb +23 -0
- data/app/components/shadcn/avatar/image/component.rb +20 -0
- data/app/components/shadcn/avatar/preview.rb +11 -0
- data/app/components/shadcn/avatar/previews/default.html.erb +13 -0
- data/app/components/shadcn/avatar.rb +32 -0
- data/app/components/shadcn/badge/component.rb +57 -0
- data/app/components/shadcn/badge/preview.rb +11 -0
- data/app/components/shadcn/badge/previews/default.html.erb +5 -0
- data/app/components/shadcn/breadcrumb/component.rb +15 -0
- data/app/components/shadcn/breadcrumb/ellipsis/component.rb +28 -0
- data/app/components/shadcn/breadcrumb/page/component.rb +25 -0
- data/app/components/shadcn/breadcrumb/preview.rb +16 -0
- data/app/components/shadcn/breadcrumb/previews/custom_separator.html.erb +17 -0
- data/app/components/shadcn/breadcrumb/previews/default.html.erb +15 -0
- data/app/components/shadcn/breadcrumb/separator/component.rb +31 -0
- data/app/components/shadcn/breadcrumb.rb +18 -0
- data/app/components/shadcn/bubble/component.rb +90 -0
- data/app/components/shadcn/bubble/preview.rb +16 -0
- data/app/components/shadcn/bubble/previews/alignment.html.erb +33 -0
- data/app/components/shadcn/bubble/previews/default.html.erb +22 -0
- data/app/components/shadcn/bubble/reactions/component.rb +54 -0
- data/app/components/shadcn/bubble.rb +24 -0
- data/app/components/shadcn/button/component.rb +85 -0
- data/app/components/shadcn/button/preview.rb +31 -0
- data/app/components/shadcn/button/previews/default.html.erb +8 -0
- data/app/components/shadcn/button/previews/sizes.html.erb +5 -0
- data/app/components/shadcn/button/previews/variants.html.erb +5 -0
- data/app/components/shadcn/button_group/component.rb +53 -0
- data/app/components/shadcn/button_group/preview.rb +15 -0
- data/app/components/shadcn/button_group/previews/default.html.erb +18 -0
- data/app/components/shadcn/button_group/previews/vertical.html.erb +5 -0
- data/app/components/shadcn/button_group/separator/component.rb +30 -0
- data/app/components/shadcn/button_group/text/component.rb +20 -0
- data/app/components/shadcn/calendar/component.rb +558 -0
- data/app/components/shadcn/calendar/month.rb +74 -0
- data/app/components/shadcn/calendar/preview.rb +64 -0
- data/app/components/shadcn/calendar/previews/booked.html.erb +18 -0
- data/app/components/shadcn/calendar/previews/custom_cell_size.html.erb +11 -0
- data/app/components/shadcn/calendar/previews/date_and_time.html.erb +31 -0
- data/app/components/shadcn/calendar/previews/default.html.erb +8 -0
- data/app/components/shadcn/calendar/previews/dropdown_caption.html.erb +11 -0
- data/app/components/shadcn/calendar/previews/in_a_form.html.erb +8 -0
- data/app/components/shadcn/calendar/previews/presets.html.erb +20 -0
- data/app/components/shadcn/calendar/previews/range.html.erb +10 -0
- data/app/components/shadcn/calendar/previews/week_numbers.html.erb +8 -0
- data/app/components/shadcn/card/component.rb +24 -0
- data/app/components/shadcn/card/header/component.rb +26 -0
- data/app/components/shadcn/card/preview.rb +16 -0
- data/app/components/shadcn/card/previews/default.html.erb +18 -0
- data/app/components/shadcn/card/previews/image.html.erb +37 -0
- data/app/components/shadcn/card.rb +21 -0
- data/app/components/shadcn/carousel/component.rb +61 -0
- data/app/components/shadcn/carousel/content/component.rb +86 -0
- data/app/components/shadcn/carousel/item/component.rb +42 -0
- data/app/components/shadcn/carousel/next/component.rb +59 -0
- data/app/components/shadcn/carousel/preview.rb +22 -0
- data/app/components/shadcn/carousel/previews/default.html.erb +22 -0
- data/app/components/shadcn/carousel/previews/sizes.html.erb +42 -0
- data/app/components/shadcn/carousel/previews/vertical.html.erb +27 -0
- data/app/components/shadcn/carousel/previous/component.rb +59 -0
- data/app/components/shadcn/chart/area/component.rb +43 -0
- data/app/components/shadcn/chart/bar/component.rb +75 -0
- data/app/components/shadcn/chart/cartesian/component.rb +152 -0
- data/app/components/shadcn/chart/component.rb +124 -0
- data/app/components/shadcn/chart/focusable.rb +38 -0
- data/app/components/shadcn/chart/legend/component.rb +55 -0
- data/app/components/shadcn/chart/line/component.rb +50 -0
- data/app/components/shadcn/chart/pie/component.rb +169 -0
- data/app/components/shadcn/chart/plot.rb +147 -0
- data/app/components/shadcn/chart/preview.rb +45 -0
- data/app/components/shadcn/chart/previews/area.html.erb +31 -0
- data/app/components/shadcn/chart/previews/bar.html.erb +32 -0
- data/app/components/shadcn/chart/previews/bar_stacked.html.erb +30 -0
- data/app/components/shadcn/chart/previews/default.html.erb +30 -0
- data/app/components/shadcn/chart/previews/donut.html.erb +16 -0
- data/app/components/shadcn/chart/previews/line.html.erb +30 -0
- data/app/components/shadcn/chart/previews/percentages.html.erb +17 -0
- data/app/components/shadcn/chart/table/component.rb +75 -0
- data/app/components/shadcn/chart/tooltip/component.rb +111 -0
- data/app/components/shadcn/checkbox/component.rb +109 -0
- data/app/components/shadcn/checkbox/preview.rb +16 -0
- data/app/components/shadcn/checkbox/previews/default.html.erb +14 -0
- data/app/components/shadcn/checkbox/previews/states.html.erb +23 -0
- data/app/components/shadcn/collapsible/component.rb +35 -0
- data/app/components/shadcn/collapsible/content/component.rb +20 -0
- data/app/components/shadcn/collapsible/preview.rb +11 -0
- data/app/components/shadcn/collapsible/previews/default.html.erb +9 -0
- data/app/components/shadcn/collapsible/trigger/component.rb +23 -0
- data/app/components/shadcn/combobox/chip/component.rb +60 -0
- data/app/components/shadcn/combobox/chip_input/component.rb +43 -0
- data/app/components/shadcn/combobox/chips/component.rb +54 -0
- data/app/components/shadcn/combobox/clear/component.rb +32 -0
- data/app/components/shadcn/combobox/component.rb +113 -0
- data/app/components/shadcn/combobox/content/component.rb +59 -0
- data/app/components/shadcn/combobox/empty/component.rb +23 -0
- data/app/components/shadcn/combobox/input/component.rb +85 -0
- data/app/components/shadcn/combobox/item/component.rb +69 -0
- data/app/components/shadcn/combobox/list/component.rb +27 -0
- data/app/components/shadcn/combobox/preview.rb +31 -0
- data/app/components/shadcn/combobox/previews/default.html.erb +20 -0
- data/app/components/shadcn/combobox/previews/grouped.html.erb +25 -0
- data/app/components/shadcn/combobox/previews/multiple.html.erb +28 -0
- data/app/components/shadcn/combobox/previews/with_clear.html.erb +16 -0
- data/app/components/shadcn/combobox/trigger/component.rb +54 -0
- data/app/components/shadcn/combobox.rb +16 -0
- data/app/components/shadcn/command/component.rb +67 -0
- data/app/components/shadcn/command/dialog/component.rb +72 -0
- data/app/components/shadcn/command/empty/component.rb +29 -0
- data/app/components/shadcn/command/group/component.rb +63 -0
- data/app/components/shadcn/command/input/component.rb +66 -0
- data/app/components/shadcn/command/item/component.rb +62 -0
- data/app/components/shadcn/command/list/component.rb +36 -0
- data/app/components/shadcn/command/preview.rb +26 -0
- data/app/components/shadcn/command/previews/default.html.erb +41 -0
- data/app/components/shadcn/command/previews/dialog.html.erb +33 -0
- data/app/components/shadcn/command/previews/ranking.html.erb +16 -0
- data/app/components/shadcn/command/separator/component.rb +33 -0
- data/app/components/shadcn/command.rb +14 -0
- data/app/components/shadcn/concerns/modal_root.rb +43 -0
- data/app/components/shadcn/concerns/submits_value.rb +81 -0
- data/app/components/shadcn/context_menu/component.rb +45 -0
- data/app/components/shadcn/context_menu/content/component.rb +40 -0
- data/app/components/shadcn/context_menu/preview.rb +16 -0
- data/app/components/shadcn/context_menu/previews/default.html.erb +34 -0
- data/app/components/shadcn/context_menu/previews/items.html.erb +35 -0
- data/app/components/shadcn/context_menu/sub/component.rb +47 -0
- data/app/components/shadcn/context_menu/sub_content/component.rb +31 -0
- data/app/components/shadcn/context_menu/trigger/component.rb +50 -0
- data/app/components/shadcn/context_menu.rb +43 -0
- data/app/components/shadcn/dialog/close/component.rb +20 -0
- data/app/components/shadcn/dialog/component.rb +20 -0
- data/app/components/shadcn/dialog/content/component.rb +78 -0
- data/app/components/shadcn/dialog/header/component.rb +23 -0
- data/app/components/shadcn/dialog/overlay/component.rb +28 -0
- data/app/components/shadcn/dialog/preview.rb +28 -0
- data/app/components/shadcn/dialog/previews/default.html.erb +17 -0
- data/app/components/shadcn/dialog/previews/inside_stacking_context.html.erb +25 -0
- data/app/components/shadcn/dialog/previews/no_close_button.html.erb +15 -0
- data/app/components/shadcn/dialog/previews/scrollable_content.html.erb +29 -0
- data/app/components/shadcn/dialog/trigger/component.rb +24 -0
- data/app/components/shadcn/dialog.rb +17 -0
- data/app/components/shadcn/drawer/component.rb +33 -0
- data/app/components/shadcn/drawer/content/component.rb +95 -0
- data/app/components/shadcn/drawer/header/component.rb +34 -0
- data/app/components/shadcn/drawer/preview.rb +29 -0
- data/app/components/shadcn/drawer/previews/default.html.erb +21 -0
- data/app/components/shadcn/drawer/previews/scrollable.html.erb +20 -0
- data/app/components/shadcn/drawer/previews/scrollable_side.html.erb +21 -0
- data/app/components/shadcn/drawer/previews/sides.html.erb +17 -0
- data/app/components/shadcn/drawer.rb +27 -0
- data/app/components/shadcn/dropdown_menu/checkbox_item/component.rb +61 -0
- data/app/components/shadcn/dropdown_menu/component.rb +48 -0
- data/app/components/shadcn/dropdown_menu/content/component.rb +49 -0
- data/app/components/shadcn/dropdown_menu/group/component.rb +16 -0
- data/app/components/shadcn/dropdown_menu/item/component.rb +50 -0
- data/app/components/shadcn/dropdown_menu/preview.rb +16 -0
- data/app/components/shadcn/dropdown_menu/previews/checkboxes_and_radio.html.erb +34 -0
- data/app/components/shadcn/dropdown_menu/previews/default.html.erb +23 -0
- data/app/components/shadcn/dropdown_menu/radio_group/component.rb +16 -0
- data/app/components/shadcn/dropdown_menu/radio_item/component.rb +63 -0
- data/app/components/shadcn/dropdown_menu/sub/component.rb +44 -0
- data/app/components/shadcn/dropdown_menu/sub_content/component.rb +45 -0
- data/app/components/shadcn/dropdown_menu/sub_trigger/component.rb +58 -0
- data/app/components/shadcn/dropdown_menu/trigger/component.rb +25 -0
- data/app/components/shadcn/dropdown_menu.rb +18 -0
- data/app/components/shadcn/empty/component.rb +17 -0
- data/app/components/shadcn/empty/media/component.rb +48 -0
- data/app/components/shadcn/empty/preview.rb +16 -0
- data/app/components/shadcn/empty/previews/default.html.erb +15 -0
- data/app/components/shadcn/empty/previews/media.html.erb +32 -0
- data/app/components/shadcn/empty.rb +26 -0
- data/app/components/shadcn/field/component.rb +61 -0
- data/app/components/shadcn/field/error/component.rb +49 -0
- data/app/components/shadcn/field/legend/component.rb +30 -0
- data/app/components/shadcn/field/preview.rb +17 -0
- data/app/components/shadcn/field/previews/default.html.erb +29 -0
- data/app/components/shadcn/field/previews/form_builder.html.erb +38 -0
- data/app/components/shadcn/field/separator/component.rb +35 -0
- data/app/components/shadcn/field.rb +44 -0
- data/app/components/shadcn/hover_card/component.rb +51 -0
- data/app/components/shadcn/hover_card/content/component.rb +45 -0
- data/app/components/shadcn/hover_card/preview.rb +16 -0
- data/app/components/shadcn/hover_card/previews/default.html.erb +36 -0
- data/app/components/shadcn/hover_card/previews/sides.html.erb +15 -0
- data/app/components/shadcn/hover_card/trigger/component.rb +33 -0
- data/app/components/shadcn/icon/component.rb +76 -0
- data/app/components/shadcn/icon.rb +43 -0
- data/app/components/shadcn/input/component.rb +26 -0
- data/app/components/shadcn/input/preview.rb +16 -0
- data/app/components/shadcn/input/previews/default.html.erb +5 -0
- data/app/components/shadcn/input/previews/states.html.erb +20 -0
- data/app/components/shadcn/input_group/addon/component.rb +65 -0
- data/app/components/shadcn/input_group/button/component.rb +40 -0
- data/app/components/shadcn/input_group/component.rb +43 -0
- data/app/components/shadcn/input_group/input/component.rb +25 -0
- data/app/components/shadcn/input_group/preview.rb +17 -0
- data/app/components/shadcn/input_group/previews/addons.html.erb +53 -0
- data/app/components/shadcn/input_group/previews/default.html.erb +25 -0
- data/app/components/shadcn/input_group/text/component.rb +20 -0
- data/app/components/shadcn/input_group/textarea/component.rb +21 -0
- data/app/components/shadcn/input_otp/component.rb +95 -0
- data/app/components/shadcn/input_otp/preview.rb +17 -0
- data/app/components/shadcn/input_otp/previews/default.html.erb +19 -0
- data/app/components/shadcn/input_otp/previews/variations.html.erb +33 -0
- data/app/components/shadcn/input_otp/separator/component.rb +21 -0
- data/app/components/shadcn/input_otp/slot/component.rb +60 -0
- data/app/components/shadcn/input_otp.rb +11 -0
- data/app/components/shadcn/item/component.rb +56 -0
- data/app/components/shadcn/item/group/component.rb +53 -0
- data/app/components/shadcn/item/media/component.rb +53 -0
- data/app/components/shadcn/item/preview.rb +20 -0
- data/app/components/shadcn/item/previews/default.html.erb +32 -0
- data/app/components/shadcn/item/previews/link.html.erb +39 -0
- data/app/components/shadcn/item/previews/outline.html.erb +8 -0
- data/app/components/shadcn/item/separator/component.rb +24 -0
- data/app/components/shadcn/item.rb +34 -0
- data/app/components/shadcn/kbd/component.rb +23 -0
- data/app/components/shadcn/kbd/group/component.rb +17 -0
- data/app/components/shadcn/kbd/preview.rb +11 -0
- data/app/components/shadcn/kbd/previews/default.html.erb +4 -0
- data/app/components/shadcn/label/component.rb +20 -0
- data/app/components/shadcn/label/preview.rb +11 -0
- data/app/components/shadcn/label/previews/default.html.erb +4 -0
- data/app/components/shadcn/marker/component.rb +46 -0
- data/app/components/shadcn/marker/icon/component.rb +23 -0
- data/app/components/shadcn/marker/preview.rb +17 -0
- data/app/components/shadcn/marker/previews/default.html.erb +18 -0
- data/app/components/shadcn/marker/previews/status.html.erb +32 -0
- data/app/components/shadcn/marker.rb +17 -0
- data/app/components/shadcn/menubar/component.rb +36 -0
- data/app/components/shadcn/menubar/content/component.rb +49 -0
- data/app/components/shadcn/menubar/menu/component.rb +39 -0
- data/app/components/shadcn/menubar/preview.rb +16 -0
- data/app/components/shadcn/menubar/previews/default.html.erb +52 -0
- data/app/components/shadcn/menubar/previews/items.html.erb +38 -0
- data/app/components/shadcn/menubar/sub/component.rb +43 -0
- data/app/components/shadcn/menubar/sub_content/component.rb +31 -0
- data/app/components/shadcn/menubar/sub_trigger/component.rb +31 -0
- data/app/components/shadcn/menubar/trigger/component.rb +41 -0
- data/app/components/shadcn/menubar.rb +47 -0
- data/app/components/shadcn/message/component.rb +33 -0
- data/app/components/shadcn/message/preview.rb +16 -0
- data/app/components/shadcn/message/previews/actions.html.erb +51 -0
- data/app/components/shadcn/message/previews/default.html.erb +35 -0
- data/app/components/shadcn/message.rb +35 -0
- data/app/components/shadcn/message_scroller/button/component.rb +78 -0
- data/app/components/shadcn/message_scroller/component.rb +59 -0
- data/app/components/shadcn/message_scroller/content/component.rb +50 -0
- data/app/components/shadcn/message_scroller/item/component.rb +45 -0
- data/app/components/shadcn/message_scroller/preview.rb +11 -0
- data/app/components/shadcn/message_scroller/previews/default.html.erb +72 -0
- data/app/components/shadcn/message_scroller/viewport/component.rb +41 -0
- data/app/components/shadcn/mode_switcher/component.rb +67 -0
- data/app/components/shadcn/mode_switcher/preview.rb +11 -0
- data/app/components/shadcn/mode_switcher/previews/default.html.erb +5 -0
- data/app/components/shadcn/mode_toggle/component.rb +75 -0
- data/app/components/shadcn/mode_toggle/preview.rb +11 -0
- data/app/components/shadcn/mode_toggle/previews/default.html.erb +20 -0
- data/app/components/shadcn/native_select/component.rb +59 -0
- data/app/components/shadcn/native_select/preview.rb +16 -0
- data/app/components/shadcn/native_select/previews/default.html.erb +9 -0
- data/app/components/shadcn/native_select/previews/groups.html.erb +26 -0
- data/app/components/shadcn/native_select.rb +16 -0
- data/app/components/shadcn/navigation_menu/component.rb +51 -0
- data/app/components/shadcn/navigation_menu/content/component.rb +58 -0
- data/app/components/shadcn/navigation_menu/preview.rb +11 -0
- data/app/components/shadcn/navigation_menu/previews/default.html.erb +49 -0
- data/app/components/shadcn/navigation_menu/trigger/component.rb +59 -0
- data/app/components/shadcn/navigation_menu.rb +28 -0
- data/app/components/shadcn/pagination/component.rb +19 -0
- data/app/components/shadcn/pagination/ellipsis/component.rb +28 -0
- data/app/components/shadcn/pagination/link/component.rb +37 -0
- data/app/components/shadcn/pagination/next/component.rb +31 -0
- data/app/components/shadcn/pagination/preview.rb +16 -0
- data/app/components/shadcn/pagination/previews/default.html.erb +18 -0
- data/app/components/shadcn/pagination/previews/simple.html.erb +39 -0
- data/app/components/shadcn/pagination/previous/component.rb +31 -0
- data/app/components/shadcn/pagination.rb +14 -0
- data/app/components/shadcn/parts.rb +38 -0
- data/app/components/shadcn/popover/anchor/component.rb +17 -0
- data/app/components/shadcn/popover/component.rb +42 -0
- data/app/components/shadcn/popover/content/component.rb +40 -0
- data/app/components/shadcn/popover/preview.rb +28 -0
- data/app/components/shadcn/popover/previews/align.html.erb +13 -0
- data/app/components/shadcn/popover/previews/default.html.erb +9 -0
- data/app/components/shadcn/popover/previews/inside_containing_block.html.erb +41 -0
- data/app/components/shadcn/popover/previews/inside_stacking_context.html.erb +30 -0
- data/app/components/shadcn/popover/trigger/component.rb +24 -0
- data/app/components/shadcn/popover.rb +16 -0
- data/app/components/shadcn/progress/component.rb +62 -0
- data/app/components/shadcn/progress/preview.rb +11 -0
- data/app/components/shadcn/progress/previews/default.html.erb +5 -0
- data/app/components/shadcn/radio_group/component.rb +51 -0
- data/app/components/shadcn/radio_group/item/component.rb +74 -0
- data/app/components/shadcn/radio_group/preview.rb +16 -0
- data/app/components/shadcn/radio_group/previews/default.html.erb +15 -0
- data/app/components/shadcn/radio_group/previews/states.html.erb +41 -0
- data/app/components/shadcn/resizable/component.rb +59 -0
- data/app/components/shadcn/resizable/handle/component.rb +70 -0
- data/app/components/shadcn/resizable/panel/component.rb +53 -0
- data/app/components/shadcn/resizable/preview.rb +23 -0
- data/app/components/shadcn/resizable/previews/default.html.erb +25 -0
- data/app/components/shadcn/resizable/previews/vertical.html.erb +19 -0
- data/app/components/shadcn/resizable/previews/with_handle.html.erb +17 -0
- data/app/components/shadcn/scroll_area/component.rb +84 -0
- data/app/components/shadcn/scroll_area/preview.rb +11 -0
- data/app/components/shadcn/scroll_area/previews/default.html.erb +36 -0
- data/app/components/shadcn/scroll_area/scrollbar/component.rb +72 -0
- data/app/components/shadcn/scroll_area/viewport/component.rb +70 -0
- data/app/components/shadcn/scroll_area.rb +14 -0
- data/app/components/shadcn/select/component.rb +67 -0
- data/app/components/shadcn/select/content/component.rb +157 -0
- data/app/components/shadcn/select/empty/component.rb +38 -0
- data/app/components/shadcn/select/group/component.rb +16 -0
- data/app/components/shadcn/select/item/component.rb +71 -0
- data/app/components/shadcn/select/list/component.rb +41 -0
- data/app/components/shadcn/select/preview.rb +24 -0
- data/app/components/shadcn/select/previews/default.html.erb +17 -0
- data/app/components/shadcn/select/previews/scrollable.html.erb +19 -0
- data/app/components/shadcn/select/previews/searchable.html.erb +18 -0
- data/app/components/shadcn/select/previews/states.html.erb +25 -0
- data/app/components/shadcn/select/search/component.rb +54 -0
- data/app/components/shadcn/select/trigger/component.rb +78 -0
- data/app/components/shadcn/select/value/component.rb +28 -0
- data/app/components/shadcn/select.rb +15 -0
- data/app/components/shadcn/separator/component.rb +41 -0
- data/app/components/shadcn/separator/preview.rb +11 -0
- data/app/components/shadcn/separator/previews/default.html.erb +9 -0
- data/app/components/shadcn/sheet/component.rb +16 -0
- data/app/components/shadcn/sheet/content/component.rb +98 -0
- data/app/components/shadcn/sheet/header/component.rb +23 -0
- data/app/components/shadcn/sheet/preview.rb +16 -0
- data/app/components/shadcn/sheet/previews/default.html.erb +16 -0
- data/app/components/shadcn/sheet/previews/no_close_button.html.erb +14 -0
- data/app/components/shadcn/sheet.rb +22 -0
- data/app/components/shadcn/sidebar/component.rb +232 -0
- data/app/components/shadcn/sidebar/input/component.rb +25 -0
- data/app/components/shadcn/sidebar/menu_action/component.rb +58 -0
- data/app/components/shadcn/sidebar/menu_button/component.rb +100 -0
- data/app/components/shadcn/sidebar/menu_skeleton/component.rb +51 -0
- data/app/components/shadcn/sidebar/menu_sub_button/component.rb +60 -0
- data/app/components/shadcn/sidebar/preview.rb +22 -0
- data/app/components/shadcn/sidebar/previews/default.html.erb +189 -0
- data/app/components/shadcn/sidebar/previews/floating.html.erb +39 -0
- data/app/components/shadcn/sidebar/previews/inset.html.erb +48 -0
- data/app/components/shadcn/sidebar/provider/component.rb +53 -0
- data/app/components/shadcn/sidebar/rail/component.rb +43 -0
- data/app/components/shadcn/sidebar/separator/component.rb +23 -0
- data/app/components/shadcn/sidebar/trigger/component.rb +39 -0
- data/app/components/shadcn/sidebar.rb +98 -0
- data/app/components/shadcn/skeleton/component.rb +14 -0
- data/app/components/shadcn/skeleton/preview.rb +11 -0
- data/app/components/shadcn/skeleton/previews/default.html.erb +7 -0
- data/app/components/shadcn/slider/component.rb +145 -0
- data/app/components/shadcn/slider/preview.rb +16 -0
- data/app/components/shadcn/slider/previews/default.html.erb +17 -0
- data/app/components/shadcn/slider/previews/vertical.html.erb +7 -0
- data/app/components/shadcn/slider/range/component.rb +51 -0
- data/app/components/shadcn/slider/thumb/component.rb +58 -0
- data/app/components/shadcn/slider/track/component.rb +32 -0
- data/app/components/shadcn/spinner/component.rb +21 -0
- data/app/components/shadcn/spinner/preview.rb +11 -0
- data/app/components/shadcn/spinner/previews/default.html.erb +7 -0
- data/app/components/shadcn/switch/component.rb +104 -0
- data/app/components/shadcn/switch/preview.rb +11 -0
- data/app/components/shadcn/switch/previews/default.html.erb +24 -0
- data/app/components/shadcn/table/component.rb +26 -0
- data/app/components/shadcn/table/preview.rb +16 -0
- data/app/components/shadcn/table/previews/default.html.erb +19 -0
- data/app/components/shadcn/table/previews/footer.html.erb +25 -0
- data/app/components/shadcn/table.rb +33 -0
- data/app/components/shadcn/tabs/component.rb +40 -0
- data/app/components/shadcn/tabs/content/component.rb +34 -0
- data/app/components/shadcn/tabs/list/component.rb +51 -0
- data/app/components/shadcn/tabs/preview.rb +16 -0
- data/app/components/shadcn/tabs/previews/default.html.erb +21 -0
- data/app/components/shadcn/tabs/previews/line.html.erb +23 -0
- data/app/components/shadcn/tabs/trigger/component.rb +66 -0
- data/app/components/shadcn/textarea/component.rb +24 -0
- data/app/components/shadcn/textarea/preview.rb +16 -0
- data/app/components/shadcn/textarea/previews/default.html.erb +3 -0
- data/app/components/shadcn/textarea/previews/states.html.erb +18 -0
- data/app/components/shadcn/theme_selector/component.rb +88 -0
- data/app/components/shadcn/theme_selector/preview.rb +17 -0
- data/app/components/shadcn/theme_selector/previews/all_themes.html.erb +20 -0
- data/app/components/shadcn/theme_selector/previews/default.html.erb +18 -0
- data/app/components/shadcn/toaster/component.rb +139 -0
- data/app/components/shadcn/toaster/preview.rb +16 -0
- data/app/components/shadcn/toaster/previews/default.html.erb +19 -0
- data/app/components/shadcn/toaster/previews/from_the_server.html.erb +15 -0
- data/app/components/shadcn/toaster/toast/component.rb +134 -0
- data/app/components/shadcn/toggle/component.rb +81 -0
- data/app/components/shadcn/toggle/preview.rb +11 -0
- data/app/components/shadcn/toggle/previews/default.html.erb +6 -0
- data/app/components/shadcn/toggle_group/component.rb +62 -0
- data/app/components/shadcn/toggle_group/item/component.rb +59 -0
- data/app/components/shadcn/toggle_group/preview.rb +16 -0
- data/app/components/shadcn/toggle_group/previews/default.html.erb +12 -0
- data/app/components/shadcn/toggle_group/previews/sizes.html.erb +37 -0
- data/app/components/shadcn/tooltip/component.rb +38 -0
- data/app/components/shadcn/tooltip/content/component.rb +62 -0
- data/app/components/shadcn/tooltip/preview.rb +21 -0
- data/app/components/shadcn/tooltip/previews/default.html.erb +4 -0
- data/app/components/shadcn/tooltip/previews/sides.html.erb +19 -0
- data/app/components/shadcn/tooltip/previews/with_keyboard_shortcut.html.erb +11 -0
- data/app/components/shadcn/tooltip/provider/component.rb +28 -0
- data/app/components/shadcn/tooltip/trigger/component.rb +25 -0
- data/app/helpers/shadcn_view_component/form_helper.rb +25 -0
- data/app/helpers/shadcn_view_component/theme_helper.rb +61 -0
- data/app/javascript/shadcn/animation.js +180 -0
- data/app/javascript/shadcn/command_score.js +110 -0
- data/app/javascript/shadcn/controllers/accordion_controller.js +127 -0
- data/app/javascript/shadcn/controllers/avatar_controller.js +32 -0
- data/app/javascript/shadcn/controllers/calendar_controller.js +633 -0
- data/app/javascript/shadcn/controllers/carousel_controller.js +139 -0
- data/app/javascript/shadcn/controllers/chart_controller.js +110 -0
- data/app/javascript/shadcn/controllers/checkbox_controller.js +61 -0
- data/app/javascript/shadcn/controllers/collapsible_controller.js +55 -0
- data/app/javascript/shadcn/controllers/combobox_controller.js +360 -0
- data/app/javascript/shadcn/controllers/command_controller.js +199 -0
- data/app/javascript/shadcn/controllers/dialog_controller.js +154 -0
- data/app/javascript/shadcn/controllers/drawer_controller.js +265 -0
- data/app/javascript/shadcn/controllers/dropdown_menu_controller.js +259 -0
- data/app/javascript/shadcn/controllers/hover_card_controller.js +85 -0
- data/app/javascript/shadcn/controllers/input_group_controller.js +17 -0
- data/app/javascript/shadcn/controllers/input_otp_controller.js +80 -0
- data/app/javascript/shadcn/controllers/menubar_controller.js +151 -0
- data/app/javascript/shadcn/controllers/message_scroller_controller.js +456 -0
- data/app/javascript/shadcn/controllers/navigation_menu_controller.js +211 -0
- data/app/javascript/shadcn/controllers/popover_controller.js +66 -0
- data/app/javascript/shadcn/controllers/radio_group_controller.js +69 -0
- data/app/javascript/shadcn/controllers/resizable_controller.js +167 -0
- data/app/javascript/shadcn/controllers/scroll_area_controller.js +253 -0
- data/app/javascript/shadcn/controllers/select_controller.js +320 -0
- data/app/javascript/shadcn/controllers/sidebar_controller.js +273 -0
- data/app/javascript/shadcn/controllers/slider_controller.js +230 -0
- data/app/javascript/shadcn/controllers/switch_controller.js +39 -0
- data/app/javascript/shadcn/controllers/tabs_controller.js +81 -0
- data/app/javascript/shadcn/controllers/theme_controller.js +67 -0
- data/app/javascript/shadcn/controllers/toaster_controller.js +281 -0
- data/app/javascript/shadcn/controllers/toggle_controller.js +24 -0
- data/app/javascript/shadcn/controllers/toggle_group_controller.js +73 -0
- data/app/javascript/shadcn/controllers/tooltip_controller.js +58 -0
- data/app/javascript/shadcn/direction.js +41 -0
- data/app/javascript/shadcn/dismiss.js +73 -0
- data/app/javascript/shadcn/floating.js +207 -0
- data/app/javascript/shadcn/focus.js +86 -0
- data/app/javascript/shadcn/id.js +14 -0
- data/app/javascript/shadcn/index.js +110 -0
- data/app/javascript/shadcn/popper.js +262 -0
- data/app/javascript/shadcn/scroll_geometry.js +267 -0
- data/app/javascript/shadcn/theme.js +161 -0
- data/app/javascript/shadcn/top_layer.js +59 -0
- data/app/javascript/shadcn/typeahead.js +99 -0
- data/config/importmap.rb +6 -0
- data/config/locales/en.yml +62 -0
- data/lib/generators/shadcn_view_component/install/install_generator.rb +149 -0
- data/lib/shadcn_view_component/engine.rb +73 -0
- data/lib/shadcn_view_component/form_builder.rb +264 -0
- data/lib/shadcn_view_component/icon_registry.rb +66 -0
- data/lib/shadcn_view_component/icons.rb +32 -0
- data/lib/shadcn_view_component/themes.rb +1065 -0
- data/lib/shadcn_view_component/version.rb +3 -0
- data/lib/shadcn_view_component.rb +82 -0
- data/lib/tasks/icons.rake +53 -0
- data/lib/tasks/themes.rake +171 -0
- metadata +608 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Drawer
|
|
5
|
+
# Port of registry/new-york-v4/ui/drawer.tsx
|
|
6
|
+
#
|
|
7
|
+
# vaul's Drawer.Root wraps Radix's Dialog.Root, so the open/close half of
|
|
8
|
+
# this component *is* the dialog's and runs on `shadcn--dialog`: the focus
|
|
9
|
+
# trap, the scroll lock, Escape, the outside click and the exit animation
|
|
10
|
+
# are all already there and are not reimplemented. What vaul adds is the
|
|
11
|
+
# drag, and that is `shadcn--drawer`, on the content — the same arrangement
|
|
12
|
+
# the menubar has with the dropdown.
|
|
13
|
+
class Component < ApplicationViewComponent
|
|
14
|
+
include Concerns::ModalRoot
|
|
15
|
+
|
|
16
|
+
renders_one :trigger, "Shadcn::Drawer::Trigger::Component"
|
|
17
|
+
# `dialog_content` rather than `drawer_content`, which reads better here
|
|
18
|
+
# but would make this the one modal family out of four with its own name
|
|
19
|
+
# for the same slot — `ModalRoot` renders it, and Sheet and AlertDialog
|
|
20
|
+
# both call it that.
|
|
21
|
+
renders_one :dialog_content, "Shadcn::Drawer::Content::Component"
|
|
22
|
+
|
|
23
|
+
slot_name :drawer
|
|
24
|
+
|
|
25
|
+
# Two controllers on one element. `data-controller` is one of the
|
|
26
|
+
# attributes that *replaces* rather than concatenates, so the dialog's own
|
|
27
|
+
# string has to be repeated here rather than added to.
|
|
28
|
+
def element_attributes(**defaults)
|
|
29
|
+
super(**{ "data-controller" => "shadcn--dialog shadcn--drawer" }.merge(defaults))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Drawer
|
|
5
|
+
module Content
|
|
6
|
+
# DrawerContent — renders its own overlay, as the TSX does, and the drag
|
|
7
|
+
# handle above the content.
|
|
8
|
+
#
|
|
9
|
+
# Unlike the Sheet, the four edges are *not* cva variants: upstream emits
|
|
10
|
+
# all four sets of classes at once and lets `data-vaul-drawer-direction`
|
|
11
|
+
# pick between them, so this element carries every one of them and the
|
|
12
|
+
# attribute does the choosing. That attribute name is vaul's, not ours —
|
|
13
|
+
# it is in the class strings this port has to reproduce byte for byte, so
|
|
14
|
+
# the markup has to speak it.
|
|
15
|
+
class Component < ApplicationViewComponent
|
|
16
|
+
DIRECTIONS = %i[top bottom left right].freeze
|
|
17
|
+
|
|
18
|
+
HANDLE_CLASSES = "mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full bg-muted " \
|
|
19
|
+
"group-data-[vaul-drawer-direction=bottom]/drawer-content:block"
|
|
20
|
+
|
|
21
|
+
renders_one :header, "Shadcn::Drawer::Header::Component"
|
|
22
|
+
renders_one :footer, "Shadcn::Drawer::Footer::Component"
|
|
23
|
+
|
|
24
|
+
slot_name :"drawer-content"
|
|
25
|
+
|
|
26
|
+
style do
|
|
27
|
+
base {
|
|
28
|
+
"group/drawer-content fixed z-50 flex h-auto flex-col bg-background " \
|
|
29
|
+
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 " \
|
|
30
|
+
"data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] " \
|
|
31
|
+
"data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b " \
|
|
32
|
+
"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 " \
|
|
33
|
+
"data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] " \
|
|
34
|
+
"data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t " \
|
|
35
|
+
"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 " \
|
|
36
|
+
"data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l " \
|
|
37
|
+
"data-[vaul-drawer-direction=right]:sm:max-w-sm " \
|
|
38
|
+
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 " \
|
|
39
|
+
"data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r " \
|
|
40
|
+
"data-[vaul-drawer-direction=left]:sm:max-w-sm"
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
attr_reader :direction
|
|
45
|
+
|
|
46
|
+
def initialize(direction: :bottom, **attributes)
|
|
47
|
+
@direction = DIRECTIONS.include?(direction&.to_sym) ? direction.to_sym : :bottom
|
|
48
|
+
super(**attributes)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def element_attributes(**defaults)
|
|
52
|
+
super(**{
|
|
53
|
+
role: "dialog",
|
|
54
|
+
"aria-modal" => "true",
|
|
55
|
+
tabindex: "-1",
|
|
56
|
+
"data-state" => "closed",
|
|
57
|
+
hidden: true,
|
|
58
|
+
"data-vaul-drawer" => "",
|
|
59
|
+
"data-vaul-drawer-direction" => direction,
|
|
60
|
+
# A constant, because this port has no snap points — and named
|
|
61
|
+
# rather than dropped because vaul's own selectors carry it, and the
|
|
62
|
+
# stylesheet reproduced in `shadcn.css` matches on it.
|
|
63
|
+
"data-vaul-snap-points" => "false",
|
|
64
|
+
"data-shadcn--dialog-target" => "content",
|
|
65
|
+
"data-shadcn--drawer-target" => "content",
|
|
66
|
+
"data-action" => "pointerdown->shadcn--drawer#press " \
|
|
67
|
+
"pointermove->shadcn--drawer#move " \
|
|
68
|
+
"pointerup->shadcn--drawer#release " \
|
|
69
|
+
"pointercancel->shadcn--drawer#release"
|
|
70
|
+
}.merge(defaults))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# shadcn wraps the overlay and the content in a DrawerPortal, which vaul
|
|
74
|
+
# relocates to `document.body`; here it stays put, as the dialog's does,
|
|
75
|
+
# and is `display: contents` so it adds no box of its own.
|
|
76
|
+
def call
|
|
77
|
+
tag.div("data-slot": "drawer-portal", style: CONTENTS_STYLE) do
|
|
78
|
+
safe_join([
|
|
79
|
+
render(Overlay::Component.new("data-vaul-overlay": "", "data-shadcn--drawer-target": "overlay")),
|
|
80
|
+
render_element(body: safe_join([ handle, header, content, footer ].compact))
|
|
81
|
+
])
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
# Shown only when the drawer comes up from the bottom — the class does
|
|
88
|
+
# that, so it is rendered whatever the direction, exactly as upstream.
|
|
89
|
+
def handle
|
|
90
|
+
tag.div(class: HANDLE_CLASSES)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Drawer
|
|
5
|
+
module Header
|
|
6
|
+
# DrawerHeader — a slot for the title and the description, as the Sheet's
|
|
7
|
+
# and the Dialog's are.
|
|
8
|
+
#
|
|
9
|
+
# The two `group-data-*` classes read the direction off the *content*,
|
|
10
|
+
# which is why that attribute lives there rather than on the root shadcn
|
|
11
|
+
# takes it on: a header centres itself only when the drawer comes from an
|
|
12
|
+
# edge that makes it the top of the panel.
|
|
13
|
+
class Component < ApplicationViewComponent
|
|
14
|
+
renders_one :title, "Shadcn::Drawer::Title::Component"
|
|
15
|
+
renders_one :description, "Shadcn::Drawer::Description::Component"
|
|
16
|
+
|
|
17
|
+
slot_name :"drawer-header"
|
|
18
|
+
|
|
19
|
+
style do
|
|
20
|
+
base {
|
|
21
|
+
"flex flex-col gap-0.5 p-4 " \
|
|
22
|
+
"group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center " \
|
|
23
|
+
"group-data-[vaul-drawer-direction=top]/drawer-content:text-center " \
|
|
24
|
+
"md:gap-1.5 md:text-left"
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def call
|
|
29
|
+
render_element(body: safe_join([ title, description, content ].compact))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Drawer
|
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
|
6
|
+
def default
|
|
7
|
+
render_with_template
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# The other three edges, which the same class string serves — only the
|
|
11
|
+
# `data-vaul-drawer-direction` changes.
|
|
12
|
+
def sides
|
|
13
|
+
render_with_template
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# A drawer taller than it can show, which is where the drag has to give
|
|
17
|
+
# way to the scroll.
|
|
18
|
+
def scrollable
|
|
19
|
+
render_with_template
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# The same list, in a drawer that closes sideways — where the two gestures
|
|
23
|
+
# stop competing and the drag is let through whatever is scrolled.
|
|
24
|
+
def scrollable_side
|
|
25
|
+
render_with_template
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%# Upstream's own example: a bottom drawer with a header, a body and a footer.
|
|
2
|
+
The handle above the header is what says it can be dragged. %>
|
|
3
|
+
<%= render(Shadcn::Drawer::Component.new) do |d| %>
|
|
4
|
+
<% d.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { "Open drawer" } %>
|
|
5
|
+
<% d.with_dialog_content do |c| %>
|
|
6
|
+
<% c.with_header do |h| %>
|
|
7
|
+
<% h.with_title { "Move goal" } %>
|
|
8
|
+
<% h.with_description { "Set your daily activity goal." } %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<div class="p-4 pb-0">
|
|
11
|
+
<p class="text-sm text-muted-foreground">
|
|
12
|
+
Drag this panel downwards, or throw it, and it closes. Drag it up and it
|
|
13
|
+
gives a little and comes back.
|
|
14
|
+
</p>
|
|
15
|
+
</div>
|
|
16
|
+
<% c.with_footer do %>
|
|
17
|
+
<%= render(Shadcn::Button::Component.new) { "Submit" } %>
|
|
18
|
+
<%= render(Shadcn::Drawer::Close::Component.new(class: Shadcn::Button::Component.variant_classes(variant: :outline))) { "Cancel" } %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<%# The case the drag has to give way for: a list longer than the drawer. A
|
|
2
|
+
downward drag that starts part-way down the list scrolls it and must not
|
|
3
|
+
also throw the drawer away — which is what `shouldDrag` decides. %>
|
|
4
|
+
<%= render(Shadcn::Drawer::Component.new) do |d| %>
|
|
5
|
+
<% d.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { "Open a long drawer" } %>
|
|
6
|
+
<% d.with_dialog_content do |c| %>
|
|
7
|
+
<% c.with_header do |h| %>
|
|
8
|
+
<% h.with_title { "Recent activity" } %>
|
|
9
|
+
<% h.with_description { "Scroll the list; the drawer stays put." } %>
|
|
10
|
+
<% end %>
|
|
11
|
+
<div class="max-h-64 overflow-y-auto px-4">
|
|
12
|
+
<% 30.times do |i| %>
|
|
13
|
+
<div class="border-b py-3 text-sm last:border-b-0">Entry <%= i + 1 %></div>
|
|
14
|
+
<% end %>
|
|
15
|
+
</div>
|
|
16
|
+
<% c.with_footer do %>
|
|
17
|
+
<%= render(Shadcn::Drawer::Close::Component.new(class: Shadcn::Button::Component.variant_classes(variant: :outline))) { "Close" } %>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%# The same long list in a drawer that closes sideways. It is the case where
|
|
2
|
+
the two gestures stop competing: a vertical pull scrolls the list, and a
|
|
3
|
+
horizontal one can only mean the drawer, so `shouldDrag` lets it through
|
|
4
|
+
without asking what is scrolled. %>
|
|
5
|
+
<%= render(Shadcn::Drawer::Component.new) do |d| %>
|
|
6
|
+
<% d.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { "Open filters" } %>
|
|
7
|
+
<% d.with_dialog_content(direction: :right) do |c| %>
|
|
8
|
+
<% c.with_header do |h| %>
|
|
9
|
+
<% h.with_title { "Filters" } %>
|
|
10
|
+
<% h.with_description { "Scroll the list, or push the panel to the right." } %>
|
|
11
|
+
<% end %>
|
|
12
|
+
<div class="max-h-96 overflow-y-auto px-4">
|
|
13
|
+
<% 30.times do |i| %>
|
|
14
|
+
<div class="border-b py-3 text-sm last:border-b-0">Filter <%= i + 1 %></div>
|
|
15
|
+
<% end %>
|
|
16
|
+
</div>
|
|
17
|
+
<% c.with_footer do %>
|
|
18
|
+
<%= render(Shadcn::Drawer::Close::Component.new(class: Shadcn::Button::Component.variant_classes(variant: :outline))) { "Close" } %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<%# One class string serves all four edges; only the attribute changes. %>
|
|
2
|
+
<div class="flex items-center gap-2">
|
|
3
|
+
<% %i[bottom top left right].each do |direction| %>
|
|
4
|
+
<%= render(Shadcn::Drawer::Component.new) do |d| %>
|
|
5
|
+
<% d.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { direction.to_s.capitalize } %>
|
|
6
|
+
<% d.with_dialog_content(direction:) do |c| %>
|
|
7
|
+
<% c.with_header do |h| %>
|
|
8
|
+
<% h.with_title { "From the #{direction}" } %>
|
|
9
|
+
<% h.with_description { "Dragged towards that edge, it closes." } %>
|
|
10
|
+
<% end %>
|
|
11
|
+
<% c.with_footer do %>
|
|
12
|
+
<%= render(Shadcn::Drawer::Close::Component.new(class: Shadcn::Button::Component.variant_classes(variant: :outline))) { "Close" } %>
|
|
13
|
+
<% end %>
|
|
14
|
+
<% end %>
|
|
15
|
+
<% end %>
|
|
16
|
+
<% end %>
|
|
17
|
+
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
# The parts of the Drawer family that are just an element with a `data-slot`
|
|
5
|
+
# and a fixed set of classes. Anything with variants, slots or markup of its
|
|
6
|
+
# own keeps its own `component.rb`.
|
|
7
|
+
#
|
|
8
|
+
# Upstream builds this on **vaul**, not on Radix — but vaul is itself a Radix
|
|
9
|
+
# Dialog with a drag on top (`import * as DialogPrimitive from
|
|
10
|
+
# '@radix-ui/react-dialog'` is its third line), so the parts that are only
|
|
11
|
+
# markup come from the Dialog here for the same reason the Sheet's do.
|
|
12
|
+
module Drawer
|
|
13
|
+
extend Parts
|
|
14
|
+
|
|
15
|
+
part :close, slot: "drawer-close", from: Dialog::Close::Component
|
|
16
|
+
|
|
17
|
+
part :description, tag: :p, slot: "drawer-description", classes: "text-sm text-muted-foreground"
|
|
18
|
+
|
|
19
|
+
part :footer, slot: "drawer-footer", classes: "mt-auto flex flex-col gap-2 p-4"
|
|
20
|
+
|
|
21
|
+
part :overlay, slot: "drawer-overlay", from: Dialog::Overlay::Component
|
|
22
|
+
|
|
23
|
+
part :title, tag: :h2, slot: "drawer-title", classes: "font-semibold text-foreground"
|
|
24
|
+
|
|
25
|
+
part :trigger, slot: "drawer-trigger", from: Dialog::Trigger::Component
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module DropdownMenu
|
|
5
|
+
module CheckboxItem
|
|
6
|
+
# DropdownMenuCheckboxItem
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
INDICATOR_CLASSES = "pointer-events-none absolute left-2 flex size-3.5 " \
|
|
9
|
+
"items-center justify-center"
|
|
10
|
+
|
|
11
|
+
slot_name :"dropdown-menu-checkbox-item"
|
|
12
|
+
|
|
13
|
+
style do
|
|
14
|
+
base {
|
|
15
|
+
"relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 " \
|
|
16
|
+
"text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground " \
|
|
17
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50 " \
|
|
18
|
+
"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_reader :checked, :disabled
|
|
23
|
+
|
|
24
|
+
def initialize(checked: false, disabled: false, **attributes)
|
|
25
|
+
@checked = checked
|
|
26
|
+
@disabled = disabled
|
|
27
|
+
super(**attributes)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def element_attributes(**defaults)
|
|
31
|
+
super(**{
|
|
32
|
+
role: "menuitemcheckbox",
|
|
33
|
+
tabindex: "-1",
|
|
34
|
+
"aria-checked" => checked.to_s,
|
|
35
|
+
"data-state" => (checked ? "checked" : "unchecked"),
|
|
36
|
+
"data-disabled" => (true if disabled),
|
|
37
|
+
"data-shadcn--dropdown-menu-target" => "item",
|
|
38
|
+
"data-action" => "click->shadcn--dropdown-menu#select " \
|
|
39
|
+
"pointerenter->shadcn--dropdown-menu#pointerenter"
|
|
40
|
+
}.merge(defaults))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def call
|
|
44
|
+
render_element(body: safe_join([ indicator, content ]))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def indicator
|
|
50
|
+
tag.span(class: INDICATOR_CLASSES) do
|
|
51
|
+
tag.span(
|
|
52
|
+
render(Icon::Component.new("check", class: "size-4")),
|
|
53
|
+
"data-slot": "dropdown-menu-checkbox-item-indicator",
|
|
54
|
+
hidden: (true unless checked)
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module DropdownMenu
|
|
5
|
+
# Port of registry/new-york-v4/ui/dropdown-menu.tsx
|
|
6
|
+
class Component < ApplicationViewComponent
|
|
7
|
+
renders_one :trigger, "Shadcn::DropdownMenu::Trigger::Component"
|
|
8
|
+
renders_one :menu_content, "Shadcn::DropdownMenu::Content::Component"
|
|
9
|
+
|
|
10
|
+
slot_name :"dropdown-menu"
|
|
11
|
+
|
|
12
|
+
attr_reader :open, :side, :align, :side_offset, :align_offset, :loop
|
|
13
|
+
|
|
14
|
+
# `loop` is Radix's own prop, declared on MenuContentImpl and documented
|
|
15
|
+
# `@defaultValue false` (vendor/radix/ui/menu.tsx:363-368). It rides here
|
|
16
|
+
# rather than on Content for the same reason `side` and `align` do: one
|
|
17
|
+
# Stimulus controller owns the whole family, and the root is where it is
|
|
18
|
+
# attached.
|
|
19
|
+
def initialize(open: false, side: :bottom, align: :start, side_offset: 4,
|
|
20
|
+
align_offset: 0, loop: false, **attributes)
|
|
21
|
+
@open = open
|
|
22
|
+
@side = side&.to_sym || :bottom
|
|
23
|
+
@align = align&.to_sym || :start
|
|
24
|
+
@side_offset = side_offset
|
|
25
|
+
@align_offset = align_offset
|
|
26
|
+
@loop = loop
|
|
27
|
+
super(**attributes)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def element_attributes(**defaults)
|
|
31
|
+
super(**{
|
|
32
|
+
style: merged_style(CONTENTS_STYLE),
|
|
33
|
+
"data-controller" => "shadcn--dropdown-menu",
|
|
34
|
+
"data-shadcn--dropdown-menu-open-value" => open,
|
|
35
|
+
"data-shadcn--dropdown-menu-side-value" => side,
|
|
36
|
+
"data-shadcn--dropdown-menu-align-value" => align,
|
|
37
|
+
"data-shadcn--dropdown-menu-side-offset-value" => side_offset,
|
|
38
|
+
"data-shadcn--dropdown-menu-align-offset-value" => align_offset,
|
|
39
|
+
"data-shadcn--dropdown-menu-loop-value" => loop
|
|
40
|
+
}.merge(defaults))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def call
|
|
44
|
+
render_element(body: safe_join([ trigger, menu_content, content ].compact))
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module DropdownMenu
|
|
5
|
+
module Content
|
|
6
|
+
# DropdownMenuContent
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
renders_many :items, "Shadcn::DropdownMenu::Item::Component"
|
|
9
|
+
|
|
10
|
+
slot_name :"dropdown-menu-content"
|
|
11
|
+
|
|
12
|
+
style do
|
|
13
|
+
base {
|
|
14
|
+
"z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] " \
|
|
15
|
+
"origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden " \
|
|
16
|
+
"overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground " \
|
|
17
|
+
"shadow-md data-[side=bottom]:slide-in-from-top-2 " \
|
|
18
|
+
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 " \
|
|
19
|
+
"data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out " \
|
|
20
|
+
"data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 " \
|
|
21
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 " \
|
|
22
|
+
"data-[state=open]:zoom-in-95"
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def element_attributes(**defaults)
|
|
27
|
+
super(**{
|
|
28
|
+
role: "menu",
|
|
29
|
+
tabindex: "-1",
|
|
30
|
+
"aria-orientation" => "vertical",
|
|
31
|
+
"data-state" => "closed",
|
|
32
|
+
hidden: true,
|
|
33
|
+
"data-shadcn--dropdown-menu-target" => "content",
|
|
34
|
+
"data-action" => "keydown->shadcn--dropdown-menu#contentKeydown"
|
|
35
|
+
}.merge(defaults))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# shadcn wraps the content in a DropdownMenuPortal. Radix relocates it to
|
|
39
|
+
# `document.body`; here it stays put (see the Stimulus controller for
|
|
40
|
+
# why) and is `display: contents`, so it adds no box of its own.
|
|
41
|
+
def call
|
|
42
|
+
tag.div("data-slot": "dropdown-menu-portal", style: CONTENTS_STYLE) do
|
|
43
|
+
render_element(body: safe_join([ items, content ].flatten.compact))
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module DropdownMenu
|
|
5
|
+
module Group
|
|
6
|
+
# DropdownMenuGroup
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
slot_name :"dropdown-menu-group"
|
|
9
|
+
|
|
10
|
+
def element_attributes(**defaults)
|
|
11
|
+
super(**{ role: "group" }.merge(defaults))
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module DropdownMenu
|
|
5
|
+
module Item
|
|
6
|
+
# DropdownMenuItem
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
slot_name :"dropdown-menu-item"
|
|
9
|
+
|
|
10
|
+
style do
|
|
11
|
+
base {
|
|
12
|
+
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm " \
|
|
13
|
+
"outline-hidden select-none focus:bg-accent focus:text-accent-foreground " \
|
|
14
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50 " \
|
|
15
|
+
"data-[inset]:pl-8 data-[variant=destructive]:text-destructive " \
|
|
16
|
+
"data-[variant=destructive]:focus:bg-destructive/10 " \
|
|
17
|
+
"data-[variant=destructive]:focus:text-destructive " \
|
|
18
|
+
"dark:data-[variant=destructive]:focus:bg-destructive/20 " \
|
|
19
|
+
"[&_svg]:pointer-events-none [&_svg]:shrink-0 " \
|
|
20
|
+
"[&_svg:not([class*='size-'])]:size-4 " \
|
|
21
|
+
"[&_svg:not([class*='text-'])]:text-muted-foreground " \
|
|
22
|
+
"data-[variant=destructive]:*:[svg]:text-destructive!"
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
attr_reader :variant, :inset, :disabled
|
|
27
|
+
|
|
28
|
+
def initialize(variant: :default, inset: false, disabled: false, **attributes)
|
|
29
|
+
@variant = variant&.to_sym || :default
|
|
30
|
+
@inset = inset
|
|
31
|
+
@disabled = disabled
|
|
32
|
+
super(**attributes)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def element_attributes(**defaults)
|
|
36
|
+
super(**{
|
|
37
|
+
role: "menuitem",
|
|
38
|
+
tabindex: "-1",
|
|
39
|
+
"data-variant" => variant,
|
|
40
|
+
"data-inset" => (true if inset),
|
|
41
|
+
"data-disabled" => (true if disabled),
|
|
42
|
+
"data-shadcn--dropdown-menu-target" => "item",
|
|
43
|
+
"data-action" => "click->shadcn--dropdown-menu#select " \
|
|
44
|
+
"pointerenter->shadcn--dropdown-menu#pointerenter"
|
|
45
|
+
}.merge(defaults))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module DropdownMenu
|
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
|
6
|
+
def default
|
|
7
|
+
render_with_template
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Upstream's "Checkboxes", "Radio Group" and "Destructive".
|
|
11
|
+
def checkboxes_and_radio
|
|
12
|
+
render_with_template
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<%# Upstream's "Checkboxes", "Radio Group" and "Destructive", none of which the
|
|
2
|
+
default preview shows: it has the label, the items, the separators and the
|
|
3
|
+
shortcuts, and stops there.
|
|
4
|
+
|
|
5
|
+
A checkbox item keeps the menu open when chosen and a radio item replaces
|
|
6
|
+
whichever of its group was set — both are the menu's own behaviour rather
|
|
7
|
+
than markup, and both are the dropdown controller's. %>
|
|
8
|
+
<div class="flex items-center gap-2">
|
|
9
|
+
<%= render(Shadcn::DropdownMenu::Component.new) do |m| %>
|
|
10
|
+
<% m.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { "View" } %>
|
|
11
|
+
<% m.with_menu_content(class: "w-56") do %>
|
|
12
|
+
<%= render(Shadcn::DropdownMenu::Label::Component.new) { "Appearance" } %>
|
|
13
|
+
<%= render(Shadcn::DropdownMenu::Separator::Component.new) %>
|
|
14
|
+
<%= render(Shadcn::DropdownMenu::CheckboxItem::Component.new(checked: true)) { "Status bar" } %>
|
|
15
|
+
<%= render(Shadcn::DropdownMenu::CheckboxItem::Component.new) { "Activity bar" } %>
|
|
16
|
+
<%= render(Shadcn::DropdownMenu::CheckboxItem::Component.new(disabled: true)) { "Panel — not available" } %>
|
|
17
|
+
<% end %>
|
|
18
|
+
<% end %>
|
|
19
|
+
|
|
20
|
+
<%= render(Shadcn::DropdownMenu::Component.new) do |m| %>
|
|
21
|
+
<% m.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { "Panel position" } %>
|
|
22
|
+
<% m.with_menu_content(class: "w-56") do %>
|
|
23
|
+
<%= render(Shadcn::DropdownMenu::Label::Component.new) { "Position" } %>
|
|
24
|
+
<%= render(Shadcn::DropdownMenu::Separator::Component.new) %>
|
|
25
|
+
<%= render(Shadcn::DropdownMenu::RadioGroup::Component.new) do %>
|
|
26
|
+
<% %w[Top Bottom Right].each do |side| %>
|
|
27
|
+
<%= render(Shadcn::DropdownMenu::RadioItem::Component.new(value: side.downcase, checked: side == "Bottom")) { side } %>
|
|
28
|
+
<% end %>
|
|
29
|
+
<% end %>
|
|
30
|
+
<%= render(Shadcn::DropdownMenu::Separator::Component.new) %>
|
|
31
|
+
<%= render(Shadcn::DropdownMenu::Item::Component.new(variant: :destructive)) { "Reset layout" } %>
|
|
32
|
+
<% end %>
|
|
33
|
+
<% end %>
|
|
34
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<%= render(Shadcn::DropdownMenu::Component.new) do |m| %>
|
|
2
|
+
<% m.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { "Open menu" } %>
|
|
3
|
+
<%# Items go in the block rather than through the `item` slot, so the label
|
|
4
|
+
and separators keep their place between them. %>
|
|
5
|
+
<% m.with_menu_content(class: "w-56") do %>
|
|
6
|
+
<%= render(Shadcn::DropdownMenu::Label::Component.new) { "My Account" } %>
|
|
7
|
+
<%= render(Shadcn::DropdownMenu::Separator::Component.new) %>
|
|
8
|
+
<%= render(Shadcn::DropdownMenu::Group::Component.new) do %>
|
|
9
|
+
<%= render(Shadcn::DropdownMenu::Item::Component.new) do %>
|
|
10
|
+
Profile
|
|
11
|
+
<%= render(Shadcn::DropdownMenu::Shortcut::Component.new) { "⌘P" } %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<%= render(Shadcn::DropdownMenu::Item::Component.new) { "Billing" } %>
|
|
14
|
+
<%# "Settings" and "Support" share an initial on purpose: without two
|
|
15
|
+
entries starting with the same letter, a browser spec cannot tell
|
|
16
|
+
typeahead's repeat-cycling from always landing on the first match. %>
|
|
17
|
+
<%= render(Shadcn::DropdownMenu::Item::Component.new) { "Settings" } %>
|
|
18
|
+
<%= render(Shadcn::DropdownMenu::Item::Component.new) { "Support" } %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<%= render(Shadcn::DropdownMenu::Separator::Component.new) %>
|
|
21
|
+
<%= render(Shadcn::DropdownMenu::Item::Component.new(variant: :destructive)) { "Log out" } %>
|
|
22
|
+
<% end %>
|
|
23
|
+
<% end %>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module DropdownMenu
|
|
5
|
+
module RadioGroup
|
|
6
|
+
# DropdownMenuRadioGroup
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
slot_name :"dropdown-menu-radio-group"
|
|
9
|
+
|
|
10
|
+
def element_attributes(**defaults)
|
|
11
|
+
super(**{ role: "group" }.merge(defaults))
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|