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,21 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# The text shown in a PhlexKit::SelectTrigger — the selected item's label (yielded
|
|
3
|
+
# block) or the `placeholder:` when nothing is chosen. The Stimulus controller
|
|
4
|
+
# rewrites this element's text on selection. See select.rb.
|
|
5
|
+
class SelectValue < BaseComponent
|
|
6
|
+
def initialize(placeholder: nil, **attrs)
|
|
7
|
+
@placeholder = placeholder
|
|
8
|
+
@attrs = attrs
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def view_template(&block)
|
|
12
|
+
span(**mix({ class: "pk-select-value", data: { phlex_kit__select_target: "value" } }, @attrs)) do
|
|
13
|
+
if block
|
|
14
|
+
yield
|
|
15
|
+
elsif @placeholder
|
|
16
|
+
plain @placeholder
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* Co-located with separator.rb — UI::Separator. ruby_ui's Tailwind
|
|
2
|
+
(`shrink-0 bg-border` + `h-[1px] w-full` / `h-full w-[1px]`) as vanilla CSS on
|
|
3
|
+
the palette tokens. Theme tokens come from the global stylesheet. */
|
|
4
|
+
.pk-separator { flex-shrink: 0; background: var(--pk-border); border: 0; }
|
|
5
|
+
.pk-separator.horizontal { height: 1px; width: 100%; }
|
|
6
|
+
.pk-separator.vertical { height: 100%; width: 1px; }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Visual/semantic divider, ported from ruby_ui's RubyUI::Separator. `as:` picks
|
|
3
|
+
# the element (div/hr), `orientation:` is horizontal (default) or vertical, and
|
|
4
|
+
# `decorative:` toggles the a11y role (none vs separator). Presentational; attrs
|
|
5
|
+
# pass through via `mix`. A bad orientation fails loud (ArgumentError), mirroring
|
|
6
|
+
# the kit's fail-loud selectors.
|
|
7
|
+
class Separator < BaseComponent
|
|
8
|
+
ORIENTATIONS = %i[horizontal vertical].freeze
|
|
9
|
+
|
|
10
|
+
def initialize(as: :div, orientation: :horizontal, decorative: true, **attrs)
|
|
11
|
+
@as = as
|
|
12
|
+
@orientation = orientation.to_sym
|
|
13
|
+
unless ORIENTATIONS.include?(@orientation)
|
|
14
|
+
raise ArgumentError, "Invalid orientation: #{orientation.inspect}"
|
|
15
|
+
end
|
|
16
|
+
@decorative = decorative
|
|
17
|
+
@attrs = attrs
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def view_template(&block)
|
|
21
|
+
send(@as, **mix({ role: (@decorative ? "none" : "separator"), class: classes }, @attrs), &block)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def classes
|
|
27
|
+
[ "pk-separator", @orientation.to_s ].join(" ")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* Co-located with sheet.rb. Theme tokens from the global stylesheet. */
|
|
2
|
+
.pk-sheet-trigger { display: inline-block; }
|
|
3
|
+
.pk-sheet-backdrop { position: fixed; inset: 0; z-index: 50; background: rgb(0 0 0 / .5); backdrop-filter: blur(2px); }
|
|
4
|
+
.pk-sheet-content {
|
|
5
|
+
position: fixed; z-index: 50; display: flex; flex-direction: column; gap: 1rem;
|
|
6
|
+
background: var(--pk-surface); color: var(--pk-text); padding: 1.5rem;
|
|
7
|
+
box-shadow: 0 10px 30px rgb(0 0 0 / .35); overflow: auto;
|
|
8
|
+
}
|
|
9
|
+
.pk-sheet-content.right { inset-block: 0; right: 0; height: 100%; width: min(24rem, 100%); border-left: 1px solid var(--pk-border); }
|
|
10
|
+
.pk-sheet-content.left { inset-block: 0; left: 0; height: 100%; width: min(24rem, 100%); border-right: 1px solid var(--pk-border); }
|
|
11
|
+
.pk-sheet-content.top { inset-inline: 0; top: 0; border-bottom: 1px solid var(--pk-border); }
|
|
12
|
+
.pk-sheet-content.bottom { inset-inline: 0; bottom: 0; border-top: 1px solid var(--pk-border); }
|
|
13
|
+
.pk-sheet-header { display: flex; flex-direction: column; gap: .375rem; }
|
|
14
|
+
.pk-sheet-footer { display: flex; flex-direction: column-reverse; gap: .5rem; }
|
|
15
|
+
.pk-sheet-title { font-size: 1.125rem; font-weight: 600; line-height: 1; letter-spacing: -.01em; }
|
|
16
|
+
.pk-sheet-description { font-size: .875rem; color: var(--pk-muted); }
|
|
17
|
+
.pk-sheet-middle { padding-block: 1rem; }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Side panel (drawer). Ported from ruby_ui's RubyUI::Sheet. Compose Sheet >
|
|
3
|
+
# (SheetTrigger + SheetContent(side:) > SheetHeader/Title/Description/Footer).
|
|
4
|
+
# On open the content template is cloned into <body>. phlex-kit--sheet.
|
|
5
|
+
class Sheet < BaseComponent
|
|
6
|
+
def initialize(open: false, **attrs)
|
|
7
|
+
@open = open
|
|
8
|
+
@attrs = attrs
|
|
9
|
+
end
|
|
10
|
+
def view_template(&)
|
|
11
|
+
div(**mix({ data: { controller: "phlex-kit--sheet", phlex_kit__sheet_open_value: @open.to_s } }, @attrs), &)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
class SheetContent < BaseComponent
|
|
3
|
+
SIDES = { top: "top", right: "right", bottom: "bottom", left: "left" }.freeze
|
|
4
|
+
def initialize(side: :right, **attrs)
|
|
5
|
+
@side = side.to_sym
|
|
6
|
+
@attrs = attrs
|
|
7
|
+
end
|
|
8
|
+
def view_template(&block)
|
|
9
|
+
template(data: { phlex_kit__sheet_target: "content" }) do
|
|
10
|
+
div(data: { controller: "phlex-kit--sheet-content" }) do
|
|
11
|
+
div(class: "pk-sheet-backdrop", data: { action: "click->phlex-kit--sheet-content#close" })
|
|
12
|
+
div(**mix({ class: ["pk-sheet-content", SIDES.fetch(@side)].join(" ") }, @attrs)) do
|
|
13
|
+
block&.call
|
|
14
|
+
button(type: "button", class: "pk-overlay-close", data: { action: "click->phlex-kit--sheet-content#close" }) do
|
|
15
|
+
svg(width: "15", height: "15", viewbox: "0 0 15 15", fill: "none", xmlns: "http://www.w3.org/2000/svg") do |s|
|
|
16
|
+
s.path(fill_rule: "evenodd", clip_rule: "evenodd", fill: "currentColor", d: "M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z")
|
|
17
|
+
end
|
|
18
|
+
span(class: "pk-sr-only") { "Close" }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* Co-located with shortcut_key.rb. Theme tokens from the global stylesheet. */
|
|
2
|
+
.pk-shortcut-key {
|
|
3
|
+
pointer-events: none;
|
|
4
|
+
user-select: none;
|
|
5
|
+
display: inline-flex;
|
|
6
|
+
height: 1.25rem;
|
|
7
|
+
align-items: center;
|
|
8
|
+
gap: .25rem;
|
|
9
|
+
border: 1px solid var(--pk-border);
|
|
10
|
+
border-radius: calc(var(--pk-radius) - 4px);
|
|
11
|
+
background: var(--pk-surface-2);
|
|
12
|
+
padding-inline: .375rem;
|
|
13
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
14
|
+
font-size: 10px;
|
|
15
|
+
font-weight: 500;
|
|
16
|
+
color: var(--pk-muted);
|
|
17
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Keyboard-shortcut hint, rendered as <kbd>. Ported from ruby_ui's
|
|
3
|
+
# RubyUI::ShortcutKey. Purely visual — wires no key handler.
|
|
4
|
+
class ShortcutKey < BaseComponent
|
|
5
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
6
|
+
|
|
7
|
+
def view_template(&) = kbd(**mix({ class: "pk-shortcut-key" }, @attrs), &)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* Co-located with sidebar.rb — UI::Sidebar (+ Wrapper / Header / Content / Footer
|
|
2
|
+
/ Group / Menu / MenuItem / MenuButton / Inset). ruby_ui's structure at
|
|
3
|
+
collapsible:none, Tailwind → vanilla CSS on the palette tokens. The collapsible/
|
|
4
|
+
offcanvas/icon modes (+ their Stimulus/cookie/Sheet) are deliberately not ported.
|
|
5
|
+
Theme tokens come from the global stylesheet. */
|
|
6
|
+
.pk-sidebar-wrapper { display: flex; min-height: 100dvh; width: 100%; }
|
|
7
|
+
|
|
8
|
+
.pk-sidebar {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
width: 14rem;
|
|
12
|
+
flex-shrink: 0;
|
|
13
|
+
background: var(--pk-surface);
|
|
14
|
+
border-right: 1px solid var(--pk-border);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.pk-sidebar-header { display: flex; flex-direction: column; gap: .5rem; padding: 1rem .75rem .25rem; }
|
|
18
|
+
.pk-sidebar-content { display: flex; flex-direction: column; gap: .25rem; flex: 1; min-height: 0; overflow: auto; padding: .5rem .75rem; }
|
|
19
|
+
.pk-sidebar-footer { display: flex; flex-direction: column; gap: .5rem; padding: .75rem; }
|
|
20
|
+
.pk-sidebar-group { display: flex; flex-direction: column; gap: .125rem; }
|
|
21
|
+
|
|
22
|
+
.pk-sidebar-menu { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .125rem; width: 100%; }
|
|
23
|
+
.pk-sidebar-menu-item { position: relative; }
|
|
24
|
+
.pk-sidebar-menu-button {
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
gap: .5rem;
|
|
28
|
+
width: 100%;
|
|
29
|
+
padding: .5rem .65rem;
|
|
30
|
+
border: 0;
|
|
31
|
+
border-radius: 8px;
|
|
32
|
+
background: transparent;
|
|
33
|
+
color: var(--pk-text);
|
|
34
|
+
font: inherit;
|
|
35
|
+
font-size: .9rem;
|
|
36
|
+
text-align: left;
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
}
|
|
39
|
+
.pk-sidebar-menu-button:hover { background: var(--pk-accent); text-decoration: none; }
|
|
40
|
+
.pk-sidebar-menu-button[data-active="true"] { background: var(--pk-brand); color: var(--pk-brand-ink); font-weight: 600; }
|
|
41
|
+
|
|
42
|
+
.pk-sidebar-inset { flex: 1; min-width: 0; }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Sidebar shell, ported from ruby_ui's RubyUI::Sidebar at `collapsible: :none`
|
|
3
|
+
# (the NonCollapsibleSidebar path): a static flex-column rail. Deliberately
|
|
4
|
+
# WITHOUT ruby_ui's collapsible/offcanvas Stimulus controller + cookie state +
|
|
5
|
+
# mobile Sheet (the admin sidebar is static) — those can be added later if a
|
|
6
|
+
# collapsible chrome is wanted. Compose with SidebarWrapper (the page root) +
|
|
7
|
+
# SidebarHeader / SidebarContent / SidebarMenu (+ Item / Button) / SidebarFooter,
|
|
8
|
+
# alongside a SidebarInset for the main content. Tailwind → vanilla `.pk-sidebar*`
|
|
9
|
+
# (sidebar.css).
|
|
10
|
+
class Sidebar < BaseComponent
|
|
11
|
+
def initialize(**attrs)
|
|
12
|
+
@attrs = attrs
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def view_template(&block)
|
|
16
|
+
div(**mix({ class: "pk-sidebar" }, @attrs), &block)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Scrollable middle region of a PhlexKit::Sidebar (holds the nav menu). See sidebar.rb.
|
|
3
|
+
class SidebarContent < BaseComponent
|
|
4
|
+
def initialize(**attrs)
|
|
5
|
+
@attrs = attrs
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def view_template(&block)
|
|
9
|
+
div(**mix({ class: "pk-sidebar-content" }, @attrs), &block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Bottom region of a PhlexKit::Sidebar (user identity + sign out). See sidebar.rb.
|
|
3
|
+
class SidebarFooter < BaseComponent
|
|
4
|
+
def initialize(**attrs)
|
|
5
|
+
@attrs = attrs
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def view_template(&block)
|
|
9
|
+
div(**mix({ class: "pk-sidebar-footer" }, @attrs), &block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# A cluster of menu items within SidebarContent. See sidebar.rb.
|
|
3
|
+
class SidebarGroup < BaseComponent
|
|
4
|
+
def initialize(**attrs)
|
|
5
|
+
@attrs = attrs
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def view_template(&block)
|
|
9
|
+
div(**mix({ class: "pk-sidebar-group" }, @attrs), &block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Top region of a PhlexKit::Sidebar (brand + store switcher). See sidebar.rb.
|
|
3
|
+
class SidebarHeader < BaseComponent
|
|
4
|
+
def initialize(**attrs)
|
|
5
|
+
@attrs = attrs
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def view_template(&block)
|
|
9
|
+
div(**mix({ class: "pk-sidebar-header" }, @attrs), &block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# The main content region beside a PhlexKit::Sidebar (renders <main>, flex-1). Pass
|
|
3
|
+
# `class: "main"` to keep the app's existing content padding/typography.
|
|
4
|
+
# See sidebar.rb.
|
|
5
|
+
class SidebarInset < BaseComponent
|
|
6
|
+
def initialize(**attrs)
|
|
7
|
+
@attrs = attrs
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template(&block)
|
|
11
|
+
main(**mix({ class: "pk-sidebar-inset" }, @attrs), &block)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# The nav list (<ul>) inside SidebarContent. See sidebar.rb.
|
|
3
|
+
class SidebarMenu < BaseComponent
|
|
4
|
+
def initialize(**attrs)
|
|
5
|
+
@attrs = attrs
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def view_template(&block)
|
|
9
|
+
ul(**mix({ class: "pk-sidebar-menu" }, @attrs), &block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# The interactive element of a SidebarMenuItem. `as:` is :button (default) or :a
|
|
3
|
+
# (pass `href:`); `active: true` marks the current page (drives the highlight via
|
|
4
|
+
# data-active — a named kwarg, not an attr, since `mix` would merge a repeated
|
|
5
|
+
# attribute rather than override). Attrs pass through via mix. See sidebar.rb.
|
|
6
|
+
class SidebarMenuButton < BaseComponent
|
|
7
|
+
def initialize(as: :button, active: false, **attrs)
|
|
8
|
+
@as = as
|
|
9
|
+
@active = active
|
|
10
|
+
@attrs = attrs
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def view_template(&block)
|
|
14
|
+
send(@as, **mix({ class: "pk-sidebar-menu-button", "data-active": (@active ? "true" : "false") }, @attrs), &block)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# A single nav row (<li>) in a SidebarMenu. See sidebar.rb.
|
|
3
|
+
class SidebarMenuItem < BaseComponent
|
|
4
|
+
def initialize(**attrs)
|
|
5
|
+
@attrs = attrs
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def view_template(&block)
|
|
9
|
+
li(**mix({ class: "pk-sidebar-menu-item" }, @attrs), &block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# The page-level flex row that holds a PhlexKit::Sidebar + a PhlexKit::SidebarInset.
|
|
3
|
+
# See sidebar.rb.
|
|
4
|
+
class SidebarWrapper < BaseComponent
|
|
5
|
+
def initialize(**attrs)
|
|
6
|
+
@attrs = attrs
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def view_template(&block)
|
|
10
|
+
div(**mix({ class: "pk-sidebar-wrapper" }, @attrs), &block)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* Co-located with skeleton.rb. Theme tokens come from the global stylesheet. */
|
|
2
|
+
.pk-skeleton {
|
|
3
|
+
border-radius: calc(var(--pk-radius) - 2px);
|
|
4
|
+
background: color-mix(in oklab, var(--pk-brand, #6c8cff) 10%, transparent);
|
|
5
|
+
animation: pk-pulse 1.5s cubic-bezier(.4, 0, .6, 1) infinite;
|
|
6
|
+
}
|
|
7
|
+
@keyframes pk-pulse { 50% { opacity: .5; } }
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Placeholder shimmer for loading content. Ported from ruby_ui's RubyUI::Skeleton
|
|
3
|
+
# (Tailwind `animate-pulse rounded-md bg-primary/10` → vanilla .pk-skeleton).
|
|
4
|
+
class Skeleton < BaseComponent
|
|
5
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
6
|
+
|
|
7
|
+
def view_template(&) = div(**mix({ class: "pk-skeleton" }, @attrs), &)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* Co-located with slider.rb — UI::Slider, shadcn parity on a native range
|
|
2
|
+
input: muted track, primary filled portion (--pk-slider-progress, kept in
|
|
3
|
+
sync by the controller), round bordered thumb. */
|
|
4
|
+
.pk-slider {
|
|
5
|
+
appearance: none;
|
|
6
|
+
-webkit-appearance: none;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 1rem;
|
|
9
|
+
margin: 0;
|
|
10
|
+
background: transparent;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
}
|
|
13
|
+
.pk-slider:focus-visible { outline: none; }
|
|
14
|
+
.pk-slider::-webkit-slider-runnable-track {
|
|
15
|
+
height: .375rem;
|
|
16
|
+
border-radius: 9999px;
|
|
17
|
+
background: linear-gradient(to right,
|
|
18
|
+
var(--pk-brand) var(--pk-slider-progress, 50%),
|
|
19
|
+
var(--pk-surface-2) var(--pk-slider-progress, 50%));
|
|
20
|
+
}
|
|
21
|
+
.pk-slider::-webkit-slider-thumb {
|
|
22
|
+
-webkit-appearance: none;
|
|
23
|
+
width: 1rem;
|
|
24
|
+
height: 1rem;
|
|
25
|
+
margin-top: -0.3125rem;
|
|
26
|
+
border-radius: 9999px;
|
|
27
|
+
border: 1px solid var(--pk-brand);
|
|
28
|
+
background: var(--pk-bg);
|
|
29
|
+
box-shadow: 0 1px 2px rgb(0 0 0 / .25);
|
|
30
|
+
transition: box-shadow .15s ease;
|
|
31
|
+
}
|
|
32
|
+
.pk-slider:focus-visible::-webkit-slider-thumb {
|
|
33
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
34
|
+
}
|
|
35
|
+
.pk-slider::-moz-range-track {
|
|
36
|
+
height: .375rem;
|
|
37
|
+
border-radius: 9999px;
|
|
38
|
+
background: var(--pk-surface-2);
|
|
39
|
+
}
|
|
40
|
+
.pk-slider::-moz-range-progress {
|
|
41
|
+
height: .375rem;
|
|
42
|
+
border-radius: 9999px;
|
|
43
|
+
background: var(--pk-brand);
|
|
44
|
+
}
|
|
45
|
+
.pk-slider::-moz-range-thumb {
|
|
46
|
+
width: 1rem;
|
|
47
|
+
height: 1rem;
|
|
48
|
+
border-radius: 9999px;
|
|
49
|
+
border: 1px solid var(--pk-brand);
|
|
50
|
+
background: var(--pk-bg);
|
|
51
|
+
}
|
|
52
|
+
.pk-slider:disabled { opacity: .5; cursor: not-allowed; }
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Range slider, ported from shadcn/ui's Slider. Radix's slider is replaced
|
|
3
|
+
# with a styled native <input type="range"> (keyboard/touch/forms for free);
|
|
4
|
+
# the tiny phlex-kit--slider controller keeps the filled-track width in sync
|
|
5
|
+
# via a custom property. `.pk-slider` (slider.css).
|
|
6
|
+
class Slider < BaseComponent
|
|
7
|
+
def initialize(min: 0, max: 100, step: 1, value: nil, **attrs)
|
|
8
|
+
@min = min
|
|
9
|
+
@max = max
|
|
10
|
+
@step = step
|
|
11
|
+
@value = value || (@min + (@max - @min) / 2)
|
|
12
|
+
@attrs = attrs
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def view_template
|
|
16
|
+
input(**mix({
|
|
17
|
+
type: :range,
|
|
18
|
+
min: @min,
|
|
19
|
+
max: @max,
|
|
20
|
+
step: @step,
|
|
21
|
+
value: @value,
|
|
22
|
+
class: "pk-slider",
|
|
23
|
+
style: "--pk-slider-progress: #{progress}%",
|
|
24
|
+
data: {
|
|
25
|
+
controller: "phlex-kit--slider",
|
|
26
|
+
action: "input->phlex-kit--slider#update"
|
|
27
|
+
}
|
|
28
|
+
}, @attrs))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def progress
|
|
34
|
+
span = (@max - @min).to_f
|
|
35
|
+
return 0 if span.zero?
|
|
36
|
+
(((@value.to_f - @min) / span) * 100).round(2)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/* Co-located with spinner.rb — UI::Spinner (shadcn's spinning loader). */
|
|
2
|
+
.pk-spinner { width: 1rem; height: 1rem; animation: pk-spin 1s linear infinite; }
|
|
3
|
+
.pk-spinner.sm { width: .75rem; height: .75rem; }
|
|
4
|
+
.pk-spinner.lg { width: 1.5rem; height: 1.5rem; }
|
|
5
|
+
@keyframes pk-spin { to { transform: rotate(360deg); } }
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Loading spinner, ported from shadcn/ui's Spinner (a spinning loader icon;
|
|
3
|
+
# not in ruby_ui). Sizes via SIZES.fetch. `.pk-spinner` (spinner.css).
|
|
4
|
+
class Spinner < BaseComponent
|
|
5
|
+
SIZES = { sm: "sm", md: nil, lg: "lg" }.freeze
|
|
6
|
+
|
|
7
|
+
def initialize(size: :md, **attrs)
|
|
8
|
+
@size = size.to_sym
|
|
9
|
+
@attrs = attrs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def view_template
|
|
13
|
+
svg(**mix({
|
|
14
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
15
|
+
viewbox: "0 0 24 24",
|
|
16
|
+
fill: "none",
|
|
17
|
+
stroke: "currentColor",
|
|
18
|
+
"stroke-width": "2",
|
|
19
|
+
"stroke-linecap": "round",
|
|
20
|
+
"stroke-linejoin": "round",
|
|
21
|
+
class: [ "pk-spinner", SIZES.fetch(@size) ].compact.join(" "),
|
|
22
|
+
role: "status",
|
|
23
|
+
aria: { label: "Loading" }
|
|
24
|
+
}, @attrs)) { |s| s.path(d: "M21 12a9 9 0 1 1-6.219-8.56") }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/* Co-located with stars.rb — UI::Stars. The gold rating glyphs; self-colours so
|
|
2
|
+
product cards / summaries get amber stars too (the old `.review .stars` rule
|
|
3
|
+
only coloured stars inside a review). Theme tokens come from the global stylesheet. */
|
|
4
|
+
.pk-stars { color: var(--pk-amber); letter-spacing: 1px; }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Star rating (CUSTOM — ruby_ui has no rating component). Replaces the `stars`
|
|
3
|
+
# view helper: renders `rating` filled stars + the remainder empty, out of
|
|
4
|
+
# `max`. Presentational; attrs pass through via mix. Self-colours (amber) so it
|
|
5
|
+
# works anywhere, not just inside a review.
|
|
6
|
+
class Stars < BaseComponent
|
|
7
|
+
def initialize(rating:, max: 5, **attrs)
|
|
8
|
+
@rating = rating.to_i.clamp(0, max)
|
|
9
|
+
@max = max
|
|
10
|
+
@attrs = attrs
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def view_template
|
|
14
|
+
span(**mix({ class: "pk-stars", title: "#{@rating}/#{@max}" }, @attrs)) do
|
|
15
|
+
plain(("★" * @rating) + ("☆" * (@max - @rating)))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* Co-located with switch.rb. Theme tokens from the global stylesheet. */
|
|
2
|
+
.pk-switch {
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
height: 1.5rem;
|
|
5
|
+
width: 2.75rem;
|
|
6
|
+
flex: none;
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
align-items: center;
|
|
9
|
+
border: 2px solid transparent;
|
|
10
|
+
border-radius: 9999px;
|
|
11
|
+
background: var(--pk-border);
|
|
12
|
+
transition: background-color .15s ease;
|
|
13
|
+
}
|
|
14
|
+
.pk-switch:has(.pk-switch-input:checked) { background: var(--pk-brand); }
|
|
15
|
+
.pk-switch:has(.pk-switch-input:disabled) { cursor: not-allowed; opacity: .5; }
|
|
16
|
+
.pk-switch-input { display: none; }
|
|
17
|
+
.pk-switch-thumb {
|
|
18
|
+
pointer-events: none;
|
|
19
|
+
display: block;
|
|
20
|
+
height: 1.25rem;
|
|
21
|
+
width: 1.25rem;
|
|
22
|
+
border-radius: 9999px;
|
|
23
|
+
background: var(--pk-surface);
|
|
24
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / .3);
|
|
25
|
+
transition: transform .15s ease;
|
|
26
|
+
transform: translateX(0);
|
|
27
|
+
}
|
|
28
|
+
.pk-switch:has(.pk-switch-input:checked) .pk-switch-thumb { transform: translateX(1.25rem); }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# On/off toggle rendered as a checkbox styled as a track+thumb. Ported from
|
|
3
|
+
# ruby_ui's RubyUI::Switch — pure CSS (`:has(:checked)`), no Stimulus. Emits an
|
|
4
|
+
# optional hidden field so an unchecked box still posts a value (Rails idiom).
|
|
5
|
+
class Switch < BaseComponent
|
|
6
|
+
def initialize(include_hidden: true, checked_value: "1", unchecked_value: "0", **attrs)
|
|
7
|
+
@include_hidden = include_hidden
|
|
8
|
+
@checked_value = checked_value
|
|
9
|
+
@unchecked_value = unchecked_value
|
|
10
|
+
@attrs = attrs
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def view_template
|
|
14
|
+
label(**mix({ role: "switch", class: "pk-switch" }, {})) do
|
|
15
|
+
input(type: "hidden", name: @attrs[:name], value: @unchecked_value) if @include_hidden
|
|
16
|
+
input(**mix({ class: "pk-switch-input" }, @attrs).merge(type: "checkbox", value: @checked_value))
|
|
17
|
+
span(class: "pk-switch-thumb")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* Co-located with table.rb — UI::Table (+ Header/Body/Footer/Row/Head/Cell/
|
|
2
|
+
Caption). ruby_ui's structure kept; Tailwind replaced with vanilla CSS on the
|
|
3
|
+
palette tokens. Geometry from ruby_ui (text-sm, h-10 px-2 heads, p-2 cells,
|
|
4
|
+
row bottom-border + hover). Theme tokens come from the global stylesheet. */
|
|
5
|
+
.pk-table-wrapper { position: relative; width: 100%; overflow: auto; }
|
|
6
|
+
.pk-table { width: 100%; border-collapse: collapse; caption-side: bottom; font-size: .875rem; }
|
|
7
|
+
|
|
8
|
+
.pk-table-header .pk-table-row { border-bottom: 1px solid var(--pk-border); }
|
|
9
|
+
.pk-table-body .pk-table-row:last-child { border-bottom: 0; }
|
|
10
|
+
.pk-table-footer { border-top: 1px solid var(--pk-border); font-weight: 500; }
|
|
11
|
+
|
|
12
|
+
.pk-table-row { border-bottom: 1px solid var(--pk-border); transition: background-color .12s ease; }
|
|
13
|
+
.pk-table-row:hover { background: color-mix(in oklab, var(--pk-surface-2) 60%, transparent); }
|
|
14
|
+
|
|
15
|
+
.pk-table-head {
|
|
16
|
+
height: 2.5rem;
|
|
17
|
+
padding: 0 .5rem;
|
|
18
|
+
text-align: left;
|
|
19
|
+
vertical-align: middle;
|
|
20
|
+
font-weight: 500;
|
|
21
|
+
color: var(--pk-muted);
|
|
22
|
+
}
|
|
23
|
+
.pk-table-cell { padding: .5rem; vertical-align: middle; }
|
|
24
|
+
.pk-table-caption { margin-top: 1rem; font-size: .875rem; color: var(--pk-muted); }
|