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,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Select
|
|
5
|
+
module Trigger
|
|
6
|
+
# SelectTrigger
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
CHEVRON_CLASSES = "size-4 opacity-50"
|
|
9
|
+
|
|
10
|
+
renders_one :value, "Shadcn::Select::Value::Component"
|
|
11
|
+
|
|
12
|
+
default_tag :button
|
|
13
|
+
slot_name :"select-trigger"
|
|
14
|
+
|
|
15
|
+
style do
|
|
16
|
+
base {
|
|
17
|
+
"flex w-fit items-center justify-between gap-2 rounded-md border border-input " \
|
|
18
|
+
"bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs " \
|
|
19
|
+
"transition-[color,box-shadow] outline-none focus-visible:border-ring " \
|
|
20
|
+
"focus-visible:ring-[3px] focus-visible:ring-ring/50 " \
|
|
21
|
+
"disabled:cursor-not-allowed disabled:opacity-50 " \
|
|
22
|
+
"aria-invalid:border-destructive aria-invalid:ring-destructive/20 " \
|
|
23
|
+
"data-[placeholder]:text-muted-foreground data-[size=default]:h-9 " \
|
|
24
|
+
"data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 " \
|
|
25
|
+
"*:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center " \
|
|
26
|
+
"*:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 " \
|
|
27
|
+
"dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none " \
|
|
28
|
+
"[&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 " \
|
|
29
|
+
"[&_svg:not([class*='text-'])]:text-muted-foreground"
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_reader :size, :placeholder, :disabled, :searchable
|
|
34
|
+
|
|
35
|
+
def initialize(size: :default, placeholder: true, disabled: false,
|
|
36
|
+
searchable: false, **attributes)
|
|
37
|
+
@size = size&.to_sym || :default
|
|
38
|
+
@placeholder = placeholder
|
|
39
|
+
@disabled = disabled
|
|
40
|
+
@searchable = searchable
|
|
41
|
+
super(**attributes)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def element_attributes(**defaults)
|
|
45
|
+
super(**{
|
|
46
|
+
type: "button",
|
|
47
|
+
# A searchable select's trigger is a plain button announcing a
|
|
48
|
+
# listbox popup: the typing happens in the field inside the popover,
|
|
49
|
+
# not here. shadcn's aria variant emits it that way, and it has the
|
|
50
|
+
# side benefit that a role-less button can take its accessible name
|
|
51
|
+
# from its own text, which `role="combobox"` cannot.
|
|
52
|
+
role: ("combobox" unless searchable),
|
|
53
|
+
disabled: (true if disabled),
|
|
54
|
+
"aria-expanded" => "false",
|
|
55
|
+
"aria-haspopup" => ("listbox" if searchable),
|
|
56
|
+
"aria-autocomplete" => ("none" unless searchable),
|
|
57
|
+
"data-size" => size,
|
|
58
|
+
"data-state" => "closed",
|
|
59
|
+
"data-placeholder" => (true if placeholder),
|
|
60
|
+
"data-shadcn--select-target" => "trigger",
|
|
61
|
+
"data-action" => "click->shadcn--select#toggle " \
|
|
62
|
+
"keydown->shadcn--select#triggerKeydown"
|
|
63
|
+
}.merge(defaults))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def call
|
|
67
|
+
render_element(body: safe_join([ value, content, chevron ].compact))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def chevron
|
|
73
|
+
render(Icon::Component.new("chevron-down", class: CHEVRON_CLASSES))
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Select
|
|
5
|
+
module Value
|
|
6
|
+
# SelectValue — the controller writes the chosen item's label in here.
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
default_tag :span
|
|
9
|
+
slot_name :"select-value"
|
|
10
|
+
|
|
11
|
+
attr_reader :placeholder
|
|
12
|
+
|
|
13
|
+
def initialize(placeholder: nil, **attributes)
|
|
14
|
+
@placeholder = placeholder
|
|
15
|
+
super(**attributes)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def element_attributes(**defaults)
|
|
19
|
+
super(**{ "data-shadcn--select-target" => "value" }.merge(defaults))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def call
|
|
23
|
+
render_element(body: content.presence || placeholder)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
# The parts of the Select family that are just an element with a
|
|
5
|
+
# `data-slot` and a fixed set of classes. Anything with variants, slots or
|
|
6
|
+
# markup of its own keeps its own `component.rb`.
|
|
7
|
+
module Select
|
|
8
|
+
extend Parts
|
|
9
|
+
|
|
10
|
+
part :label, slot: "select-label", classes: "px-2 py-1.5 text-xs text-muted-foreground"
|
|
11
|
+
|
|
12
|
+
part :separator, slot: "select-separator",
|
|
13
|
+
classes: "pointer-events-none -mx-1 my-1 h-px bg-border"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Separator
|
|
5
|
+
# Port of registry/new-york-v4/ui/separator.tsx
|
|
6
|
+
#
|
|
7
|
+
# Reproduces Radix's semantics: a decorative separator is `role="none"`,
|
|
8
|
+
# a meaningful one is `role="separator"` and only advertises
|
|
9
|
+
# `aria-orientation` when vertical.
|
|
10
|
+
class Component < ApplicationViewComponent
|
|
11
|
+
slot_name :separator
|
|
12
|
+
|
|
13
|
+
style do
|
|
14
|
+
base {
|
|
15
|
+
"shrink-0 bg-border data-[orientation=horizontal]:h-px " \
|
|
16
|
+
"data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full " \
|
|
17
|
+
"data-[orientation=vertical]:w-px"
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
attr_reader :orientation, :decorative
|
|
22
|
+
|
|
23
|
+
def initialize(orientation: :horizontal, decorative: true, **attributes)
|
|
24
|
+
@orientation = orientation.to_sym
|
|
25
|
+
@decorative = decorative
|
|
26
|
+
super(**attributes)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def element_attributes(**defaults)
|
|
30
|
+
semantics =
|
|
31
|
+
if decorative
|
|
32
|
+
{ role: "none" }
|
|
33
|
+
else
|
|
34
|
+
{ role: "separator", "aria-orientation" => (orientation.to_s if orientation == :vertical) }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
super(**{ "data-orientation" => orientation }.merge(semantics).merge(defaults))
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<div class="max-w-sm">
|
|
2
|
+
<div class="text-sm font-medium">Radix Primitives</div>
|
|
3
|
+
<%= render(Shadcn::Separator::Component.new(class: "my-4")) %>
|
|
4
|
+
<div class="flex h-5 items-center gap-4 text-sm">
|
|
5
|
+
<div>Blog</div>
|
|
6
|
+
<%= render(Shadcn::Separator::Component.new(orientation: :vertical)) %>
|
|
7
|
+
<div>Docs</div>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Sheet
|
|
5
|
+
# Port of registry/new-york-v4/ui/sheet.tsx — shadcn builds the Sheet on the
|
|
6
|
+
# very same Radix Dialog primitive, so the port shares its behaviour.
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
include Concerns::ModalRoot
|
|
9
|
+
|
|
10
|
+
renders_one :trigger, "Shadcn::Sheet::Trigger::Component"
|
|
11
|
+
renders_one :dialog_content, "Shadcn::Sheet::Content::Component"
|
|
12
|
+
|
|
13
|
+
slot_name :sheet
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Sheet
|
|
5
|
+
module Content
|
|
6
|
+
# SheetContent — slides in from one of the four edges.
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
CLOSE_CLASSES = "absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background " \
|
|
9
|
+
"transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring " \
|
|
10
|
+
"focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none " \
|
|
11
|
+
"data-[state=open]:bg-secondary"
|
|
12
|
+
|
|
13
|
+
renders_one :header, "Shadcn::Sheet::Header::Component"
|
|
14
|
+
renders_one :footer, "Shadcn::Sheet::Footer::Component"
|
|
15
|
+
|
|
16
|
+
slot_name :"sheet-content"
|
|
17
|
+
|
|
18
|
+
style do
|
|
19
|
+
base {
|
|
20
|
+
"fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out " \
|
|
21
|
+
"data-[state=closed]:animate-out data-[state=closed]:duration-300 " \
|
|
22
|
+
"data-[state=open]:animate-in data-[state=open]:duration-500"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
variants {
|
|
26
|
+
side {
|
|
27
|
+
right {
|
|
28
|
+
"inset-y-0 right-0 h-full w-3/4 border-l " \
|
|
29
|
+
"data-[state=closed]:slide-out-to-right " \
|
|
30
|
+
"data-[state=open]:slide-in-from-right sm:max-w-sm"
|
|
31
|
+
}
|
|
32
|
+
left {
|
|
33
|
+
"inset-y-0 left-0 h-full w-3/4 border-r " \
|
|
34
|
+
"data-[state=closed]:slide-out-to-left " \
|
|
35
|
+
"data-[state=open]:slide-in-from-left sm:max-w-sm"
|
|
36
|
+
}
|
|
37
|
+
top {
|
|
38
|
+
"inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top " \
|
|
39
|
+
"data-[state=open]:slide-in-from-top"
|
|
40
|
+
}
|
|
41
|
+
bottom {
|
|
42
|
+
"inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom " \
|
|
43
|
+
"data-[state=open]:slide-in-from-bottom"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
defaults { { side: :right } }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
attr_reader :side, :show_close_button
|
|
52
|
+
|
|
53
|
+
def initialize(side: :right, show_close_button: true, **attributes)
|
|
54
|
+
@side = side&.to_sym || :right
|
|
55
|
+
@show_close_button = show_close_button
|
|
56
|
+
super(**attributes)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def style_variants
|
|
60
|
+
{ side: }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def element_attributes(**defaults)
|
|
64
|
+
super(**{
|
|
65
|
+
role: "dialog",
|
|
66
|
+
"aria-modal" => "true",
|
|
67
|
+
tabindex: "-1",
|
|
68
|
+
"data-state" => "closed",
|
|
69
|
+
hidden: true,
|
|
70
|
+
"data-shadcn--dialog-target" => "content"
|
|
71
|
+
}.merge(defaults))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def call
|
|
75
|
+
tag.div("data-slot": "sheet-portal", style: CONTENTS_STYLE) do
|
|
76
|
+
safe_join([
|
|
77
|
+
render(Overlay::Component.new),
|
|
78
|
+
render_element(body: safe_join([ header, content, footer, close_button ].compact))
|
|
79
|
+
])
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def close_button
|
|
86
|
+
return unless show_close_button
|
|
87
|
+
|
|
88
|
+
render(Close::Component.new(class: CLOSE_CLASSES)) do
|
|
89
|
+
safe_join([
|
|
90
|
+
render(Icon::Component.new("x", class: "size-4")),
|
|
91
|
+
tag.span(shadcn_t("dialog.close"), class: "sr-only")
|
|
92
|
+
])
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Sheet
|
|
5
|
+
module Header
|
|
6
|
+
# SheetHeader
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
renders_one :title, "Shadcn::Sheet::Title::Component"
|
|
9
|
+
renders_one :description, "Shadcn::Sheet::Description::Component"
|
|
10
|
+
|
|
11
|
+
slot_name :"sheet-header"
|
|
12
|
+
|
|
13
|
+
style do
|
|
14
|
+
base { "flex flex-col gap-1.5 p-4" }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call
|
|
18
|
+
render_element(body: safe_join([ title, description, content ].compact))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Sheet
|
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
|
6
|
+
def default
|
|
7
|
+
render_with_template
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Upstream's "No Close Button".
|
|
11
|
+
def no_close_button
|
|
12
|
+
render_with_template
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div class="flex items-center gap-2">
|
|
2
|
+
<% %i[right left top bottom].each do |side| %>
|
|
3
|
+
<%= render(Shadcn::Sheet::Component.new) do |s| %>
|
|
4
|
+
<% s.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { side.to_s.capitalize } %>
|
|
5
|
+
<% s.with_dialog_content(side:) do |c| %>
|
|
6
|
+
<% c.with_header do |h| %>
|
|
7
|
+
<% h.with_title { "Edit profile" } %>
|
|
8
|
+
<% h.with_description { "Make changes to your profile here." } %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<% c.with_footer do %>
|
|
11
|
+
<%= render(Shadcn::Sheet::Close::Component.new(class: Shadcn::Button::Component.variant_classes(variant: :outline))) { "Close" } %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% end %>
|
|
14
|
+
<% end %>
|
|
15
|
+
<% end %>
|
|
16
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<%# Upstream's "No Close Button": the corner dismiss left out, so the panel is
|
|
2
|
+
closed from its own footer, from Escape, or from outside. %>
|
|
3
|
+
<%= render(Shadcn::Sheet::Component.new) do |s| %>
|
|
4
|
+
<% s.with_trigger(class: Shadcn::Button::Component.variant_classes(variant: :outline)) { "Open" } %>
|
|
5
|
+
<% s.with_dialog_content(show_close_button: false) do |c| %>
|
|
6
|
+
<% c.with_header do |h| %>
|
|
7
|
+
<% h.with_title { "Filters" } %>
|
|
8
|
+
<% h.with_description { "Narrow the list down." } %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<% c.with_footer do %>
|
|
11
|
+
<%= render(Shadcn::Sheet::Close::Component.new(class: Shadcn::Button::Component.variant_classes(variant: :outline))) { "Done" } %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% end %>
|
|
14
|
+
<% end %>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
# The parts of the Sheet family that are just an element with a
|
|
5
|
+
# `data-slot` and a fixed set of classes. Anything with variants, slots or
|
|
6
|
+
# markup of its own keeps its own `component.rb`.
|
|
7
|
+
module Sheet
|
|
8
|
+
extend Parts
|
|
9
|
+
|
|
10
|
+
part :close, slot: "sheet-close", from: Dialog::Close::Component
|
|
11
|
+
|
|
12
|
+
part :description, tag: :p, slot: "sheet-description", classes: "text-sm text-muted-foreground"
|
|
13
|
+
|
|
14
|
+
part :footer, slot: "sheet-footer", classes: "mt-auto flex flex-col gap-2 p-4"
|
|
15
|
+
|
|
16
|
+
part :overlay, slot: "sheet-overlay", from: Dialog::Overlay::Component
|
|
17
|
+
|
|
18
|
+
part :title, tag: :h2, slot: "sheet-title", classes: "font-semibold text-foreground"
|
|
19
|
+
|
|
20
|
+
part :trigger, slot: "sheet-trigger", from: Dialog::Trigger::Component
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Sidebar
|
|
5
|
+
# The panel itself — upstream's `Sidebar` (vendor/shadcn/ui/sidebar.tsx:154),
|
|
6
|
+
# not its provider, which is `Sidebar::Provider::Component`.
|
|
7
|
+
#
|
|
8
|
+
# Upstream renders three different trees here and picks between them while
|
|
9
|
+
# rendering. Two of those choices are knowable on a server and one is not:
|
|
10
|
+
#
|
|
11
|
+
# collapsible: :none a bare panel, decided here
|
|
12
|
+
# isMobile a Sheet, decided by `matchMedia` — so not here
|
|
13
|
+
#
|
|
14
|
+
# The mobile branch is the controller's, applied to this same DOM without
|
|
15
|
+
# moving it. See decisions/02-javascript.md.
|
|
16
|
+
class Component < ApplicationViewComponent
|
|
17
|
+
slot_name :sidebar
|
|
18
|
+
|
|
19
|
+
style do
|
|
20
|
+
base { "group peer hidden text-sidebar-foreground md:block" }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
attr_reader :side, :variant, :collapsible
|
|
24
|
+
|
|
25
|
+
def initialize(side: :left, variant: :sidebar, collapsible: :offcanvas, **attributes)
|
|
26
|
+
@side = side&.to_sym || :left
|
|
27
|
+
@variant = variant&.to_sym || :sidebar
|
|
28
|
+
@collapsible = collapsible&.to_sym || :offcanvas
|
|
29
|
+
super(**attributes)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def element_attributes(**defaults)
|
|
33
|
+
return super(**defaults) if bare?
|
|
34
|
+
|
|
35
|
+
super(**{
|
|
36
|
+
"data-shadcn--sidebar-target" => "sidebar",
|
|
37
|
+
"data-state" => "expanded",
|
|
38
|
+
# Upstream fills this only while collapsed (sidebar.tsx:212) — the
|
|
39
|
+
# classes match `group-data-[collapsible=offcanvas]:…`, so a value here
|
|
40
|
+
# while expanded would style an open panel as a closed one. The value
|
|
41
|
+
# to collapse *to* therefore has to live somewhere else.
|
|
42
|
+
"data-collapsible" => "",
|
|
43
|
+
"data-sidebar-collapsible" => collapsible,
|
|
44
|
+
"data-variant" => variant,
|
|
45
|
+
"data-side" => side
|
|
46
|
+
}.merge(defaults))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# `collapsible: :none` is a different element with different classes, not
|
|
50
|
+
# the same one with a flag (sidebar.tsx:166-180).
|
|
51
|
+
def css_classes(extra = nil)
|
|
52
|
+
return super if !bare?
|
|
53
|
+
|
|
54
|
+
ShadcnViewComponent.cn(
|
|
55
|
+
"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground", extra
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def call
|
|
60
|
+
return render_element(body: content) if bare?
|
|
61
|
+
|
|
62
|
+
render_element(body: safe_join([ overlay, gap, container ]))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def bare? = collapsible == :none
|
|
68
|
+
|
|
69
|
+
# The dimmed backdrop upstream gets for free by rendering a real `Sheet`
|
|
70
|
+
# below `md` (sidebar.tsx:184). There is no Sheet here — this panel *is*
|
|
71
|
+
# the sheet — so the element it would have portalled has to be in the
|
|
72
|
+
# markup, hidden, from the start. It is the gem's own `sheet-overlay`,
|
|
73
|
+
# classes and all, rather than a new slot: a host styling `sheet-overlay`
|
|
74
|
+
# should reach this one too.
|
|
75
|
+
#
|
|
76
|
+
# `hidden` until the controller opens the sheet, and it stays in the
|
|
77
|
+
# server's markup on desktop, where nothing ever unhides it. The dialog
|
|
78
|
+
# target it inherits is cleared: this one answers to the sidebar.
|
|
79
|
+
def overlay
|
|
80
|
+
render(
|
|
81
|
+
Shadcn::Sheet::Overlay::Component.new(
|
|
82
|
+
"data-shadcn--dialog-target": nil,
|
|
83
|
+
"data-shadcn--sidebar-target": "overlay"
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def gap
|
|
89
|
+
tag.div("data-slot": "sidebar-gap", class: gap_classes)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def gap_classes
|
|
93
|
+
floating = "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
|
|
94
|
+
plain = "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
|
|
95
|
+
|
|
96
|
+
ShadcnViewComponent.cn(
|
|
97
|
+
"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
|
|
98
|
+
"group-data-[collapsible=offcanvas]:w-0",
|
|
99
|
+
"group-data-[side=right]:rotate-180",
|
|
100
|
+
inset_like? ? floating : plain,
|
|
101
|
+
# This element exists to reserve the panel's width in the page's flow.
|
|
102
|
+
# A sheet overlays the page instead, so on the mobile branch it has to
|
|
103
|
+
# reserve nothing. The Popover API already takes the panel out of flow
|
|
104
|
+
# while the sheet is open, which makes this redundant there and load
|
|
105
|
+
# -bearing everywhere else: `top_layer.js` is feature-detected, and the
|
|
106
|
+
# fallback leaves the panel in flow.
|
|
107
|
+
"group-data-[mobile=true]:w-0"
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def container
|
|
112
|
+
tag.div(
|
|
113
|
+
safe_join([ sheet_header, inner ]),
|
|
114
|
+
"data-slot": "sidebar-container",
|
|
115
|
+
# The element that animates, so the controller has to be able to write
|
|
116
|
+
# `data-state` on it and wait for its animations to settle.
|
|
117
|
+
"data-shadcn--sidebar-target": "container",
|
|
118
|
+
# Read by the controller when it turns this panel into a sheet: a
|
|
119
|
+
# dialog needs a name, and the name has to exist before it is pointed
|
|
120
|
+
# at.
|
|
121
|
+
"data-sheet-title" => sheet_title_id,
|
|
122
|
+
"data-sheet-description" => sheet_description_id,
|
|
123
|
+
class: container_classes
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# The name and the description a Sheet gives the mobile sidebar
|
|
128
|
+
# (sidebar.tsx:198-201), which upstream renders only in its mobile tree.
|
|
129
|
+
# There is one tree here, so they are always in the markup and `hidden`
|
|
130
|
+
# until the controller opens the sheet: `hidden` keeps them out of the
|
|
131
|
+
# accessibility tree entirely, where `sr-only` alone would have a desktop
|
|
132
|
+
# screen reader read "Sidebar. Displays the mobile sidebar." in the middle
|
|
133
|
+
# of a page with no sheet on it.
|
|
134
|
+
#
|
|
135
|
+
# The ids are here rather than generated in JavaScript because the
|
|
136
|
+
# elements are: `aria-labelledby` has to point at something the server
|
|
137
|
+
# rendered.
|
|
138
|
+
def sheet_header
|
|
139
|
+
tag.div(
|
|
140
|
+
safe_join([
|
|
141
|
+
tag.h2(shadcn_t("sidebar.title"), id: sheet_title_id, "data-slot": "sheet-title"),
|
|
142
|
+
tag.p(shadcn_t("sidebar.description"), id: sheet_description_id, "data-slot": "sheet-description")
|
|
143
|
+
]),
|
|
144
|
+
class: "sr-only",
|
|
145
|
+
hidden: true,
|
|
146
|
+
"data-slot": "sheet-header",
|
|
147
|
+
"data-shadcn--sidebar-target": "sheetHeader"
|
|
148
|
+
)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def sheet_title_id = @sheet_title_id ||= "shadcn-sidebar-title-#{SecureRandom.hex(4)}"
|
|
152
|
+
def sheet_description_id = @sheet_description_id ||= "shadcn-sidebar-description-#{SecureRandom.hex(4)}"
|
|
153
|
+
|
|
154
|
+
def container_classes
|
|
155
|
+
ShadcnViewComponent.cn(
|
|
156
|
+
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) " \
|
|
157
|
+
"transition-[left,right,width] duration-200 ease-linear md:flex",
|
|
158
|
+
side_classes,
|
|
159
|
+
padding_classes,
|
|
160
|
+
# Upstream renders a Sheet below `md` and this panel above it, so its
|
|
161
|
+
# `hidden … md:flex` is never asked to show anything on a phone. Here
|
|
162
|
+
# there is one tree and the sheet *is* this element, so the mobile
|
|
163
|
+
# branch has to turn both of those off. The controller does that for
|
|
164
|
+
# the panel's own `hidden … md:block`; nothing was doing it for the
|
|
165
|
+
# container inside, which is why the sheet opened onto an empty strip.
|
|
166
|
+
#
|
|
167
|
+
# A `group-data-` variant rather than the inline `display` used on the
|
|
168
|
+
# panel: both are two-class selectors, so they outrank `md:flex` at
|
|
169
|
+
# every width without the specificity fight a bare class would lose.
|
|
170
|
+
"group-data-[mobile=true]:flex group-data-[mobile=true]:w-(--sidebar-width-mobile)",
|
|
171
|
+
# `z-50` and `shadow-lg` are `sheet-content`'s (sheet.tsx:63), and the
|
|
172
|
+
# overlay above carries `z-50` too — so the two match upstream's pair
|
|
173
|
+
# and DOM order decides, which puts the panel over its own backdrop.
|
|
174
|
+
# The desktop `z-10` would put it under.
|
|
175
|
+
"group-data-[mobile=true]:z-50 group-data-[mobile=true]:shadow-lg",
|
|
176
|
+
sheet_animation_classes
|
|
177
|
+
)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# `sheet-content`'s own entrance and exit (sheet.tsx:63-68), keyed the way
|
|
181
|
+
# upstream keys them: on the element's *own* `data-state`, which the
|
|
182
|
+
# controller writes only on the mobile branch. On desktop the attribute is
|
|
183
|
+
# absent, so none of this matches and the panel keeps sliding on the
|
|
184
|
+
# `transition-[left,right,width]` above instead.
|
|
185
|
+
#
|
|
186
|
+
# The panel's `data-state` is a different axis — expanded or collapsed —
|
|
187
|
+
# which is why this one is on the container rather than up there.
|
|
188
|
+
def sheet_animation_classes
|
|
189
|
+
slide =
|
|
190
|
+
if side == :left
|
|
191
|
+
"data-[state=open]:slide-in-from-left data-[state=closed]:slide-out-to-left"
|
|
192
|
+
else
|
|
193
|
+
"data-[state=open]:slide-in-from-right data-[state=closed]:slide-out-to-right"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out " \
|
|
197
|
+
"data-[state=open]:duration-500 data-[state=closed]:duration-300 #{slide}"
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def side_classes
|
|
201
|
+
if side == :left
|
|
202
|
+
"left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
|
|
203
|
+
else
|
|
204
|
+
"right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]"
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def padding_classes
|
|
209
|
+
if inset_like?
|
|
210
|
+
"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
|
|
211
|
+
else
|
|
212
|
+
"group-data-[collapsible=icon]:w-(--sidebar-width-icon) " \
|
|
213
|
+
"group-data-[side=left]:border-r group-data-[side=right]:border-l"
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def inner
|
|
218
|
+
tag.div(
|
|
219
|
+
content,
|
|
220
|
+
"data-sidebar": "sidebar",
|
|
221
|
+
"data-slot": "sidebar-inner",
|
|
222
|
+
class: "flex h-full w-full flex-col bg-sidebar " \
|
|
223
|
+
"group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border " \
|
|
224
|
+
"group-data-[variant=floating]:border-sidebar-border " \
|
|
225
|
+
"group-data-[variant=floating]:shadow-sm"
|
|
226
|
+
)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def inset_like? = [ :floating, :inset ].include?(variant)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Sidebar
|
|
5
|
+
module Input
|
|
6
|
+
# SidebarInput — the ported Input under another `data-slot`, with the
|
|
7
|
+
# sidebar's own sizing on top. Inherit-and-restamp, as ButtonGroupSeparator
|
|
8
|
+
# does to Separator, so the parent's classes are not restated and cannot
|
|
9
|
+
# rot.
|
|
10
|
+
class Component < Shadcn::Input::Component
|
|
11
|
+
slot_name :"sidebar-input"
|
|
12
|
+
|
|
13
|
+
EXTRA_CLASSES = "h-8 w-full bg-background shadow-none"
|
|
14
|
+
|
|
15
|
+
def css_classes(extra = nil)
|
|
16
|
+
super([ EXTRA_CLASSES, extra ].compact.join(" "))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def element_attributes(**defaults)
|
|
20
|
+
super(**{ "data-sidebar" => "input" }.merge(defaults))
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|