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,14 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# The icon/avatar slot inside an Empty state. variant: :icon gives the tinted
|
|
3
|
+
# rounded chip; :default is bare. Ported from ruby_ui's RubyUI::EmptyMedia.
|
|
4
|
+
class EmptyMedia < BaseComponent
|
|
5
|
+
VARIANTS = { default: nil, icon: "icon" }.freeze
|
|
6
|
+
def initialize(variant: :default, **attrs)
|
|
7
|
+
@variant = variant.to_sym
|
|
8
|
+
@attrs = attrs
|
|
9
|
+
end
|
|
10
|
+
def view_template(&)
|
|
11
|
+
div(**mix({ class: ["pk-empty-media", VARIANTS.fetch(@variant)].compact.join(" ") }, @attrs), &)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* Co-located with form.rb — UI::Form. Form-level layout (ruby_ui applies
|
|
2
|
+
`space-y-*` on the <form>): `.pk-form` stacks fields with rhythm;
|
|
3
|
+
`.pk-form-actions` lays the submit/cancel row out horizontally. Field-level
|
|
4
|
+
styles live with form_field.rb. Theme tokens come from the global
|
|
5
|
+
stylesheet. */
|
|
6
|
+
.pk-form {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: 1.25rem;
|
|
10
|
+
}
|
|
11
|
+
.pk-form-actions {
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
gap: .5rem;
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Form shell, ported from ruby_ui's RubyUI::Form. A plain <form> that stacks
|
|
3
|
+
# PhlexKit::FormFields with rhythm (`.pk-form`, form.css — plus
|
|
4
|
+
# `.pk-form-actions` for the submit/cancel row). Live validation lives on each
|
|
5
|
+
# FormField (see form_field.rb), so this stays markup-only:
|
|
6
|
+
#
|
|
7
|
+
# render PhlexKit::Form.new(action: "/reviews", method: "post") do
|
|
8
|
+
# render PhlexKit::FormField.new do
|
|
9
|
+
# render PhlexKit::FormFieldLabel.new(for: "email") { "Email" }
|
|
10
|
+
# render PhlexKit::Input.new(type: :email, id: "email", name: "email", required: true)
|
|
11
|
+
# render PhlexKit::FormFieldError.new
|
|
12
|
+
# end
|
|
13
|
+
# div(class: "pk-form-actions") { render PhlexKit::Button.new(type: :submit) { "Save" } }
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# With Rails form helpers, put the class on the builder instead:
|
|
17
|
+
# `form_with(..., class: "pk-form")`.
|
|
18
|
+
class Form < BaseComponent
|
|
19
|
+
def initialize(**attrs)
|
|
20
|
+
@attrs = attrs
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def view_template(&)
|
|
24
|
+
form(**mix({ class: "pk-form" }, @attrs), &)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Co-located with form_field.rb — UI::FormField (+ Label / Hint / Error).
|
|
2
|
+
ruby_ui's structure kept (a vertical stack: label, control, hint, error); only
|
|
3
|
+
the styling is ours, vanilla CSS on the palette tokens. Geometry from ruby_ui
|
|
4
|
+
(flex-col gap-2, text-sm, empty:hidden, text-muted-foreground / text-destructive).
|
|
5
|
+
Theme tokens come from the global stylesheet. */
|
|
6
|
+
.pk-form-field {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: .5rem;
|
|
10
|
+
}
|
|
11
|
+
.pk-form-field-label {
|
|
12
|
+
font-size: .875rem;
|
|
13
|
+
font-weight: 500;
|
|
14
|
+
line-height: 1.1;
|
|
15
|
+
}
|
|
16
|
+
.pk-form-field-label:empty { display: none; }
|
|
17
|
+
.pk-form-field-hint {
|
|
18
|
+
margin: 0;
|
|
19
|
+
font-size: .875rem;
|
|
20
|
+
color: var(--pk-muted);
|
|
21
|
+
}
|
|
22
|
+
.pk-form-field-hint:empty { display: none; }
|
|
23
|
+
.pk-form-field-error {
|
|
24
|
+
margin: 0;
|
|
25
|
+
font-size: .875rem;
|
|
26
|
+
font-weight: 500;
|
|
27
|
+
color: var(--pk-red);
|
|
28
|
+
}
|
|
29
|
+
.pk-form-field-error:empty { display: none; }
|
|
30
|
+
|
|
31
|
+
/* Form-level layout (.pk-form / .pk-form-actions) lives with form.rb. */
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Form field group, ported from ruby_ui's RubyUI::FormField: a vertical stack
|
|
3
|
+
# grouping a FormFieldLabel + a control (PhlexKit::Input / Textarea / NativeSelect /
|
|
4
|
+
# Checkbox / RadioButton …) + an optional FormFieldHint / FormFieldError.
|
|
5
|
+
# Carries the phlex-kit--form-field controller for live validation: the kit's
|
|
6
|
+
# controls register as its input target, and once the browser first flags the
|
|
7
|
+
# control invalid (a submit attempt) — or the error renders with server
|
|
8
|
+
# content — the FormFieldError live-updates as the user types, with
|
|
9
|
+
# per-constraint messages via data-* on the control (data-value-missing,
|
|
10
|
+
# data-type-mismatch, data-too-short, …). Compose inside PhlexKit::Form (form.rb).
|
|
11
|
+
#
|
|
12
|
+
# This replaces the legacy `.field` wrapper in converted views — and crucially
|
|
13
|
+
# does NOT carry `.field`'s descendant `input/select/textarea` styling (whose
|
|
14
|
+
# specificity would otherwise override `.pk-input` &c.), so the kit's controls
|
|
15
|
+
# render with their own look. Multi-part, like PhlexKit::Card:
|
|
16
|
+
#
|
|
17
|
+
# render PhlexKit::FormField.new do
|
|
18
|
+
# render PhlexKit::FormFieldLabel.new(for: "user_email") { "Email" }
|
|
19
|
+
# render PhlexKit::Input.new(type: :email, id: "user_email", name: "user[email]")
|
|
20
|
+
# render PhlexKit::FormFieldError.new { "is invalid" }
|
|
21
|
+
# end
|
|
22
|
+
class FormField < BaseComponent
|
|
23
|
+
def initialize(**attrs)
|
|
24
|
+
@attrs = attrs
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def view_template(&block)
|
|
28
|
+
div(**mix({ class: "pk-form-field", data: { controller: "phlex-kit--form-field" } }, @attrs), &block)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Validation error text for a PhlexKit::FormField, styled with the destructive token
|
|
3
|
+
# and hidden when empty. Render it empty for live client-side messages (the
|
|
4
|
+
# phlex-kit--form-field controller fills it once the control goes invalid), or
|
|
5
|
+
# with server-rendered model errors — non-empty content arms validation on
|
|
6
|
+
# connect. See form_field.rb.
|
|
7
|
+
class FormFieldError < BaseComponent
|
|
8
|
+
def initialize(**attrs)
|
|
9
|
+
@attrs = attrs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def view_template(&block)
|
|
13
|
+
p(**mix({
|
|
14
|
+
class: "pk-form-field-error",
|
|
15
|
+
data: { phlex_kit__form_field_target: "error" }
|
|
16
|
+
}, @attrs), &block)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Muted helper text under a PhlexKit::FormField control. Hidden when empty.
|
|
3
|
+
# See form_field.rb.
|
|
4
|
+
class FormFieldHint < BaseComponent
|
|
5
|
+
def initialize(**attrs)
|
|
6
|
+
@attrs = attrs
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def view_template(&block)
|
|
10
|
+
p(**mix({ class: "pk-form-field-hint" }, @attrs), &block)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Label for a PhlexKit::FormField control. Pass `for:` to bind it to the control's id
|
|
3
|
+
# (e.g. `for: f.field_id(:email)`). Hidden when empty. See form_field.rb.
|
|
4
|
+
class FormFieldLabel < BaseComponent
|
|
5
|
+
def initialize(**attrs)
|
|
6
|
+
@attrs = attrs
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def view_template(&block)
|
|
10
|
+
label(**mix({ class: "pk-form-field-label" }, @attrs), &block)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/* Co-located with hover_card.rb. Tokens from the global stylesheet. */
|
|
2
|
+
.pk-hover-card { position: relative; display: inline-block; }
|
|
3
|
+
.pk-hover-card-trigger { display: inline-block; }
|
|
4
|
+
.pk-hover-card-content {
|
|
5
|
+
position: absolute; z-index: 50; top: calc(100% + .5rem); left: 0; width: 16rem;
|
|
6
|
+
border: 1px solid var(--pk-border); border-radius: calc(var(--pk-radius) - 2px); background: var(--pk-surface);
|
|
7
|
+
color: var(--pk-text); padding: 1rem; box-shadow: 0 8px 24px rgb(0 0 0 / .3); outline: none;
|
|
8
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Hover/focus-triggered floating card, positioned with CSS. Ported from ruby_ui's
|
|
3
|
+
# RubyUI::HoverCard. Compose HoverCard > (HoverCardTrigger + HoverCardContent).
|
|
4
|
+
class HoverCard < BaseComponent
|
|
5
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
6
|
+
def view_template(&)
|
|
7
|
+
div(**mix({ class: "pk-hover-card", data: { controller: "phlex-kit--hover-card", action: "mouseenter->phlex-kit--hover-card#show mouseleave->phlex-kit--hover-card#hide focusin->phlex-kit--hover-card#show focusout->phlex-kit--hover-card#hide" } }, @attrs), &)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
class HoverCardContent < BaseComponent
|
|
3
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
4
|
+
def view_template(&)
|
|
5
|
+
div(**mix({ class: "pk-hover-card-content pk-hidden", data: { phlex_kit__hover_card_target: "content", state: "closed" } }, @attrs), &)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/* Co-located with input.rb — UI::Input. ruby_ui's Tailwind input replaced with
|
|
2
|
+
our own vanilla CSS: the geometry is ruby_ui's (h-9 / rounded-md / px-3 py-1 /
|
|
3
|
+
text-sm / shadow-xs / ring-on-focus), realised against this app's palette
|
|
4
|
+
tokens. Not styled to match the legacy `.field input`; this is the kit's own
|
|
5
|
+
look and will be revisited in the visual redesign. Theme tokens come from the
|
|
6
|
+
global stylesheet. */
|
|
7
|
+
.pk-input {
|
|
8
|
+
height: 2rem;
|
|
9
|
+
width: 100%;
|
|
10
|
+
border-radius: var(--pk-radius);
|
|
11
|
+
border: 1px solid var(--pk-input);
|
|
12
|
+
background: color-mix(in oklab, var(--pk-input) 30%, transparent);
|
|
13
|
+
color: var(--pk-text);
|
|
14
|
+
padding: .25rem .625rem;
|
|
15
|
+
font: inherit;
|
|
16
|
+
font-size: .875rem;
|
|
17
|
+
transition: color .15s ease, border-color .15s ease, box-shadow .15s ease;
|
|
18
|
+
}
|
|
19
|
+
.pk-input::placeholder { color: var(--pk-muted); }
|
|
20
|
+
.pk-input:focus-visible {
|
|
21
|
+
outline: none;
|
|
22
|
+
border-color: var(--pk-brand);
|
|
23
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
24
|
+
}
|
|
25
|
+
.pk-input:disabled { cursor: not-allowed; opacity: .5; }
|
|
26
|
+
.pk-input[aria-invalid="true"] {
|
|
27
|
+
border-color: var(--pk-red);
|
|
28
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-red) 30%, transparent);
|
|
29
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Form text input, ported from ruby_ui's RubyUI::Input (https://ruby-ui.com).
|
|
3
|
+
# ruby_ui's Tailwind strings are replaced with plain `.pk-input` CSS
|
|
4
|
+
# (input.css) on the app's design tokens. Like upstream, it registers as a
|
|
5
|
+
# phlex-kit--form-field input target — live validation kicks in when wrapped
|
|
6
|
+
# in a PhlexKit::FormField, and Stimulus ignores the wiring otherwise.
|
|
7
|
+
#
|
|
8
|
+
# `type:` picks the HTML input type (:text, :email, :password, :number, …);
|
|
9
|
+
# everything else — `name:`, `value:`, `id:`, `placeholder:`, `required:`,
|
|
10
|
+
# `**on(...)` — rides the `mix` pass-through onto the <input>, so a caller's
|
|
11
|
+
# `class:` augments rather than clobbers ours. This is a presentational
|
|
12
|
+
# primitive, NOT a Rails form-builder helper: in a Phlex view you supply the
|
|
13
|
+
# name/value yourself, exactly as Admin::ReviewRow composes PhlexKit::Button.
|
|
14
|
+
#
|
|
15
|
+
# No VARIANTS: an input is an input. Sizing/state live in CSS (:focus,
|
|
16
|
+
# :disabled, [aria-invalid]).
|
|
17
|
+
class Input < BaseComponent
|
|
18
|
+
def initialize(type: :text, **attrs)
|
|
19
|
+
@type = type
|
|
20
|
+
@attrs = attrs
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def view_template
|
|
24
|
+
input(**mix({
|
|
25
|
+
type: @type,
|
|
26
|
+
class: "pk-input",
|
|
27
|
+
data: {
|
|
28
|
+
phlex_kit__form_field_target: "input",
|
|
29
|
+
action: "input->phlex-kit--form-field#onInput invalid->phlex-kit--form-field#onInvalid"
|
|
30
|
+
}
|
|
31
|
+
}, @attrs))
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* Co-located with input_group.rb — UI::InputGroup, shadcn parity: the shell
|
|
2
|
+
carries the border/fill and focus ring; the inner .pk-input goes naked. */
|
|
3
|
+
.pk-input-group {
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
width: 100%;
|
|
7
|
+
border: 1px solid var(--pk-input);
|
|
8
|
+
border-radius: var(--pk-radius);
|
|
9
|
+
background: color-mix(in oklab, var(--pk-input) 30%, transparent);
|
|
10
|
+
transition: border-color .15s ease, box-shadow .15s ease;
|
|
11
|
+
}
|
|
12
|
+
.pk-input-group:focus-within {
|
|
13
|
+
border-color: var(--pk-brand);
|
|
14
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
15
|
+
}
|
|
16
|
+
.pk-input-group .pk-input {
|
|
17
|
+
border: 0;
|
|
18
|
+
background: transparent;
|
|
19
|
+
box-shadow: none;
|
|
20
|
+
flex: 1;
|
|
21
|
+
}
|
|
22
|
+
.pk-input-group .pk-input:focus-visible { outline: none; box-shadow: none; border: 0; }
|
|
23
|
+
.pk-input-group-addon {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
gap: .25rem;
|
|
27
|
+
flex: none;
|
|
28
|
+
padding: 0 .625rem;
|
|
29
|
+
color: var(--pk-muted);
|
|
30
|
+
font-size: .875rem;
|
|
31
|
+
}
|
|
32
|
+
.pk-input-group-addon.start { padding-right: 0; }
|
|
33
|
+
.pk-input-group-addon.end { padding-left: 0; }
|
|
34
|
+
.pk-input-group-addon svg { width: 1rem; height: 1rem; }
|
|
35
|
+
.pk-input-group-text { color: var(--pk-muted); }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Input with attached addons, ported from shadcn/ui's InputGroup: a bordered
|
|
3
|
+
# shell that focuses as one control; compose InputGroupAddon(align:) around a
|
|
4
|
+
# plain PhlexKit::Input (its own border/bg collapse inside the group).
|
|
5
|
+
# `.pk-input-group*` (input_group.css).
|
|
6
|
+
class InputGroup < BaseComponent
|
|
7
|
+
def initialize(**attrs)
|
|
8
|
+
@attrs = attrs
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def view_template(&)
|
|
12
|
+
div(**mix({ class: "pk-input-group", role: "group" }, @attrs), &)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Leading/trailing addon inside an InputGroup — icons, text or small buttons.
|
|
3
|
+
# See input_group.rb.
|
|
4
|
+
class InputGroupAddon < BaseComponent
|
|
5
|
+
ALIGNS = { start: "start", end: "end" }.freeze
|
|
6
|
+
|
|
7
|
+
def initialize(align: :start, **attrs)
|
|
8
|
+
@align = align.to_sym
|
|
9
|
+
@attrs = attrs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def view_template(&)
|
|
13
|
+
div(**mix({ class: "pk-input-group-addon #{ALIGNS.fetch(@align)}" }, @attrs), &)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Muted text inside an InputGroupAddon (e.g. a unit or prefix). See input_group.rb.
|
|
3
|
+
class InputGroupText < BaseComponent
|
|
4
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
5
|
+
def view_template(&) = span(**mix({ class: "pk-input-group-text" }, @attrs), &)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* Co-located with input_otp.rb — UI::InputOTP, shadcn parity: joined cells
|
|
2
|
+
(shared borders, outer corners rounded), ring on the active cell. */
|
|
3
|
+
.pk-input-otp { display: flex; align-items: center; gap: .5rem; }
|
|
4
|
+
.pk-input-otp-group { display: flex; align-items: center; }
|
|
5
|
+
.pk-input-otp-slot {
|
|
6
|
+
width: 2.25rem;
|
|
7
|
+
height: 2.25rem;
|
|
8
|
+
border: 1px solid var(--pk-input);
|
|
9
|
+
background: color-mix(in oklab, var(--pk-input) 30%, transparent);
|
|
10
|
+
color: var(--pk-text);
|
|
11
|
+
font: inherit;
|
|
12
|
+
font-size: .875rem;
|
|
13
|
+
text-align: center;
|
|
14
|
+
outline: none;
|
|
15
|
+
transition: border-color .15s ease, box-shadow .15s ease;
|
|
16
|
+
}
|
|
17
|
+
.pk-input-otp-slot:not(:first-child) { margin-left: -1px; }
|
|
18
|
+
.pk-input-otp-group .pk-input-otp-slot:first-child {
|
|
19
|
+
border-top-left-radius: var(--pk-radius);
|
|
20
|
+
border-bottom-left-radius: var(--pk-radius);
|
|
21
|
+
}
|
|
22
|
+
.pk-input-otp-group .pk-input-otp-slot:last-child {
|
|
23
|
+
border-top-right-radius: var(--pk-radius);
|
|
24
|
+
border-bottom-right-radius: var(--pk-radius);
|
|
25
|
+
}
|
|
26
|
+
.pk-input-otp-slot:focus {
|
|
27
|
+
position: relative;
|
|
28
|
+
z-index: 1;
|
|
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-input-otp-separator { color: var(--pk-muted); }
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# One-time-code input, ported from shadcn/ui's InputOTP (the input-otp npm
|
|
3
|
+
# lib is replaced by the phlex-kit--input-otp controller: per-slot typing with
|
|
4
|
+
# auto-advance, backspace retreat, paste distribution, arrow movement). The
|
|
5
|
+
# hidden input carries the joined value under `name:`. Compose InputOtp >
|
|
6
|
+
# InputOtpGroup(InputOtpSlot…) [+ InputOtpSeparator + more groups]; slot
|
|
7
|
+
# count must total `length:`. `.pk-input-otp*` (input_otp.css).
|
|
8
|
+
class InputOtp < BaseComponent
|
|
9
|
+
def initialize(length: 6, name: nil, value: nil, **attrs)
|
|
10
|
+
@length = length
|
|
11
|
+
@name = name
|
|
12
|
+
@value = value
|
|
13
|
+
@attrs = attrs
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def view_template(&block)
|
|
17
|
+
div(**mix({
|
|
18
|
+
class: "pk-input-otp",
|
|
19
|
+
data: {
|
|
20
|
+
controller: "phlex-kit--input-otp",
|
|
21
|
+
phlex_kit__input_otp_length_value: @length
|
|
22
|
+
}
|
|
23
|
+
}, @attrs)) do
|
|
24
|
+
input(type: :hidden, name: @name, value: @value, data: { phlex_kit__input_otp_target: "value" }) if @name
|
|
25
|
+
yield if block
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Divider between OTP groups. See input_otp.rb.
|
|
3
|
+
class InputOtpSeparator < BaseComponent
|
|
4
|
+
def initialize(**attrs) = (@attrs = attrs)
|
|
5
|
+
def view_template = div(**mix({ class: "pk-input-otp-separator", role: "separator" }, @attrs)) { "-" }
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# One character cell of an InputOtp. See input_otp.rb.
|
|
3
|
+
class InputOtpSlot < BaseComponent
|
|
4
|
+
def initialize(**attrs)
|
|
5
|
+
@attrs = attrs
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def view_template
|
|
9
|
+
input(**mix({
|
|
10
|
+
type: :text,
|
|
11
|
+
inputmode: "numeric",
|
|
12
|
+
autocomplete: "one-time-code",
|
|
13
|
+
maxlength: "1",
|
|
14
|
+
class: "pk-input-otp-slot",
|
|
15
|
+
data: {
|
|
16
|
+
phlex_kit__input_otp_target: "slot",
|
|
17
|
+
action: [
|
|
18
|
+
"input->phlex-kit--input-otp#onInput",
|
|
19
|
+
"keydown->phlex-kit--input-otp#onKeydown",
|
|
20
|
+
"paste->phlex-kit--input-otp#onPaste",
|
|
21
|
+
"focus->phlex-kit--input-otp#onFocus"
|
|
22
|
+
].join(" ")
|
|
23
|
+
}
|
|
24
|
+
}, @attrs))
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* Co-located with item.rb — UI::Item family, shadcn parity. */
|
|
2
|
+
.pk-item {
|
|
3
|
+
display: flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
gap: .625rem;
|
|
6
|
+
width: 100%;
|
|
7
|
+
border: 1px solid transparent;
|
|
8
|
+
border-radius: var(--pk-radius);
|
|
9
|
+
padding: .625rem .875rem;
|
|
10
|
+
font-size: .875rem;
|
|
11
|
+
}
|
|
12
|
+
.pk-item.outline { border-color: var(--pk-border); }
|
|
13
|
+
.pk-item.muted { background: var(--pk-surface-2); }
|
|
14
|
+
.pk-item-media {
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
flex: none;
|
|
19
|
+
color: var(--pk-muted);
|
|
20
|
+
}
|
|
21
|
+
.pk-item-media svg { width: 1rem; height: 1rem; }
|
|
22
|
+
.pk-item-content { display: flex; flex: 1; flex-direction: column; gap: .125rem; min-width: 0; }
|
|
23
|
+
.pk-item-title { font-weight: 500; line-height: 1.25; }
|
|
24
|
+
.pk-item-description {
|
|
25
|
+
color: var(--pk-muted);
|
|
26
|
+
font-size: .875rem;
|
|
27
|
+
line-height: 1.375;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
text-overflow: ellipsis;
|
|
30
|
+
}
|
|
31
|
+
.pk-item-actions { display: flex; align-items: center; gap: .5rem; flex: none; }
|
|
32
|
+
.pk-item-group { display: flex; flex-direction: column; width: 100%; gap: .5rem; }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# List row, ported from shadcn/ui's Item: a flex row of ItemMedia +
|
|
3
|
+
# ItemContent(ItemTitle + ItemDescription) + ItemActions, optionally grouped
|
|
4
|
+
# in an ItemGroup. variant :outline draws a bordered card row.
|
|
5
|
+
# `.pk-item*` (item.css).
|
|
6
|
+
class Item < BaseComponent
|
|
7
|
+
VARIANTS = { default: nil, outline: "outline", muted: "muted" }.freeze
|
|
8
|
+
|
|
9
|
+
def initialize(variant: :default, **attrs)
|
|
10
|
+
@variant = variant.to_sym
|
|
11
|
+
@attrs = attrs
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def view_template(&)
|
|
15
|
+
div(**mix({ class: [ "pk-item", VARIANTS.fetch(@variant) ].compact.join(" ") }, @attrs), &)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* Co-located with kbd.rb — UI::Kbd (+ KbdGroup), shadcn parity. */
|
|
2
|
+
.pk-kbd {
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
gap: .25rem;
|
|
7
|
+
min-width: 1.25rem;
|
|
8
|
+
height: 1.25rem;
|
|
9
|
+
padding: 0 .25rem;
|
|
10
|
+
border-radius: calc(var(--pk-radius) - 4px);
|
|
11
|
+
background: var(--pk-surface-2);
|
|
12
|
+
color: var(--pk-muted);
|
|
13
|
+
font-family: inherit;
|
|
14
|
+
font-size: .75rem;
|
|
15
|
+
font-weight: 500;
|
|
16
|
+
}
|
|
17
|
+
.pk-kbd-group { display: inline-flex; align-items: center; gap: .25rem; font-family: inherit; }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Keyboard-key chip, ported from shadcn/ui's Kbd. The kit's ShortcutKey
|
|
3
|
+
# predates it (ruby_ui naming) — Kbd is the shadcn-parity spelling; group
|
|
4
|
+
# several in a KbdGroup. `.pk-kbd` (kbd.css).
|
|
5
|
+
class Kbd < BaseComponent
|
|
6
|
+
def initialize(**attrs)
|
|
7
|
+
@attrs = attrs
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template(&)
|
|
11
|
+
kbd(**mix({ class: "pk-kbd" }, @attrs), &)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|