phlex_kit 0.2.0
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/MIT-LICENSE +21 -0
- data/README.md +135 -0
- data/app/assets/stylesheets/phlex_kit/_tokens.css +91 -0
- data/app/assets/stylesheets/phlex_kit/phlex_kit.css +82 -0
- data/app/components/phlex_kit/accordion/accordion.css +14 -0
- data/app/components/phlex_kit/accordion/accordion.rb +10 -0
- data/app/components/phlex_kit/accordion/accordion_content.rb +8 -0
- data/app/components/phlex_kit/accordion/accordion_default_content.rb +6 -0
- data/app/components/phlex_kit/accordion/accordion_default_trigger.rb +12 -0
- data/app/components/phlex_kit/accordion/accordion_icon.rb +16 -0
- data/app/components/phlex_kit/accordion/accordion_item.rb +12 -0
- data/app/components/phlex_kit/accordion/accordion_trigger.rb +8 -0
- data/app/components/phlex_kit/alert/alert.css +32 -0
- data/app/components/phlex_kit/alert/alert.rb +37 -0
- data/app/components/phlex_kit/alert/alert_description.rb +12 -0
- data/app/components/phlex_kit/alert/alert_title.rb +12 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog.css +37 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog.rb +20 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog_action.rb +14 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog_cancel.rb +13 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog_content.rb +19 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog_description.rb +12 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog_footer.rb +12 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog_header.rb +12 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog_title.rb +12 -0
- data/app/components/phlex_kit/alert_dialog/alert_dialog_trigger.rb +12 -0
- data/app/components/phlex_kit/aspect_ratio/aspect_ratio.css +12 -0
- data/app/components/phlex_kit/aspect_ratio/aspect_ratio.rb +27 -0
- data/app/components/phlex_kit/attachment/attachment.css +62 -0
- data/app/components/phlex_kit/attachment/attachment.rb +16 -0
- data/app/components/phlex_kit/attachment/attachment_action.rb +24 -0
- data/app/components/phlex_kit/attachment/attachment_actions.rb +7 -0
- data/app/components/phlex_kit/attachment/attachment_content.rb +7 -0
- data/app/components/phlex_kit/attachment/attachment_description.rb +7 -0
- data/app/components/phlex_kit/attachment/attachment_media.rb +8 -0
- data/app/components/phlex_kit/attachment/attachment_title.rb +7 -0
- data/app/components/phlex_kit/avatar/avatar.css +35 -0
- data/app/components/phlex_kit/avatar/avatar.rb +25 -0
- data/app/components/phlex_kit/avatar/avatar_fallback.rb +13 -0
- data/app/components/phlex_kit/avatar/avatar_group.rb +7 -0
- data/app/components/phlex_kit/avatar/avatar_image.rb +24 -0
- data/app/components/phlex_kit/badge/badge.css +50 -0
- data/app/components/phlex_kit/badge/badge.rb +39 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb.css +18 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb.rb +8 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb_ellipsis.rb +15 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb_item.rb +6 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb_link.rb +9 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb_list.rb +6 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb_page.rb +8 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb_separator.rb +10 -0
- data/app/components/phlex_kit/bubble/bubble.css +32 -0
- data/app/components/phlex_kit/bubble/bubble.rb +17 -0
- data/app/components/phlex_kit/bubble/bubble_content.rb +11 -0
- data/app/components/phlex_kit/bubble/bubble_group.rb +6 -0
- data/app/components/phlex_kit/bubble/bubble_reactions.rb +12 -0
- data/app/components/phlex_kit/button/button.css +72 -0
- data/app/components/phlex_kit/button/button.rb +51 -0
- data/app/components/phlex_kit/button_group/button_group.css +8 -0
- data/app/components/phlex_kit/button_group/button_group.rb +14 -0
- data/app/components/phlex_kit/calendar/calendar.css +109 -0
- data/app/components/phlex_kit/calendar/calendar.rb +47 -0
- data/app/components/phlex_kit/calendar/calendar_body.rb +13 -0
- data/app/components/phlex_kit/calendar/calendar_days.rb +98 -0
- data/app/components/phlex_kit/calendar/calendar_header.rb +13 -0
- data/app/components/phlex_kit/calendar/calendar_next.rb +40 -0
- data/app/components/phlex_kit/calendar/calendar_prev.rb +40 -0
- data/app/components/phlex_kit/calendar/calendar_title.rb +19 -0
- data/app/components/phlex_kit/calendar/calendar_weekdays.rb +27 -0
- data/app/components/phlex_kit/card/card.css +15 -0
- data/app/components/phlex_kit/card/card.rb +29 -0
- data/app/components/phlex_kit/card/card_content.rb +12 -0
- data/app/components/phlex_kit/card/card_description.rb +12 -0
- data/app/components/phlex_kit/card/card_footer.rb +12 -0
- data/app/components/phlex_kit/card/card_header.rb +12 -0
- data/app/components/phlex_kit/card/card_title.rb +12 -0
- data/app/components/phlex_kit/carousel/carousel.css +41 -0
- data/app/components/phlex_kit/carousel/carousel.rb +37 -0
- data/app/components/phlex_kit/carousel/carousel_content.rb +16 -0
- data/app/components/phlex_kit/carousel/carousel_item.rb +17 -0
- data/app/components/phlex_kit/carousel/carousel_next.rb +39 -0
- data/app/components/phlex_kit/carousel/carousel_previous.rb +40 -0
- data/app/components/phlex_kit/chart/chart.css +9 -0
- data/app/components/phlex_kit/chart/chart.rb +31 -0
- data/app/components/phlex_kit/checkbox/checkbox.css +27 -0
- data/app/components/phlex_kit/checkbox/checkbox.rb +26 -0
- data/app/components/phlex_kit/clipboard/clipboard.css +8 -0
- data/app/components/phlex_kit/clipboard/clipboard.rb +19 -0
- data/app/components/phlex_kit/clipboard/clipboard_popover.rb +14 -0
- data/app/components/phlex_kit/clipboard/clipboard_source.rb +6 -0
- data/app/components/phlex_kit/clipboard/clipboard_trigger.rb +6 -0
- data/app/components/phlex_kit/codeblock/codeblock.css +7 -0
- data/app/components/phlex_kit/codeblock/codeblock.rb +23 -0
- data/app/components/phlex_kit/collapsible/collapsible.css +3 -0
- data/app/components/phlex_kit/collapsible/collapsible.rb +13 -0
- data/app/components/phlex_kit/collapsible/collapsible_content.rb +8 -0
- data/app/components/phlex_kit/collapsible/collapsible_trigger.rb +8 -0
- data/app/components/phlex_kit/combobox/combobox.css +310 -0
- data/app/components/phlex_kit/combobox/combobox.rb +33 -0
- data/app/components/phlex_kit/combobox/combobox_badge.rb +15 -0
- data/app/components/phlex_kit/combobox/combobox_badge_trigger.rb +55 -0
- data/app/components/phlex_kit/combobox/combobox_checkbox.rb +21 -0
- data/app/components/phlex_kit/combobox/combobox_clear_button.rb +39 -0
- data/app/components/phlex_kit/combobox/combobox_empty_state.rb +17 -0
- data/app/components/phlex_kit/combobox/combobox_input_trigger.rb +69 -0
- data/app/components/phlex_kit/combobox/combobox_item.rb +19 -0
- data/app/components/phlex_kit/combobox/combobox_item_indicator.rb +27 -0
- data/app/components/phlex_kit/combobox/combobox_list.rb +12 -0
- data/app/components/phlex_kit/combobox/combobox_list_group.rb +14 -0
- data/app/components/phlex_kit/combobox/combobox_popover.rb +27 -0
- data/app/components/phlex_kit/combobox/combobox_radio.rb +26 -0
- data/app/components/phlex_kit/combobox/combobox_search_input.rb +49 -0
- data/app/components/phlex_kit/combobox/combobox_toggle_all_checkbox.rb +21 -0
- data/app/components/phlex_kit/combobox/combobox_trigger.rb +48 -0
- data/app/components/phlex_kit/command/command.css +104 -0
- data/app/components/phlex_kit/command/command.rb +18 -0
- data/app/components/phlex_kit/command/command_dialog.rb +19 -0
- data/app/components/phlex_kit/command/command_dialog_content.rb +37 -0
- data/app/components/phlex_kit/command/command_dialog_trigger.rb +22 -0
- data/app/components/phlex_kit/command/command_empty.rb +17 -0
- data/app/components/phlex_kit/command/command_group.rb +32 -0
- data/app/components/phlex_kit/command/command_input.rb +56 -0
- data/app/components/phlex_kit/command/command_item.rb +22 -0
- data/app/components/phlex_kit/command/command_list.rb +12 -0
- data/app/components/phlex_kit/context_menu/context_menu.css +19 -0
- data/app/components/phlex_kit/context_menu/context_menu.rb +11 -0
- data/app/components/phlex_kit/context_menu/context_menu_content.rb +8 -0
- data/app/components/phlex_kit/context_menu/context_menu_item.rb +25 -0
- data/app/components/phlex_kit/context_menu/context_menu_label.rb +11 -0
- data/app/components/phlex_kit/context_menu/context_menu_separator.rb +8 -0
- data/app/components/phlex_kit/context_menu/context_menu_trigger.rb +8 -0
- data/app/components/phlex_kit/data_table/data_table.css +110 -0
- data/app/components/phlex_kit/data_table/data_table.rb +25 -0
- data/app/components/phlex_kit/data_table/data_table_bulk_actions.rb +15 -0
- data/app/components/phlex_kit/data_table/data_table_column_toggle.rb +61 -0
- data/app/components/phlex_kit/data_table/data_table_expand_toggle.rb +40 -0
- data/app/components/phlex_kit/data_table/data_table_form.rb +36 -0
- data/app/components/phlex_kit/data_table/data_table_kaminari_adapter.rb +17 -0
- data/app/components/phlex_kit/data_table/data_table_manual_adapter.rb +18 -0
- data/app/components/phlex_kit/data_table/data_table_pagination.rb +98 -0
- data/app/components/phlex_kit/data_table/data_table_pagination_bar.rb +13 -0
- data/app/components/phlex_kit/data_table/data_table_pagy_adapter.rb +17 -0
- data/app/components/phlex_kit/data_table/data_table_per_page_select.rb +29 -0
- data/app/components/phlex_kit/data_table/data_table_row_checkbox.rb +24 -0
- data/app/components/phlex_kit/data_table/data_table_search.rb +51 -0
- data/app/components/phlex_kit/data_table/data_table_select_all_checkbox.rb +19 -0
- data/app/components/phlex_kit/data_table/data_table_selection_summary.rb +19 -0
- data/app/components/phlex_kit/data_table/data_table_sort_head.rb +82 -0
- data/app/components/phlex_kit/data_table/data_table_toolbar.rb +13 -0
- data/app/components/phlex_kit/date_picker/date_picker.css +28 -0
- data/app/components/phlex_kit/date_picker/date_picker.rb +71 -0
- data/app/components/phlex_kit/dialog/dialog.css +32 -0
- data/app/components/phlex_kit/dialog/dialog.rb +14 -0
- data/app/components/phlex_kit/dialog/dialog_content.rb +21 -0
- data/app/components/phlex_kit/dialog/dialog_description.rb +6 -0
- data/app/components/phlex_kit/dialog/dialog_footer.rb +6 -0
- data/app/components/phlex_kit/dialog/dialog_header.rb +6 -0
- data/app/components/phlex_kit/dialog/dialog_middle.rb +6 -0
- data/app/components/phlex_kit/dialog/dialog_title.rb +6 -0
- data/app/components/phlex_kit/dialog/dialog_trigger.rb +8 -0
- data/app/components/phlex_kit/drawer/drawer.css +54 -0
- data/app/components/phlex_kit/drawer/drawer.rb +18 -0
- data/app/components/phlex_kit/drawer/drawer_close.rb +9 -0
- data/app/components/phlex_kit/drawer/drawer_content.rb +21 -0
- data/app/components/phlex_kit/drawer/drawer_description.rb +7 -0
- data/app/components/phlex_kit/drawer/drawer_footer.rb +7 -0
- data/app/components/phlex_kit/drawer/drawer_header.rb +7 -0
- data/app/components/phlex_kit/drawer/drawer_title.rb +7 -0
- data/app/components/phlex_kit/drawer/drawer_trigger.rb +9 -0
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu.css +38 -0
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu.rb +22 -0
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu_content.rb +23 -0
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu_item.rb +22 -0
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu_label.rb +12 -0
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu_separator.rb +12 -0
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu_trigger.rb +15 -0
- data/app/components/phlex_kit/empty/empty.css +25 -0
- data/app/components/phlex_kit/empty/empty.rb +6 -0
- data/app/components/phlex_kit/empty/empty_content.rb +6 -0
- data/app/components/phlex_kit/empty/empty_description.rb +6 -0
- data/app/components/phlex_kit/empty/empty_header.rb +6 -0
- data/app/components/phlex_kit/empty/empty_media.rb +14 -0
- data/app/components/phlex_kit/empty/empty_title.rb +6 -0
- data/app/components/phlex_kit/form/form.css +15 -0
- data/app/components/phlex_kit/form/form.rb +27 -0
- data/app/components/phlex_kit/form_field/form_field.css +31 -0
- data/app/components/phlex_kit/form_field/form_field.rb +31 -0
- data/app/components/phlex_kit/form_field/form_field_error.rb +19 -0
- data/app/components/phlex_kit/form_field/form_field_hint.rb +13 -0
- data/app/components/phlex_kit/form_field/form_field_label.rb +13 -0
- data/app/components/phlex_kit/hover_card/hover_card.css +8 -0
- data/app/components/phlex_kit/hover_card/hover_card.rb +10 -0
- data/app/components/phlex_kit/hover_card/hover_card_content.rb +8 -0
- data/app/components/phlex_kit/hover_card/hover_card_trigger.rb +6 -0
- data/app/components/phlex_kit/input/input.css +29 -0
- data/app/components/phlex_kit/input/input.rb +34 -0
- data/app/components/phlex_kit/input_group/input_group.css +35 -0
- data/app/components/phlex_kit/input_group/input_group.rb +15 -0
- data/app/components/phlex_kit/input_group/input_group_addon.rb +16 -0
- data/app/components/phlex_kit/input_group/input_group_text.rb +7 -0
- data/app/components/phlex_kit/input_otp/input_otp.css +32 -0
- data/app/components/phlex_kit/input_otp/input_otp.rb +29 -0
- data/app/components/phlex_kit/input_otp/input_otp_group.rb +7 -0
- data/app/components/phlex_kit/input_otp/input_otp_separator.rb +7 -0
- data/app/components/phlex_kit/input_otp/input_otp_slot.rb +27 -0
- data/app/components/phlex_kit/item/item.css +32 -0
- data/app/components/phlex_kit/item/item.rb +18 -0
- data/app/components/phlex_kit/item/item_actions.rb +7 -0
- data/app/components/phlex_kit/item/item_content.rb +7 -0
- data/app/components/phlex_kit/item/item_description.rb +7 -0
- data/app/components/phlex_kit/item/item_group.rb +7 -0
- data/app/components/phlex_kit/item/item_media.rb +7 -0
- data/app/components/phlex_kit/item/item_title.rb +7 -0
- data/app/components/phlex_kit/kbd/kbd.css +17 -0
- data/app/components/phlex_kit/kbd/kbd.rb +14 -0
- data/app/components/phlex_kit/kbd/kbd_group.rb +12 -0
- data/app/components/phlex_kit/label/label.css +12 -0
- data/app/components/phlex_kit/label/label.rb +14 -0
- data/app/components/phlex_kit/link/link.css +6 -0
- data/app/components/phlex_kit/link/link.rb +47 -0
- data/app/components/phlex_kit/masked_input/masked_input.rb +12 -0
- data/app/components/phlex_kit/menubar/menubar.css +66 -0
- data/app/components/phlex_kit/menubar/menubar.rb +24 -0
- data/app/components/phlex_kit/menubar/menubar_content.rb +9 -0
- data/app/components/phlex_kit/menubar/menubar_item.rb +26 -0
- data/app/components/phlex_kit/menubar/menubar_menu.rb +9 -0
- data/app/components/phlex_kit/menubar/menubar_separator.rb +7 -0
- data/app/components/phlex_kit/menubar/menubar_trigger.rb +14 -0
- data/app/components/phlex_kit/message/message.css +20 -0
- data/app/components/phlex_kit/message/message.rb +14 -0
- data/app/components/phlex_kit/message/message_avatar.rb +6 -0
- data/app/components/phlex_kit/message/message_content.rb +6 -0
- data/app/components/phlex_kit/message/message_footer.rb +6 -0
- data/app/components/phlex_kit/message/message_group.rb +6 -0
- data/app/components/phlex_kit/message/message_header.rb +6 -0
- data/app/components/phlex_kit/message_scroller/message_scroller.css +2 -0
- data/app/components/phlex_kit/message_scroller/message_scroller.rb +11 -0
- data/app/components/phlex_kit/native_select/native_select.css +51 -0
- data/app/components/phlex_kit/native_select/native_select.rb +48 -0
- data/app/components/phlex_kit/native_select/native_select_group.rb +13 -0
- data/app/components/phlex_kit/native_select/native_select_icon.rb +32 -0
- data/app/components/phlex_kit/native_select/native_select_option.rb +14 -0
- data/app/components/phlex_kit/navigation_menu/navigation_menu.css +67 -0
- data/app/components/phlex_kit/navigation_menu/navigation_menu.rb +23 -0
- data/app/components/phlex_kit/navigation_menu/navigation_menu_content.rb +9 -0
- data/app/components/phlex_kit/navigation_menu/navigation_menu_item.rb +9 -0
- data/app/components/phlex_kit/navigation_menu/navigation_menu_link.rb +13 -0
- data/app/components/phlex_kit/navigation_menu/navigation_menu_list.rb +7 -0
- data/app/components/phlex_kit/navigation_menu/navigation_menu_trigger.rb +27 -0
- data/app/components/phlex_kit/pagination/pagination.css +5 -0
- data/app/components/phlex_kit/pagination/pagination.rb +10 -0
- data/app/components/phlex_kit/pagination/pagination_content.rb +6 -0
- data/app/components/phlex_kit/pagination/pagination_ellipsis.rb +17 -0
- data/app/components/phlex_kit/pagination/pagination_item.rb +14 -0
- data/app/components/phlex_kit/popover/popover.css +9 -0
- data/app/components/phlex_kit/popover/popover.rb +11 -0
- data/app/components/phlex_kit/popover/popover_content.rb +8 -0
- data/app/components/phlex_kit/popover/popover_trigger.rb +8 -0
- data/app/components/phlex_kit/progress/progress.css +17 -0
- data/app/components/phlex_kit/progress/progress.rb +25 -0
- data/app/components/phlex_kit/radio_button/radio_button.css +9 -0
- data/app/components/phlex_kit/radio_button/radio_button.rb +19 -0
- data/app/components/phlex_kit/radio_group/radio_group.css +3 -0
- data/app/components/phlex_kit/radio_group/radio_group.rb +14 -0
- data/app/components/phlex_kit/resizable/resizable.css +23 -0
- data/app/components/phlex_kit/resizable/resizable_handle.rb +21 -0
- data/app/components/phlex_kit/resizable/resizable_panel.rb +19 -0
- data/app/components/phlex_kit/resizable/resizable_panel_group.rb +26 -0
- data/app/components/phlex_kit/scroll_area/scroll_area.css +21 -0
- data/app/components/phlex_kit/scroll_area/scroll_area.rb +15 -0
- data/app/components/phlex_kit/select/select.css +80 -0
- data/app/components/phlex_kit/select/select.rb +43 -0
- data/app/components/phlex_kit/select/select_content.rb +24 -0
- data/app/components/phlex_kit/select/select_group.rb +13 -0
- data/app/components/phlex_kit/select/select_input.rb +23 -0
- data/app/components/phlex_kit/select/select_item.rb +52 -0
- data/app/components/phlex_kit/select/select_label.rb +13 -0
- data/app/components/phlex_kit/select/select_trigger.rb +42 -0
- data/app/components/phlex_kit/select/select_value.rb +21 -0
- data/app/components/phlex_kit/separator/separator.css +6 -0
- data/app/components/phlex_kit/separator/separator.rb +30 -0
- data/app/components/phlex_kit/sheet/sheet.css +17 -0
- data/app/components/phlex_kit/sheet/sheet.rb +14 -0
- data/app/components/phlex_kit/sheet/sheet_content.rb +25 -0
- data/app/components/phlex_kit/sheet/sheet_description.rb +6 -0
- data/app/components/phlex_kit/sheet/sheet_footer.rb +6 -0
- data/app/components/phlex_kit/sheet/sheet_header.rb +6 -0
- data/app/components/phlex_kit/sheet/sheet_middle.rb +6 -0
- data/app/components/phlex_kit/sheet/sheet_title.rb +6 -0
- data/app/components/phlex_kit/sheet/sheet_trigger.rb +6 -0
- data/app/components/phlex_kit/shortcut_key/shortcut_key.css +17 -0
- data/app/components/phlex_kit/shortcut_key/shortcut_key.rb +9 -0
- data/app/components/phlex_kit/sidebar/sidebar.css +42 -0
- data/app/components/phlex_kit/sidebar/sidebar.rb +19 -0
- data/app/components/phlex_kit/sidebar/sidebar_content.rb +12 -0
- data/app/components/phlex_kit/sidebar/sidebar_footer.rb +12 -0
- data/app/components/phlex_kit/sidebar/sidebar_group.rb +12 -0
- data/app/components/phlex_kit/sidebar/sidebar_header.rb +12 -0
- data/app/components/phlex_kit/sidebar/sidebar_inset.rb +14 -0
- data/app/components/phlex_kit/sidebar/sidebar_menu.rb +12 -0
- data/app/components/phlex_kit/sidebar/sidebar_menu_button.rb +17 -0
- data/app/components/phlex_kit/sidebar/sidebar_menu_item.rb +12 -0
- data/app/components/phlex_kit/sidebar/sidebar_wrapper.rb +13 -0
- data/app/components/phlex_kit/skeleton/skeleton.css +7 -0
- data/app/components/phlex_kit/skeleton/skeleton.rb +9 -0
- data/app/components/phlex_kit/slider/slider.css +52 -0
- data/app/components/phlex_kit/slider/slider.rb +39 -0
- data/app/components/phlex_kit/spinner/spinner.css +5 -0
- data/app/components/phlex_kit/spinner/spinner.rb +27 -0
- data/app/components/phlex_kit/stars/stars.css +4 -0
- data/app/components/phlex_kit/stars/stars.rb +19 -0
- data/app/components/phlex_kit/switch/switch.css +28 -0
- data/app/components/phlex_kit/switch/switch.rb +21 -0
- data/app/components/phlex_kit/table/table.css +24 -0
- data/app/components/phlex_kit/table/table.rb +35 -0
- data/app/components/phlex_kit/table/table_body.rb +12 -0
- data/app/components/phlex_kit/table/table_caption.rb +12 -0
- data/app/components/phlex_kit/table/table_cell.rb +12 -0
- data/app/components/phlex_kit/table/table_footer.rb +12 -0
- data/app/components/phlex_kit/table/table_head.rb +12 -0
- data/app/components/phlex_kit/table/table_header.rb +12 -0
- data/app/components/phlex_kit/table/table_row.rb +12 -0
- data/app/components/phlex_kit/tabs/tabs.css +13 -0
- data/app/components/phlex_kit/tabs/tabs.rb +13 -0
- data/app/components/phlex_kit/tabs/tabs_content.rb +11 -0
- data/app/components/phlex_kit/tabs/tabs_list.rb +6 -0
- data/app/components/phlex_kit/tabs/tabs_trigger.rb +17 -0
- data/app/components/phlex_kit/textarea/textarea.css +27 -0
- data/app/components/phlex_kit/textarea/textarea.rb +24 -0
- data/app/components/phlex_kit/theme_toggle/theme_toggle.rb +15 -0
- data/app/components/phlex_kit/toast/toast.css +163 -0
- data/app/components/phlex_kit/toast/toast.rb +21 -0
- data/app/components/phlex_kit/toast/toast_action.rb +19 -0
- data/app/components/phlex_kit/toast/toast_cancel.rb +18 -0
- data/app/components/phlex_kit/toast/toast_close.rb +35 -0
- data/app/components/phlex_kit/toast/toast_description.rb +13 -0
- data/app/components/phlex_kit/toast/toast_icon.rb +63 -0
- data/app/components/phlex_kit/toast/toast_item.rb +70 -0
- data/app/components/phlex_kit/toast/toast_region.rb +121 -0
- data/app/components/phlex_kit/toast/toast_title.rb +13 -0
- data/app/components/phlex_kit/toggle/toggle.css +16 -0
- data/app/components/phlex_kit/toggle/toggle.rb +59 -0
- data/app/components/phlex_kit/toggle_group/toggle_group.css +10 -0
- data/app/components/phlex_kit/toggle_group/toggle_group.rb +65 -0
- data/app/components/phlex_kit/toggle_group/toggle_group_item.rb +37 -0
- data/app/components/phlex_kit/tooltip/tooltip.css +28 -0
- data/app/components/phlex_kit/tooltip/tooltip.rb +15 -0
- data/app/components/phlex_kit/tooltip/tooltip_content.rb +12 -0
- data/app/components/phlex_kit/tooltip/tooltip_trigger.rb +13 -0
- data/app/components/phlex_kit/typography/blockquote.rb +12 -0
- data/app/components/phlex_kit/typography/heading.rb +38 -0
- data/app/components/phlex_kit/typography/inline_code.rb +13 -0
- data/app/components/phlex_kit/typography/inline_link.rb +15 -0
- data/app/components/phlex_kit/typography/text.rb +48 -0
- data/app/components/phlex_kit/typography/typography.css +50 -0
- data/app/javascript/phlex_kit/controllers/accordion_controller.js +59 -0
- data/app/javascript/phlex_kit/controllers/alert_dialog_controller.js +24 -0
- data/app/javascript/phlex_kit/controllers/avatar_controller.js +30 -0
- data/app/javascript/phlex_kit/controllers/calendar_controller.js +316 -0
- data/app/javascript/phlex_kit/controllers/calendar_input_controller.js +10 -0
- data/app/javascript/phlex_kit/controllers/carousel_controller.js +189 -0
- data/app/javascript/phlex_kit/controllers/chart_controller.js +135 -0
- data/app/javascript/phlex_kit/controllers/clipboard_controller.js +30 -0
- data/app/javascript/phlex_kit/controllers/collapsible_controller.js +14 -0
- data/app/javascript/phlex_kit/controllers/combobox_controller.js +303 -0
- data/app/javascript/phlex_kit/controllers/command_controller.js +161 -0
- data/app/javascript/phlex_kit/controllers/command_dialog_controller.js +37 -0
- data/app/javascript/phlex_kit/controllers/context_menu_controller.js +28 -0
- data/app/javascript/phlex_kit/controllers/data_table_column_visibility_controller.js +18 -0
- data/app/javascript/phlex_kit/controllers/data_table_controller.js +61 -0
- data/app/javascript/phlex_kit/controllers/data_table_search_controller.js +67 -0
- data/app/javascript/phlex_kit/controllers/dialog_controller.js +20 -0
- data/app/javascript/phlex_kit/controllers/dropdown_menu_controller.js +106 -0
- data/app/javascript/phlex_kit/controllers/form_field_controller.js +69 -0
- data/app/javascript/phlex_kit/controllers/hover_card_controller.js +11 -0
- data/app/javascript/phlex_kit/controllers/index.js +87 -0
- data/app/javascript/phlex_kit/controllers/input_otp_controller.js +66 -0
- data/app/javascript/phlex_kit/controllers/masked_input_controller.js +26 -0
- data/app/javascript/phlex_kit/controllers/menubar_controller.js +43 -0
- data/app/javascript/phlex_kit/controllers/message_scroller_controller.js +335 -0
- data/app/javascript/phlex_kit/controllers/popover_controller.js +12 -0
- data/app/javascript/phlex_kit/controllers/resizable_controller.js +42 -0
- data/app/javascript/phlex_kit/controllers/select_controller.js +141 -0
- data/app/javascript/phlex_kit/controllers/select_item_controller.js +14 -0
- data/app/javascript/phlex_kit/controllers/sheet_content_controller.js +6 -0
- data/app/javascript/phlex_kit/controllers/sheet_controller.js +10 -0
- data/app/javascript/phlex_kit/controllers/slider_controller.js +19 -0
- data/app/javascript/phlex_kit/controllers/tabs_controller.js +28 -0
- data/app/javascript/phlex_kit/controllers/theme_toggle_controller.js +22 -0
- data/app/javascript/phlex_kit/controllers/toast_controller.js +153 -0
- data/app/javascript/phlex_kit/controllers/toaster_controller.js +321 -0
- data/app/javascript/phlex_kit/controllers/toggle_controller.js +25 -0
- data/app/javascript/phlex_kit/controllers/toggle_group_controller.js +91 -0
- data/config/importmap.rb +7 -0
- data/lib/generators/phlex_kit/component/component_generator.rb +41 -0
- data/lib/generators/phlex_kit/install/install_generator.rb +51 -0
- data/lib/generators/phlex_kit/install/templates/phlex_kit.rb +11 -0
- data/lib/phlex_kit/base_component.rb +22 -0
- data/lib/phlex_kit/configuration.rb +46 -0
- data/lib/phlex_kit/engine.rb +50 -0
- data/lib/phlex_kit/propshaft_skip_source.rb +22 -0
- data/lib/phlex_kit/version.rb +5 -0
- data/lib/phlex_kit.rb +21 -0
- metadata +545 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* Co-located with label.rb — UI::Label, shadcn parity (text-sm font-medium,
|
|
2
|
+
dims when its control is disabled). */
|
|
3
|
+
.pk-label {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: .5rem;
|
|
7
|
+
font-size: .875rem;
|
|
8
|
+
font-weight: 500;
|
|
9
|
+
line-height: 1;
|
|
10
|
+
user-select: none;
|
|
11
|
+
}
|
|
12
|
+
.pk-label:has(+ :disabled), .pk-label:has(:disabled) { cursor: not-allowed; opacity: .5; }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Standalone form label, ported from shadcn/ui's Label (FormFieldLabel is the
|
|
3
|
+
# ruby_ui-shaped equivalent inside a FormField). Pass `for:` to bind it.
|
|
4
|
+
# `.pk-label` (label.css).
|
|
5
|
+
class Label < BaseComponent
|
|
6
|
+
def initialize(**attrs)
|
|
7
|
+
@attrs = attrs
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template(&)
|
|
11
|
+
label(**mix({ class: "pk-label" }, @attrs), &)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* Co-located with link.rb — UI::Link. The button-styled variants deliberately
|
|
2
|
+
REUSE the `.pk-button*` classes from button.css (Link shares Button's exact
|
|
3
|
+
variant/size vocabulary), so this file only carries the link-specific niceties
|
|
4
|
+
on top: ruby_ui's `underline-offset-4` for the inline `:link` variant. Theme
|
|
5
|
+
tokens come from the global stylesheet. */
|
|
6
|
+
.pk-button.link { text-underline-offset: 4px; }
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Link, ported from ruby_ui's RubyUI::Link — an <a> that wears PhlexKit::Button's
|
|
3
|
+
# look. Same variant/size vocabulary as Button, so it reuses the `.pk-button*`
|
|
4
|
+
# classes from button.css (link.css only adds the inline :link treatment).
|
|
5
|
+
# Default variant is :link (an inline underline-on-hover link); the button-style
|
|
6
|
+
# variants turn it into a button-styled anchor (ruby_ui's "Link" concept — what
|
|
7
|
+
# we already do ad-hoc with `a(class: "pk-button outline sm")`).
|
|
8
|
+
#
|
|
9
|
+
# Presentational; `mix` passes `**@attrs` (incl. data-*) straight through.
|
|
10
|
+
# `VARIANTS.fetch`/`SIZES.fetch` fail loud.
|
|
11
|
+
class Link < BaseComponent
|
|
12
|
+
# Mirrors PhlexKit::Button's vocabulary 1:1 so the shared `.pk-button*` CSS applies.
|
|
13
|
+
VARIANTS = {
|
|
14
|
+
link: "link",
|
|
15
|
+
primary: "primary",
|
|
16
|
+
secondary: "secondary",
|
|
17
|
+
destructive: "destructive",
|
|
18
|
+
outline: "outline",
|
|
19
|
+
ghost: "ghost"
|
|
20
|
+
}.freeze
|
|
21
|
+
|
|
22
|
+
SIZES = {
|
|
23
|
+
sm: "sm",
|
|
24
|
+
md: nil,
|
|
25
|
+
lg: "lg",
|
|
26
|
+
xl: "xl"
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
def initialize(href: "#", variant: :link, size: :md, icon: false, **attrs)
|
|
30
|
+
@href = href
|
|
31
|
+
@variant = variant.to_sym
|
|
32
|
+
@size = size.to_sym
|
|
33
|
+
@icon = icon
|
|
34
|
+
@attrs = attrs
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def view_template(&block)
|
|
38
|
+
a(**mix({ href: @href, class: classes }, @attrs), &block)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def classes
|
|
44
|
+
[ "pk-button", VARIANTS.fetch(@variant), SIZES.fetch(@size), ("icon" if @icon) ].compact.join(" ")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Text input with an inline mask. Ported from ruby_ui's RubyUI::MaskedInput —
|
|
3
|
+
# ruby_ui uses the `maska` JS lib; PhlexKit ships a small dependency-free mask
|
|
4
|
+
# controller (#=digit, A=letter, *=any) driven by a data-mask attribute. Swap in
|
|
5
|
+
# maska by replacing masked_input_controller.js if you need its full feature set.
|
|
6
|
+
class MaskedInput < BaseComponent
|
|
7
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
8
|
+
def view_template
|
|
9
|
+
render PhlexKit::Input.new(type: "text", **mix({ data: { controller: "phlex-kit--masked-input" } }, @attrs))
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* Co-located with menubar.rb — UI::Menubar, shadcn parity (Radix replaced by
|
|
2
|
+
the phlex-kit--menubar controller). NavigationMenu shares the item look. */
|
|
3
|
+
.pk-menubar {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: .25rem;
|
|
7
|
+
border: 1px solid var(--pk-border);
|
|
8
|
+
border-radius: var(--pk-radius);
|
|
9
|
+
background: var(--pk-surface);
|
|
10
|
+
padding: .25rem;
|
|
11
|
+
}
|
|
12
|
+
.pk-menubar-menu { position: relative; }
|
|
13
|
+
.pk-menubar-trigger {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
border: 0;
|
|
17
|
+
border-radius: calc(var(--pk-radius) - 4px);
|
|
18
|
+
background: transparent;
|
|
19
|
+
color: var(--pk-text);
|
|
20
|
+
padding: .25rem .5rem;
|
|
21
|
+
font: inherit;
|
|
22
|
+
font-size: .875rem;
|
|
23
|
+
font-weight: 500;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
outline: none;
|
|
26
|
+
}
|
|
27
|
+
.pk-menubar-trigger:hover,
|
|
28
|
+
.pk-menubar-trigger[aria-expanded="true"] { background: var(--pk-accent); }
|
|
29
|
+
.pk-menubar-content {
|
|
30
|
+
position: absolute;
|
|
31
|
+
top: 100%;
|
|
32
|
+
left: 0;
|
|
33
|
+
z-index: 50;
|
|
34
|
+
min-width: 12rem;
|
|
35
|
+
margin-top: .5rem;
|
|
36
|
+
border: 1px solid var(--pk-border);
|
|
37
|
+
border-radius: var(--pk-radius);
|
|
38
|
+
background: var(--pk-surface);
|
|
39
|
+
color: var(--pk-text);
|
|
40
|
+
padding: .25rem;
|
|
41
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / .3);
|
|
42
|
+
}
|
|
43
|
+
.pk-menubar-item {
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
gap: .5rem;
|
|
47
|
+
border-radius: calc(var(--pk-radius) - 4px);
|
|
48
|
+
padding: .375rem .5rem;
|
|
49
|
+
font-size: .875rem;
|
|
50
|
+
color: var(--pk-text);
|
|
51
|
+
text-decoration: none;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
user-select: none;
|
|
54
|
+
outline: none;
|
|
55
|
+
}
|
|
56
|
+
.pk-menubar-item:hover, .pk-menubar-item:focus { background: var(--pk-accent); }
|
|
57
|
+
.pk-menubar-shortcut { margin-left: auto; font-size: .75rem; color: var(--pk-muted); letter-spacing: .1em; }
|
|
58
|
+
.pk-menubar-separator { height: 1px; margin: .25rem -0.25rem; background: var(--pk-border); }
|
|
59
|
+
.pk-menubar-content::before {
|
|
60
|
+
content: "";
|
|
61
|
+
position: absolute;
|
|
62
|
+
top: calc(-.5rem - 1px);
|
|
63
|
+
left: 0;
|
|
64
|
+
right: 0;
|
|
65
|
+
height: calc(.5rem + 1px);
|
|
66
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Desktop-style menu bar, ported from shadcn/ui's Menubar (Radix replaced by
|
|
3
|
+
# the phlex-kit--menubar controller: click opens a menu, hover switches
|
|
4
|
+
# between open menus, Escape/outside closes). Compose Menubar > MenubarMenu >
|
|
5
|
+
# (MenubarTrigger + MenubarContent > MenubarItem/MenubarSeparator).
|
|
6
|
+
# NavigationMenu shares the controller in hover mode. `.pk-menubar*`
|
|
7
|
+
# (menubar.css).
|
|
8
|
+
class Menubar < BaseComponent
|
|
9
|
+
def initialize(**attrs)
|
|
10
|
+
@attrs = attrs
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def view_template(&)
|
|
14
|
+
div(**mix({
|
|
15
|
+
class: "pk-menubar",
|
|
16
|
+
role: "menubar",
|
|
17
|
+
data: {
|
|
18
|
+
controller: "phlex-kit--menubar",
|
|
19
|
+
action: "click@window->phlex-kit--menubar#onClickOutside keydown.esc->phlex-kit--menubar#close"
|
|
20
|
+
}
|
|
21
|
+
}, @attrs), &)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Dropdown panel of a MenubarMenu. See menubar.rb.
|
|
3
|
+
class MenubarContent < BaseComponent
|
|
4
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
5
|
+
def view_template(&)
|
|
6
|
+
div(**mix({ class: "pk-menubar-content pk-hidden", role: "menu" }, @attrs), &)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Menu row (an <a> — pass href:, or as: :div for buttons). Closes the bar.
|
|
3
|
+
# See menubar.rb.
|
|
4
|
+
class MenubarItem < BaseComponent
|
|
5
|
+
def initialize(as: :a, href: "#", shortcut: nil, **attrs)
|
|
6
|
+
@as = as.to_sym
|
|
7
|
+
@href = href
|
|
8
|
+
@shortcut = shortcut
|
|
9
|
+
@attrs = attrs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def view_template(&block)
|
|
13
|
+
base = {
|
|
14
|
+
role: "menuitem",
|
|
15
|
+
tabindex: "-1",
|
|
16
|
+
class: "pk-menubar-item",
|
|
17
|
+
data: { action: "click->phlex-kit--menubar#close" }
|
|
18
|
+
}
|
|
19
|
+
base[:href] = @href unless @as == :div
|
|
20
|
+
send(@as, **mix(base, @attrs)) do
|
|
21
|
+
block&.call
|
|
22
|
+
span(class: "pk-menubar-shortcut") { @shortcut } if @shortcut
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# One trigger+panel pair in a Menubar. See menubar.rb.
|
|
3
|
+
class MenubarMenu < BaseComponent
|
|
4
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
5
|
+
def view_template(&)
|
|
6
|
+
div(**mix({ class: "pk-menubar-menu", data: { phlex_kit__menubar_target: "menu" } }, @attrs), &)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# See menubar.rb.
|
|
3
|
+
class MenubarTrigger < BaseComponent
|
|
4
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
5
|
+
def view_template(&)
|
|
6
|
+
button(**mix({
|
|
7
|
+
type: :button,
|
|
8
|
+
class: "pk-menubar-trigger",
|
|
9
|
+
aria: { haspopup: "menu", expanded: "false" },
|
|
10
|
+
data: { action: "click->phlex-kit--menubar#toggle mouseenter->phlex-kit--menubar#switch" }
|
|
11
|
+
}, @attrs), &)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* Co-located with message.rb. Theme tokens from the global stylesheet. */
|
|
2
|
+
.pk-message {
|
|
3
|
+
position: relative; display: flex; width: 100%; min-width: 0;
|
|
4
|
+
gap: .5rem; font-size: .875rem;
|
|
5
|
+
}
|
|
6
|
+
.pk-message[data-align="end"] { flex-direction: row-reverse; }
|
|
7
|
+
.pk-message-content { display: flex; width: 100%; min-width: 0; flex-direction: column; gap: .625rem; overflow-wrap: break-word; }
|
|
8
|
+
.pk-message[data-align="end"] .pk-message-content > [data-slot] { align-self: flex-end; }
|
|
9
|
+
.pk-message-group { display: flex; min-width: 0; flex-direction: column; gap: .5rem; }
|
|
10
|
+
.pk-message-header,
|
|
11
|
+
.pk-message-footer {
|
|
12
|
+
display: flex; max-width: 100%; min-width: 0; align-items: center;
|
|
13
|
+
padding-inline: .75rem; font-size: .75rem; font-weight: 500; color: var(--pk-muted);
|
|
14
|
+
}
|
|
15
|
+
.pk-message[data-align="end"] .pk-message-footer { justify-content: flex-end; }
|
|
16
|
+
.pk-message-avatar {
|
|
17
|
+
display: flex; width: fit-content; min-width: 2rem; flex: none;
|
|
18
|
+
align-items: center; justify-content: center; align-self: flex-end;
|
|
19
|
+
overflow: hidden; border-radius: 9999px; background: var(--pk-surface-2);
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Chat message row (avatar + content), ported from ruby_ui's RubyUI::Message.
|
|
3
|
+
# align: :end reverses the row. Compose Message > MessageContent (+ Avatar/
|
|
4
|
+
# Header/Footer); group several in a MessageGroup.
|
|
5
|
+
class Message < BaseComponent
|
|
6
|
+
def initialize(align: :start, **attrs)
|
|
7
|
+
@align = align.to_sym
|
|
8
|
+
@attrs = attrs
|
|
9
|
+
end
|
|
10
|
+
def view_template(&)
|
|
11
|
+
div(**mix({ class: "pk-message", data: { slot: "message", align: @align } }, @attrs), &)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Height-constrained chat transcript with autoscroll/anchoring. Ported from
|
|
3
|
+
# ruby_ui's RubyUI::MessageScroller. Mark the scroll viewport, content list, and
|
|
4
|
+
# jump button inside with data-phlex-kit--message-scroller-target attributes.
|
|
5
|
+
class MessageScroller < BaseComponent
|
|
6
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
7
|
+
def view_template(&)
|
|
8
|
+
div(**mix({ class: "pk-message-scroller", data: { controller: "phlex-kit--message-scroller", slot: "message-scroller" } }, @attrs), &)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* Co-located with native_select.rb — UI::NativeSelect (+ Icon / Option / Group).
|
|
2
|
+
ruby_ui's structure kept verbatim (wrapper > appearance:none select + absolute
|
|
3
|
+
chevron); only the styling is ours, vanilla CSS on the palette tokens. Geometry
|
|
4
|
+
from ruby_ui (h-9 default / h-7 sm, rounded-md, pr-8 pl-2.5, ring-on-focus).
|
|
5
|
+
Theme tokens come from the global stylesheet. */
|
|
6
|
+
.pk-native-select {
|
|
7
|
+
position: relative;
|
|
8
|
+
display: inline-flex;
|
|
9
|
+
width: 100%;
|
|
10
|
+
}
|
|
11
|
+
.pk-native-select-field {
|
|
12
|
+
width: 100%;
|
|
13
|
+
min-width: 0;
|
|
14
|
+
height: 2rem;
|
|
15
|
+
appearance: none;
|
|
16
|
+
-webkit-appearance: none;
|
|
17
|
+
border-radius: calc(var(--pk-radius) - 2px);
|
|
18
|
+
border: 1px solid var(--pk-input);
|
|
19
|
+
background: transparent;
|
|
20
|
+
color: var(--pk-text);
|
|
21
|
+
font: inherit;
|
|
22
|
+
font-size: .875rem;
|
|
23
|
+
padding: .25rem 2rem .25rem .625rem;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
transition: color .15s ease, border-color .15s ease, box-shadow .15s ease;
|
|
26
|
+
}
|
|
27
|
+
.pk-native-select-field:focus-visible {
|
|
28
|
+
outline: none;
|
|
29
|
+
border-color: var(--pk-brand);
|
|
30
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
31
|
+
}
|
|
32
|
+
.pk-native-select-field:disabled { cursor: not-allowed; opacity: .5; }
|
|
33
|
+
.pk-native-select-field.sm {
|
|
34
|
+
height: 1.75rem;
|
|
35
|
+
padding-top: .125rem;
|
|
36
|
+
padding-bottom: .125rem;
|
|
37
|
+
}
|
|
38
|
+
/* Native option lists are OS-drawn; force a readable palette where honoured. */
|
|
39
|
+
.pk-native-select-field option,
|
|
40
|
+
.pk-native-select-field optgroup { background: var(--pk-surface); color: var(--pk-text); }
|
|
41
|
+
.pk-native-select-icon {
|
|
42
|
+
position: absolute;
|
|
43
|
+
top: 50%;
|
|
44
|
+
right: .625rem;
|
|
45
|
+
transform: translateY(-50%);
|
|
46
|
+
display: flex;
|
|
47
|
+
pointer-events: none;
|
|
48
|
+
user-select: none;
|
|
49
|
+
color: var(--pk-muted);
|
|
50
|
+
}
|
|
51
|
+
.pk-native-select-icon svg { width: 1rem; height: 1rem; }
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Styled native <select>, ported from ruby_ui's RubyUI::NativeSelect. A real
|
|
3
|
+
# browser select (native option list, mobile-friendly) wrapped so we can hide
|
|
4
|
+
# the OS chevron (appearance:none) and draw our own — otherwise the native
|
|
5
|
+
# arrow renders an inconsistent light-on-dark box. Multi-part, like PhlexKit::Card:
|
|
6
|
+
#
|
|
7
|
+
# render PhlexKit::NativeSelect.new(name: "store_id") do
|
|
8
|
+
# render PhlexKit::NativeSelectOption.new(value: "") { "All stores" }
|
|
9
|
+
# render PhlexKit::NativeSelectGroup.new(label: "Live") do
|
|
10
|
+
# render PhlexKit::NativeSelectOption.new(value: store.id) { store.name }
|
|
11
|
+
# end
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# The yielded block is the <option>/<optgroup> list; `name:`/`id:`/`required:`/
|
|
15
|
+
# `**on(...)` pass through to the <select> via `mix`. `size:` is the kit's lone
|
|
16
|
+
# selector here (default | sm) — `SIZES.fetch` fails loud on anything else.
|
|
17
|
+
class NativeSelect < BaseComponent
|
|
18
|
+
# size => extra class appended after the base select class (nil = default).
|
|
19
|
+
SIZES = {
|
|
20
|
+
default: nil,
|
|
21
|
+
sm: "sm"
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
def initialize(size: :default, **attrs)
|
|
25
|
+
@size = size.to_sym
|
|
26
|
+
@attrs = attrs
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def view_template(&block)
|
|
30
|
+
div(class: "pk-native-select") do
|
|
31
|
+
select(**mix({
|
|
32
|
+
class: classes,
|
|
33
|
+
data: {
|
|
34
|
+
phlex_kit__form_field_target: "input",
|
|
35
|
+
action: "change->phlex-kit--form-field#onChange invalid->phlex-kit--form-field#onInvalid"
|
|
36
|
+
}
|
|
37
|
+
}, @attrs), &block)
|
|
38
|
+
render PhlexKit::NativeSelectIcon.new
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def classes
|
|
45
|
+
[ "pk-native-select-field", SIZES.fetch(@size) ].compact.join(" ")
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# An <optgroup> inside PhlexKit::NativeSelect — labels a cluster of options
|
|
3
|
+
# (`label:` passes through). Plain pass-through wrapper. See native_select.rb.
|
|
4
|
+
class NativeSelectGroup < BaseComponent
|
|
5
|
+
def initialize(**attrs)
|
|
6
|
+
@attrs = attrs
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def view_template(&block)
|
|
10
|
+
optgroup(**@attrs, &block)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# The chevron that sits over the appearance:none <select> in PhlexKit::NativeSelect.
|
|
3
|
+
# Mirrors ruby_ui's NativeSelectIcon: renders a default chevron SVG, or a
|
|
4
|
+
# caller-supplied block in its place. The svg uses `currentColor`, so the icon
|
|
5
|
+
# colour is driven by `.pk-native-select-icon`'s `color` token (native_select.css).
|
|
6
|
+
class NativeSelectIcon < BaseComponent
|
|
7
|
+
def initialize(**attrs)
|
|
8
|
+
@attrs = attrs
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def view_template(&block)
|
|
12
|
+
span(**mix({ class: "pk-native-select-icon" }, @attrs)) do
|
|
13
|
+
block ? yield : chevron
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def chevron
|
|
20
|
+
svg(
|
|
21
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
22
|
+
viewbox: "0 0 24 24",
|
|
23
|
+
fill: "none",
|
|
24
|
+
stroke: "currentColor",
|
|
25
|
+
"stroke-width": "2",
|
|
26
|
+
"stroke-linecap": "round",
|
|
27
|
+
"stroke-linejoin": "round",
|
|
28
|
+
"aria-hidden": "true"
|
|
29
|
+
) { |s| s.path(d: "m6 9 6 6 6-6") }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# A single <option> inside PhlexKit::NativeSelect. Plain pass-through wrapper (no
|
|
3
|
+
# base class); `value:`/`selected:`/`disabled:` ride through to the element.
|
|
4
|
+
# See native_select.rb.
|
|
5
|
+
class NativeSelectOption < BaseComponent
|
|
6
|
+
def initialize(**attrs)
|
|
7
|
+
@attrs = attrs
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template(&block)
|
|
11
|
+
option(**@attrs, &block)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* Co-located with navigation_menu.rb — UI::NavigationMenu, shadcn parity
|
|
2
|
+
(Radix replaced by the shared phlex-kit--menubar controller, hover mode). */
|
|
3
|
+
.pk-navigation-menu { position: relative; display: flex; }
|
|
4
|
+
.pk-navigation-menu-list {
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
gap: .25rem;
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 0;
|
|
10
|
+
list-style: none;
|
|
11
|
+
}
|
|
12
|
+
.pk-navigation-menu-item { position: relative; }
|
|
13
|
+
.pk-navigation-menu-trigger, .pk-navigation-menu-link {
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: .25rem;
|
|
17
|
+
height: 2.25rem;
|
|
18
|
+
border: 0;
|
|
19
|
+
border-radius: calc(var(--pk-radius) - 2px);
|
|
20
|
+
background: transparent;
|
|
21
|
+
color: var(--pk-text);
|
|
22
|
+
padding: .5rem .75rem;
|
|
23
|
+
font: inherit;
|
|
24
|
+
font-size: .875rem;
|
|
25
|
+
font-weight: 500;
|
|
26
|
+
text-decoration: none;
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
outline: none;
|
|
29
|
+
transition: background-color .15s ease;
|
|
30
|
+
}
|
|
31
|
+
.pk-navigation-menu-trigger:hover, .pk-navigation-menu-link:hover,
|
|
32
|
+
.pk-navigation-menu-trigger[aria-expanded="true"] { background: var(--pk-accent); }
|
|
33
|
+
.pk-navigation-menu-chevron { width: .75rem; height: .75rem; transition: transform .2s ease; }
|
|
34
|
+
.pk-navigation-menu-trigger[aria-expanded="true"] .pk-navigation-menu-chevron { transform: rotate(180deg); }
|
|
35
|
+
.pk-navigation-menu-content {
|
|
36
|
+
position: absolute;
|
|
37
|
+
/* invisible bridge over the gap so hovering toward the panel doesn't
|
|
38
|
+
mouseleave the nav and close it */
|
|
39
|
+
--pk-nav-gap: .375rem;
|
|
40
|
+
top: 100%;
|
|
41
|
+
left: 0;
|
|
42
|
+
z-index: 50;
|
|
43
|
+
min-width: 16rem;
|
|
44
|
+
margin-top: var(--pk-nav-gap);
|
|
45
|
+
border: 1px solid var(--pk-border);
|
|
46
|
+
border-radius: var(--pk-radius);
|
|
47
|
+
background: var(--pk-surface);
|
|
48
|
+
color: var(--pk-text);
|
|
49
|
+
padding: .5rem;
|
|
50
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / .3);
|
|
51
|
+
}
|
|
52
|
+
.pk-navigation-menu-content .pk-navigation-menu-link {
|
|
53
|
+
display: flex;
|
|
54
|
+
height: auto;
|
|
55
|
+
width: 100%;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
align-items: flex-start;
|
|
58
|
+
gap: .25rem;
|
|
59
|
+
}
|
|
60
|
+
.pk-navigation-menu-content::before {
|
|
61
|
+
content: "";
|
|
62
|
+
position: absolute;
|
|
63
|
+
top: calc(-1 * var(--pk-nav-gap) - 1px);
|
|
64
|
+
left: 0;
|
|
65
|
+
right: 0;
|
|
66
|
+
height: calc(var(--pk-nav-gap) + 1px);
|
|
67
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Site navigation with hoverable panels, ported from shadcn/ui's
|
|
3
|
+
# NavigationMenu. Shares the phlex-kit--menubar controller in hover-open mode
|
|
4
|
+
# (data-hover-open). Compose NavigationMenu > NavigationMenuList >
|
|
5
|
+
# NavigationMenuItem > (NavigationMenuTrigger + NavigationMenuContent |
|
|
6
|
+
# NavigationMenuLink). `.pk-navigation-menu*` (navigation_menu.css).
|
|
7
|
+
class NavigationMenu < BaseComponent
|
|
8
|
+
def initialize(**attrs)
|
|
9
|
+
@attrs = attrs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def view_template(&)
|
|
13
|
+
nav(**mix({
|
|
14
|
+
class: "pk-navigation-menu",
|
|
15
|
+
data: {
|
|
16
|
+
controller: "phlex-kit--menubar",
|
|
17
|
+
hover_open: true,
|
|
18
|
+
action: "click@window->phlex-kit--menubar#onClickOutside keydown.esc->phlex-kit--menubar#close mouseleave->phlex-kit--menubar#close"
|
|
19
|
+
}
|
|
20
|
+
}, @attrs), &)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Hover panel of a NavigationMenuItem. See navigation_menu.rb.
|
|
3
|
+
class NavigationMenuContent < BaseComponent
|
|
4
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
5
|
+
def view_template(&)
|
|
6
|
+
div(**mix({ class: "pk-navigation-menu-content pk-hidden", role: "menu" }, @attrs), &)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# See navigation_menu.rb.
|
|
3
|
+
class NavigationMenuItem < BaseComponent
|
|
4
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
5
|
+
def view_template(&)
|
|
6
|
+
li(**mix({ class: "pk-navigation-menu-item", data: { phlex_kit__menubar_target: "menu" } }, @attrs), &)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Plain link item (top-level or inside a panel). See navigation_menu.rb.
|
|
3
|
+
class NavigationMenuLink < BaseComponent
|
|
4
|
+
def initialize(href: "#", **attrs)
|
|
5
|
+
@href = href
|
|
6
|
+
@attrs = attrs
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def view_template(&)
|
|
10
|
+
a(**mix({ class: "pk-navigation-menu-link", href: @href }, @attrs), &)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|