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,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module RadioGroup
|
|
5
|
+
module Item
|
|
6
|
+
# RadioGroupItem
|
|
7
|
+
class Component < ApplicationViewComponent
|
|
8
|
+
INDICATOR_CLASSES = "relative flex items-center justify-center"
|
|
9
|
+
DOT_CLASSES = "absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 " \
|
|
10
|
+
"fill-primary"
|
|
11
|
+
|
|
12
|
+
default_tag :button
|
|
13
|
+
slot_name :"radio-group-item"
|
|
14
|
+
|
|
15
|
+
style do
|
|
16
|
+
base {
|
|
17
|
+
"aspect-square size-4 shrink-0 rounded-full border border-input text-primary " \
|
|
18
|
+
"shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring " \
|
|
19
|
+
"focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed " \
|
|
20
|
+
"disabled:opacity-50 aria-invalid:border-destructive " \
|
|
21
|
+
"aria-invalid:ring-destructive/20 dark:bg-input/30 " \
|
|
22
|
+
"dark:aria-invalid:ring-destructive/40"
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
attr_reader :value, :checked, :disabled
|
|
27
|
+
|
|
28
|
+
def initialize(value:, checked: false, disabled: false, **attributes)
|
|
29
|
+
@value = value.to_s
|
|
30
|
+
@checked = checked
|
|
31
|
+
@disabled = disabled
|
|
32
|
+
super(**attributes)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def state
|
|
36
|
+
checked ? "checked" : "unchecked"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def element_attributes(**defaults)
|
|
40
|
+
super(**{
|
|
41
|
+
type: "button",
|
|
42
|
+
role: "radio",
|
|
43
|
+
value: value,
|
|
44
|
+
disabled: (true if disabled),
|
|
45
|
+
tabindex: (checked ? "0" : "-1"),
|
|
46
|
+
"aria-checked" => checked.to_s,
|
|
47
|
+
"data-state" => state,
|
|
48
|
+
"data-value" => value,
|
|
49
|
+
"data-disabled" => (true if disabled),
|
|
50
|
+
"data-shadcn--radio-group-target" => "item",
|
|
51
|
+
"data-action" => "click->shadcn--radio-group#select " \
|
|
52
|
+
"keydown->shadcn--radio-group#keydown"
|
|
53
|
+
}.merge(defaults))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def call
|
|
57
|
+
render_element(body: indicator)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def indicator
|
|
63
|
+
tag.span(
|
|
64
|
+
render(Icon::Component.new("circle", class: DOT_CLASSES)),
|
|
65
|
+
"data-slot": "radio-group-indicator",
|
|
66
|
+
"data-state": state,
|
|
67
|
+
hidden: (true unless checked),
|
|
68
|
+
class: INDICATOR_CLASSES
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module RadioGroup
|
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
|
6
|
+
def default
|
|
7
|
+
render_with_template
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Upstream's "Disabled" and "Invalid".
|
|
11
|
+
def states
|
|
12
|
+
render_with_template
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<%# The items are rendered in the *block*, not through the `item` slot.
|
|
2
|
+
|
|
3
|
+
Slot content is emitted before block content, so an item added through the
|
|
4
|
+
slot is hoisted out of the row it was written in and lands above every
|
|
5
|
+
label — which is what this preview did until someone looked at the page.
|
|
6
|
+
`FormBuilder#shadcn_radio_group` renders them in the block for the same
|
|
7
|
+
reason and says so. %>
|
|
8
|
+
<%= render(Shadcn::RadioGroup::Component.new(name: "plan", value: "comfortable")) do %>
|
|
9
|
+
<% [["default", "Default"], ["comfortable", "Comfortable"], ["compact", "Compact"]].each do |value, text| %>
|
|
10
|
+
<div class="flex items-center gap-2">
|
|
11
|
+
<%= render(Shadcn::RadioGroup::Item::Component.new(value:, checked: value == "comfortable", id: "r-#{value}")) %>
|
|
12
|
+
<%= render(Shadcn::Label::Component.new(for: "r-#{value}")) { text } %>
|
|
13
|
+
</div>
|
|
14
|
+
<% end %>
|
|
15
|
+
<% end %>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<%# Upstream's "Disabled" and "Invalid". Items rendered in the block rather than
|
|
2
|
+
through the slot — see the default preview for why. Disabled comes in two sizes here — the
|
|
3
|
+
whole group, and one option of an otherwise usable group — because they are
|
|
4
|
+
different things and only the second is a choice you can see and not make. %>
|
|
5
|
+
<div class="flex flex-col gap-8">
|
|
6
|
+
<div class="flex flex-col gap-2">
|
|
7
|
+
<div class="text-sm font-medium">One option is unavailable</div>
|
|
8
|
+
<%= render(Shadcn::RadioGroup::Component.new(name: "shipping", value: "standard")) do %>
|
|
9
|
+
<% [["standard", "Standard", false], ["express", "Express", false], ["same-day", "Same day — sold out", true]].each do |value, text, disabled| %>
|
|
10
|
+
<div class="flex items-center gap-2">
|
|
11
|
+
<%= render(Shadcn::RadioGroup::Item::Component.new(value:, checked: value == "standard", disabled:, id: "rs-#{value}")) %>
|
|
12
|
+
<%= render(Shadcn::Label::Component.new(for: "rs-#{value}")) { text } %>
|
|
13
|
+
</div>
|
|
14
|
+
<% end %>
|
|
15
|
+
<% end %>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="flex flex-col gap-2">
|
|
19
|
+
<div class="text-sm font-medium">The whole group is disabled</div>
|
|
20
|
+
<%= render(Shadcn::RadioGroup::Component.new(name: "billing", value: "monthly", disabled: true)) do %>
|
|
21
|
+
<% [["monthly", "Monthly"], ["yearly", "Yearly"]].each do |value, text| %>
|
|
22
|
+
<div class="flex items-center gap-2">
|
|
23
|
+
<%= render(Shadcn::RadioGroup::Item::Component.new(value:, checked: value == "monthly", id: "rb-#{value}")) %>
|
|
24
|
+
<%= render(Shadcn::Label::Component.new(for: "rb-#{value}")) { text } %>
|
|
25
|
+
</div>
|
|
26
|
+
<% end %>
|
|
27
|
+
<% end %>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="flex flex-col gap-2">
|
|
31
|
+
<div class="text-sm font-medium">Nothing chosen, and something had to be</div>
|
|
32
|
+
<%= render(Shadcn::RadioGroup::Component.new(name: "size", "aria-invalid": "true")) do %>
|
|
33
|
+
<% [["s", "Small"], ["m", "Medium"]].each do |value, text| %>
|
|
34
|
+
<div class="flex items-center gap-2">
|
|
35
|
+
<%= render(Shadcn::RadioGroup::Item::Component.new(value:, id: "rz-#{value}", "aria-invalid": "true")) %>
|
|
36
|
+
<%= render(Shadcn::Label::Component.new(for: "rz-#{value}")) { text } %>
|
|
37
|
+
</div>
|
|
38
|
+
<% end %>
|
|
39
|
+
<% end %>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Resizable
|
|
5
|
+
# Port of registry/new-york-v4/ui/resizable.tsx, whose behaviour is
|
|
6
|
+
# `react-resizable-panels` — 2,252 lines of compiled JavaScript and no
|
|
7
|
+
# dependencies of its own.
|
|
8
|
+
#
|
|
9
|
+
# What the package supplies is a drag, a keyboard and some arithmetic over
|
|
10
|
+
# `flex-grow`: panels are proportions of a flex container, so the layout is
|
|
11
|
+
# the browser's and the port only has to move two numbers when a handle is
|
|
12
|
+
# dragged. See [features/resizable.md](../../../../.claude/docs/features/resizable.md).
|
|
13
|
+
#
|
|
14
|
+
# Panels and handles are written in the block, in order, because that is
|
|
15
|
+
# what a group is — `panel, handle, panel` — and because slot content is
|
|
16
|
+
# emitted before block content, which would gather all the panels above all
|
|
17
|
+
# the handles.
|
|
18
|
+
class Component < ApplicationViewComponent
|
|
19
|
+
ORIENTATIONS = %i[horizontal vertical].freeze
|
|
20
|
+
|
|
21
|
+
default_tag :div
|
|
22
|
+
slot_name :"resizable-panel-group"
|
|
23
|
+
|
|
24
|
+
style do
|
|
25
|
+
base { "flex h-full w-full aria-[orientation=vertical]:flex-col" }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
attr_reader :orientation
|
|
29
|
+
|
|
30
|
+
# `orientation:` is upstream's `direction`, renamed to what the DOM calls
|
|
31
|
+
# it: the class above reads `aria-orientation`, and a group that says
|
|
32
|
+
# `direction` in Ruby and `orientation` in HTML is one name too many.
|
|
33
|
+
def initialize(orientation: :horizontal, **attributes)
|
|
34
|
+
@orientation = ORIENTATIONS.include?(orientation&.to_sym) ? orientation.to_sym : :horizontal
|
|
35
|
+
super(**attributes)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# No `aria-orientation`, and the direction is an inline style — which is
|
|
39
|
+
# what upstream's own DOM does, and was arrived at the hard way.
|
|
40
|
+
#
|
|
41
|
+
# The class above reads `aria-[orientation=vertical]:flex-col`, so the
|
|
42
|
+
# obvious port writes that attribute; axe then refuses it, because no role
|
|
43
|
+
# a plain group can carry supports `aria-orientation`. Reading what
|
|
44
|
+
# `react-resizable-panels` v4 actually renders settles it: the group has
|
|
45
|
+
# no role and no `aria-orientation` at all, and sets `flex-direction`
|
|
46
|
+
# inline. **The class is vestigial upstream too** — it reads an attribute
|
|
47
|
+
# the package stopped rendering. It is kept because `parity_spec` compares
|
|
48
|
+
# what upstream emits, and dropping it would claim a divergence that is
|
|
49
|
+
# not one.
|
|
50
|
+
def element_attributes(**defaults)
|
|
51
|
+
super(**{
|
|
52
|
+
"data-controller" => "shadcn--resizable",
|
|
53
|
+
"data-shadcn--resizable-orientation-value" => orientation,
|
|
54
|
+
style: merged_style(("flex-direction:column" if orientation == :vertical))
|
|
55
|
+
}.compact.merge(defaults))
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Resizable
|
|
5
|
+
module Handle
|
|
6
|
+
# The bar between two panels: a `role="separator"` that can be dragged and
|
|
7
|
+
# driven from the keyboard.
|
|
8
|
+
#
|
|
9
|
+
# Its own orientation is the *opposite* of the group's — a row of panels
|
|
10
|
+
# is divided by a vertical line — and `role="separator"` defaults to
|
|
11
|
+
# horizontal, so the attribute is always written rather than left out.
|
|
12
|
+
class Component < ApplicationViewComponent
|
|
13
|
+
GRIP_CLASSES = "z-10 flex h-4 w-3 items-center justify-center rounded-xs border bg-border"
|
|
14
|
+
|
|
15
|
+
default_tag :div
|
|
16
|
+
slot_name :"resizable-handle"
|
|
17
|
+
|
|
18
|
+
style do
|
|
19
|
+
base {
|
|
20
|
+
"relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 " \
|
|
21
|
+
"after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-ring " \
|
|
22
|
+
"focus-visible:ring-offset-1 focus-visible:outline-hidden aria-[orientation=horizontal]:h-px " \
|
|
23
|
+
"aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 " \
|
|
24
|
+
"aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full " \
|
|
25
|
+
"aria-[orientation=horizontal]:after:translate-x-0 " \
|
|
26
|
+
"aria-[orientation=horizontal]:after:-translate-y-1/2 " \
|
|
27
|
+
"[&[aria-orientation=horizontal]>div]:rotate-90"
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
attr_reader :with_handle, :orientation, :disabled
|
|
32
|
+
|
|
33
|
+
# `with_handle:` is upstream's `withHandle`: the grip a pointer can see,
|
|
34
|
+
# which is off by default there too.
|
|
35
|
+
def initialize(with_handle: false, orientation: :horizontal, disabled: false, **attributes)
|
|
36
|
+
@with_handle = with_handle
|
|
37
|
+
@orientation = orientation&.to_sym == :vertical ? :vertical : :horizontal
|
|
38
|
+
@disabled = disabled
|
|
39
|
+
super(**attributes)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def element_attributes(**defaults)
|
|
43
|
+
super(**{
|
|
44
|
+
role: "separator",
|
|
45
|
+
# The group's orientation decides the separator's, inverted.
|
|
46
|
+
"aria-orientation" => orientation == :vertical ? "horizontal" : "vertical",
|
|
47
|
+
"aria-disabled" => (disabled.presence && "true"),
|
|
48
|
+
tabindex: (disabled ? "-1" : "0"),
|
|
49
|
+
"data-separator" => "inactive",
|
|
50
|
+
"data-shadcn--resizable-target" => "handle",
|
|
51
|
+
"data-action" => "pointerdown->shadcn--resizable#press keydown->shadcn--resizable#keydown",
|
|
52
|
+
style: merged_style("flex-basis:auto;flex-grow:0;flex-shrink:0")
|
|
53
|
+
}.compact.merge(defaults))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def call
|
|
57
|
+
render_element(body: grip)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def grip
|
|
63
|
+
return unless with_handle
|
|
64
|
+
|
|
65
|
+
tag.div(render(Icon::Component.new("grip-vertical", class: "size-2.5")), class: GRIP_CLASSES)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Resizable
|
|
5
|
+
module Panel
|
|
6
|
+
# One panel. Upstream carries no classes at all — the package writes an
|
|
7
|
+
# inline style — so what is reproduced here is that style, minus the part
|
|
8
|
+
# of it that resets borders and padding the package cannot know a caller
|
|
9
|
+
# wants.
|
|
10
|
+
#
|
|
11
|
+
# A size is a share, not a pixel: `flex-grow` against `flex-basis: 0` is
|
|
12
|
+
# exactly the proportional layout the package computes, which is why the
|
|
13
|
+
# browser does the resizing and the controller only writes two numbers.
|
|
14
|
+
class Component < ApplicationViewComponent
|
|
15
|
+
default_tag :div
|
|
16
|
+
slot_name :"resizable-panel"
|
|
17
|
+
|
|
18
|
+
attr_reader :default_size, :min_size, :max_size
|
|
19
|
+
|
|
20
|
+
# Sizes are percentages, as upstream's are. Give every panel one or give
|
|
21
|
+
# none: with a mix, the ones without would each take a single share
|
|
22
|
+
# against another's twenty-five, which is not what anybody means.
|
|
23
|
+
def initialize(default_size: nil, min_size: nil, max_size: nil, **attributes)
|
|
24
|
+
@default_size = default_size
|
|
25
|
+
@min_size = min_size
|
|
26
|
+
@max_size = max_size
|
|
27
|
+
super(**attributes)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def element_attributes(**defaults)
|
|
31
|
+
super(**{
|
|
32
|
+
id: panel_id,
|
|
33
|
+
"data-shadcn--resizable-target" => "panel",
|
|
34
|
+
"data-min-size" => min_size,
|
|
35
|
+
"data-max-size" => max_size,
|
|
36
|
+
style: merged_style(
|
|
37
|
+
"flex-basis:0;flex-shrink:1;flex-grow:#{default_size || 1};overflow:hidden;" \
|
|
38
|
+
"display:flex;min-width:0;min-height:0"
|
|
39
|
+
)
|
|
40
|
+
}.compact.merge(defaults))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
# A handle points at the panel before it with `aria-controls`, so a
|
|
46
|
+
# panel needs a name of its own even when the caller gives it none.
|
|
47
|
+
def panel_id
|
|
48
|
+
attributes[:id] || "shadcn-resizable-panel-#{SecureRandom.hex(4)}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module Resizable
|
|
5
|
+
class Preview < ApplicationViewComponentPreview
|
|
6
|
+
# Upstream's own first example: two panels side by side.
|
|
7
|
+
def default
|
|
8
|
+
render_with_template
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Upstream's "Vertical".
|
|
12
|
+
def vertical
|
|
13
|
+
render_with_template
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Upstream's "With Handle", and a nested group — a row inside a column,
|
|
17
|
+
# which is the layout the docs use to show both at once.
|
|
18
|
+
def with_handle
|
|
19
|
+
render_with_template
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<%# Upstream's own example. Panels and handles go in the block, in order — a
|
|
2
|
+
group *is* `panel, handle, panel` — and sizes are percentages. %>
|
|
3
|
+
<%= render(Shadcn::Resizable::Component.new(class: "max-w-md rounded-lg border md:min-w-[450px]")) do %>
|
|
4
|
+
<%= render(Shadcn::Resizable::Panel::Component.new(default_size: 50)) do %>
|
|
5
|
+
<div class="flex h-[200px] items-center justify-center p-6">
|
|
6
|
+
<span class="font-semibold">One</span>
|
|
7
|
+
</div>
|
|
8
|
+
<% end %>
|
|
9
|
+
<%= render(Shadcn::Resizable::Handle::Component.new) %>
|
|
10
|
+
<%= render(Shadcn::Resizable::Panel::Component.new(default_size: 50)) do %>
|
|
11
|
+
<%= render(Shadcn::Resizable::Component.new(orientation: :vertical)) do %>
|
|
12
|
+
<%= render(Shadcn::Resizable::Panel::Component.new(default_size: 25)) do %>
|
|
13
|
+
<div class="flex h-full items-center justify-center p-6">
|
|
14
|
+
<span class="font-semibold">Two</span>
|
|
15
|
+
</div>
|
|
16
|
+
<% end %>
|
|
17
|
+
<%= render(Shadcn::Resizable::Handle::Component.new(orientation: :vertical)) %>
|
|
18
|
+
<%= render(Shadcn::Resizable::Panel::Component.new(default_size: 75)) do %>
|
|
19
|
+
<div class="flex h-full items-center justify-center p-6">
|
|
20
|
+
<span class="font-semibold">Three</span>
|
|
21
|
+
</div>
|
|
22
|
+
<% end %>
|
|
23
|
+
<% end %>
|
|
24
|
+
<% end %>
|
|
25
|
+
<% end %>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<%# Upstream's "Vertical": the group's orientation decides both the layout and
|
|
2
|
+
the separator's own, which is the opposite of it — a column of panels is
|
|
3
|
+
divided by a horizontal line. %>
|
|
4
|
+
<%= render(Shadcn::Resizable::Component.new(
|
|
5
|
+
orientation: :vertical,
|
|
6
|
+
class: "min-h-[200px] max-w-md rounded-lg border"
|
|
7
|
+
)) do %>
|
|
8
|
+
<%= render(Shadcn::Resizable::Panel::Component.new(default_size: 25)) do %>
|
|
9
|
+
<div class="flex h-full items-center justify-center p-6">
|
|
10
|
+
<span class="font-semibold">Header</span>
|
|
11
|
+
</div>
|
|
12
|
+
<% end %>
|
|
13
|
+
<%= render(Shadcn::Resizable::Handle::Component.new(orientation: :vertical)) %>
|
|
14
|
+
<%= render(Shadcn::Resizable::Panel::Component.new(default_size: 75)) do %>
|
|
15
|
+
<div class="flex h-full items-center justify-center p-6">
|
|
16
|
+
<span class="font-semibold">Content</span>
|
|
17
|
+
</div>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<%# Upstream's "With Handle": the grip a pointer can see. Off by default there
|
|
2
|
+
too — a handle is a hit area whether or not it is drawn.
|
|
3
|
+
|
|
4
|
+
`min_size:` and `max_size:` are percentages, and the drag stops at them. %>
|
|
5
|
+
<%= render(Shadcn::Resizable::Component.new(class: "min-h-[200px] max-w-md rounded-lg border")) do %>
|
|
6
|
+
<%= render(Shadcn::Resizable::Panel::Component.new(default_size: 25, min_size: 15, max_size: 60)) do %>
|
|
7
|
+
<div class="flex h-full items-center justify-center p-6">
|
|
8
|
+
<span class="font-semibold">Sidebar</span>
|
|
9
|
+
</div>
|
|
10
|
+
<% end %>
|
|
11
|
+
<%= render(Shadcn::Resizable::Handle::Component.new(with_handle: true)) %>
|
|
12
|
+
<%= render(Shadcn::Resizable::Panel::Component.new(default_size: 75)) do %>
|
|
13
|
+
<div class="flex h-full items-center justify-center p-6">
|
|
14
|
+
<span class="font-semibold">Content</span>
|
|
15
|
+
</div>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% end %>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module ScrollArea
|
|
5
|
+
# Port of registry/new-york-v4/ui/scroll-area.tsx, whose behaviour is Radix's
|
|
6
|
+
# `ScrollArea` — 1,189 lines against shadcn's 58, and vendored at
|
|
7
|
+
# `vendor/radix/ui/scroll-area.tsx`.
|
|
8
|
+
#
|
|
9
|
+
# Like shadcn's own, this composes the whole thing rather than exposing the
|
|
10
|
+
# parts: the viewport, one scrollbar per requested axis, and the corner where
|
|
11
|
+
# two of them meet. `orientation:` is this port's way of asking for the
|
|
12
|
+
# second bar, which shadcn does by passing a second `<ScrollBar>` as a child
|
|
13
|
+
# — a shape that relies on React's Slottable to hoist it out of the viewport
|
|
14
|
+
# and has no counterpart here.
|
|
15
|
+
#
|
|
16
|
+
# Two of Radix's four `type` strategies are reproduced: `hover`, its default,
|
|
17
|
+
# and `always`. See features/scroll-area.md.
|
|
18
|
+
class Component < ApplicationViewComponent
|
|
19
|
+
slot_name :"scroll-area"
|
|
20
|
+
|
|
21
|
+
style do
|
|
22
|
+
base { "relative" }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
attr_reader :orientation, :type, :scroll_hide_delay
|
|
26
|
+
|
|
27
|
+
def initialize(orientation: :vertical, type: :hover, scroll_hide_delay: 600, **attributes)
|
|
28
|
+
@orientation = orientation&.to_sym || :vertical
|
|
29
|
+
@type = type&.to_sym || :hover
|
|
30
|
+
@scroll_hide_delay = scroll_hide_delay
|
|
31
|
+
super(**attributes)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def element_attributes(**defaults)
|
|
35
|
+
super(**{
|
|
36
|
+
"data-controller" => "shadcn--scroll-area",
|
|
37
|
+
"data-shadcn--scroll-area-type-value" => type,
|
|
38
|
+
"data-shadcn--scroll-area-hide-delay-value" => scroll_hide_delay,
|
|
39
|
+
"data-action" => "pointerenter->shadcn--scroll-area#pointerEnter " \
|
|
40
|
+
"pointerleave->shadcn--scroll-area#pointerLeave"
|
|
41
|
+
}.merge(defaults))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def call
|
|
45
|
+
render_element(body: safe_join([ viewport, *scrollbars, corner ].compact))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def horizontal? = [ :horizontal, :both ].include?(orientation)
|
|
51
|
+
def vertical? = [ :vertical, :both ].include?(orientation)
|
|
52
|
+
|
|
53
|
+
def viewport
|
|
54
|
+
render(
|
|
55
|
+
Shadcn::ScrollArea::Viewport::Component.new(horizontal: horizontal?, vertical: vertical?)
|
|
56
|
+
) { content }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def scrollbars
|
|
60
|
+
[
|
|
61
|
+
(bar(:vertical) if vertical?),
|
|
62
|
+
(bar(:horizontal) if horizontal?)
|
|
63
|
+
]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def bar(axis)
|
|
67
|
+
render(Shadcn::ScrollArea::Scrollbar::Component.new(orientation: axis))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Only where two bars meet. Radix sizes it from the two bars' thicknesses
|
|
71
|
+
# and publishes them as the custom properties each bar stops short at.
|
|
72
|
+
def corner
|
|
73
|
+
return unless horizontal? && vertical?
|
|
74
|
+
|
|
75
|
+
tag.div(
|
|
76
|
+
style: "position: absolute; right: 0; bottom: 0; " \
|
|
77
|
+
"width: var(--radix-scroll-area-corner-width, 0px); " \
|
|
78
|
+
"height: var(--radix-scroll-area-corner-height, 0px);",
|
|
79
|
+
"data-shadcn--scroll-area-target": "corner"
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<%# Upstream's example: a bordered box of tags, taller than it is allowed to be.
|
|
2
|
+
|
|
3
|
+
The scrollbar is `type: :hover` by default — Radix's default too — so it is
|
|
4
|
+
not there until the pointer is. Radix *unmounts* it; nothing is unmounted
|
|
5
|
+
here, so it ships with `data-state="hidden"` and the controller moves the
|
|
6
|
+
attribute.
|
|
7
|
+
|
|
8
|
+
The second one asks for both axes, which is what puts a corner between the
|
|
9
|
+
two bars: each stops short of the other by exactly its thickness, and the
|
|
10
|
+
corner fills what is left. `always` on that one so both are visible in a
|
|
11
|
+
screenshot without a pointer in it. %>
|
|
12
|
+
<div class="flex gap-6">
|
|
13
|
+
<%= render(Shadcn::ScrollArea::Component.new(class: "h-64 w-48 rounded-md border")) do %>
|
|
14
|
+
<div class="p-4">
|
|
15
|
+
<h4 class="mb-4 text-sm leading-none font-medium">Tags</h4>
|
|
16
|
+
<% 24.times do |index| %>
|
|
17
|
+
<div class="text-sm">v1.2.0-beta.<%= 24 - index %></div>
|
|
18
|
+
<%= render(Shadcn::Separator::Component.new(class: "my-2")) %>
|
|
19
|
+
<% end %>
|
|
20
|
+
</div>
|
|
21
|
+
<% end %>
|
|
22
|
+
|
|
23
|
+
<%= render(Shadcn::ScrollArea::Component.new(
|
|
24
|
+
orientation: :both, type: :always, class: "h-64 w-72 rounded-md border"
|
|
25
|
+
)) do %>
|
|
26
|
+
<div class="w-max p-4">
|
|
27
|
+
<% 20.times do |row| %>
|
|
28
|
+
<div class="flex gap-4 py-1 text-sm whitespace-nowrap">
|
|
29
|
+
<% 6.times do |column| %>
|
|
30
|
+
<span class="w-24">cell <%= row + 1 %>.<%= column + 1 %></span>
|
|
31
|
+
<% end %>
|
|
32
|
+
</div>
|
|
33
|
+
<% end %>
|
|
34
|
+
</div>
|
|
35
|
+
<% end %>
|
|
36
|
+
</div>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shadcn
|
|
4
|
+
module ScrollArea
|
|
5
|
+
module Scrollbar
|
|
6
|
+
# Radix's `ScrollAreaScrollbar`, and shadcn's `ScrollBar`.
|
|
7
|
+
#
|
|
8
|
+
# `data-state` is `hidden` from the server and the controller moves it.
|
|
9
|
+
# Radix *unmounts* the bar instead — with `type="hover"`, the default, it
|
|
10
|
+
# is not in the DOM until the pointer arrives (measured on the live demo).
|
|
11
|
+
# Nothing is unmounted here for the same reason nothing is portalled, so
|
|
12
|
+
# the state attribute carries what a missing element carried there.
|
|
13
|
+
class Component < ApplicationViewComponent
|
|
14
|
+
slot_name :"scroll-area-scrollbar"
|
|
15
|
+
|
|
16
|
+
style do
|
|
17
|
+
base { "flex touch-none p-px transition-colors select-none" }
|
|
18
|
+
|
|
19
|
+
variants {
|
|
20
|
+
orientation {
|
|
21
|
+
vertical { "h-full w-2.5 border-l border-l-transparent" }
|
|
22
|
+
horizontal { "h-2.5 flex-col border-t border-t-transparent" }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
defaults { { orientation: :vertical } }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
attr_reader :orientation
|
|
30
|
+
|
|
31
|
+
def initialize(orientation: :vertical, **attributes)
|
|
32
|
+
@orientation = orientation&.to_sym || :vertical
|
|
33
|
+
super(**attributes)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def style_variants
|
|
37
|
+
{ orientation: }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The inline geometry is Radix's: the bar is absolutely positioned
|
|
41
|
+
# against the root and stops short of the corner, and the thumb's size
|
|
42
|
+
# travels as a custom property rather than as a width the controller
|
|
43
|
+
# writes on the thumb itself (measured on the live demo).
|
|
44
|
+
def element_attributes(**defaults)
|
|
45
|
+
super(**{
|
|
46
|
+
style: merged_style(position_style),
|
|
47
|
+
"data-orientation" => orientation,
|
|
48
|
+
"data-state" => "hidden",
|
|
49
|
+
"data-shadcn--scroll-area-target" => "scrollbar",
|
|
50
|
+
"data-action" => "pointerdown->shadcn--scroll-area#startDrag"
|
|
51
|
+
}.merge(defaults))
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def call
|
|
55
|
+
render_element(body: content.presence || render(Shadcn::ScrollArea::Thumb::Component.new))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def position_style
|
|
61
|
+
if orientation == :vertical
|
|
62
|
+
"position: absolute; top: 0; right: 0; " \
|
|
63
|
+
"bottom: var(--radix-scroll-area-corner-height, 0px);"
|
|
64
|
+
else
|
|
65
|
+
"position: absolute; bottom: 0; left: 0; " \
|
|
66
|
+
"right: var(--radix-scroll-area-corner-width, 0px);"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|