shadcn_phlexcomponents 0.1.5 → 0.1.9
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 +4 -4
- data/README.md +14 -0
- data/app/javascript/controllers/accordion_controller.js +7 -16
- data/app/javascript/controllers/alert_dialog_controller.js +5 -141
- data/app/javascript/controllers/combobox_controller.js +20 -0
- data/app/javascript/controllers/date_picker_controller.js +199 -64
- data/app/javascript/controllers/date_range_picker_controller.js +289 -176
- data/app/javascript/controllers/dialog_controller.js +19 -64
- data/app/javascript/controllers/dropdown_menu_controller.js +15 -37
- data/app/javascript/controllers/form_field_controller.js +24 -0
- data/app/javascript/controllers/hover_card_controller.js +1 -22
- data/app/javascript/controllers/popover_controller.js +20 -31
- data/app/javascript/controllers/select_controller.js +32 -52
- data/app/javascript/controllers/sidebar_trigger_controller.js +1 -1
- data/app/javascript/controllers/toast_controller.js +2 -2
- data/app/javascript/controllers/tooltip_controller.js +1 -2
- data/app/javascript/shadcn_phlexcomponents.js +53 -0
- data/app/javascript/utils.js +184 -0
- data/app/stylesheets/date_picker.css +212 -0
- data/lib/install/install_shadcn_phlexcomponents.rb +7 -7
- data/lib/{components → shadcn_phlexcomponents/components/accordion}/accordion.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/accordion}/accordion_content.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/accordion}/accordion_item.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/accordion}/accordion_trigger.rb +5 -4
- data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_action.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_action_to.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_cancel.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_content.rb +2 -2
- data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_trigger.rb +2 -2
- data/lib/{components → shadcn_phlexcomponents/components/avatar}/avatar.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/avatar}/avatar_fallback.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/avatar}/avatar_image.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/badge}/badge.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components}/base.rb +10 -0
- data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb.rb +2 -0
- data/lib/{components → shadcn_phlexcomponents/components/button}/button.rb +5 -5
- data/lib/{components → shadcn_phlexcomponents/components/checkbox}/checkbox.rb +5 -5
- data/lib/{components → shadcn_phlexcomponents/components/checkbox_group}/checkbox_group.rb +27 -15
- data/lib/{components → shadcn_phlexcomponents/components/collapsible}/collapsible.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/collapsible}/collapsible_content.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/collapsible}/collapsible_trigger.rb +2 -2
- data/lib/shadcn_phlexcomponents/components/date_picker/date_picker.rb +87 -0
- data/lib/shadcn_phlexcomponents/components/date_picker/date_picker_content.rb +45 -0
- data/lib/shadcn_phlexcomponents/components/date_picker/date_picker_trigger.rb +64 -0
- data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker.rb +105 -0
- data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker_content.rb +9 -0
- data/lib/shadcn_phlexcomponents/components/date_range_picker/date_range_picker_trigger.rb +9 -0
- data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog.rb +8 -8
- data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_close.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_content.rb +3 -3
- data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_trigger.rb +2 -2
- data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_content.rb +9 -9
- data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_item.rb +8 -8
- data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_trigger.rb +5 -5
- data/lib/shadcn_phlexcomponents/components/form/form.rb +139 -0
- data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +83 -0
- data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +116 -0
- data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +47 -0
- data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +96 -0
- data/lib/{components → shadcn_phlexcomponents/components/form}/form_error.rb +6 -2
- data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +108 -0
- data/lib/{components → shadcn_phlexcomponents/components/form}/form_hint.rb +6 -2
- data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +107 -0
- data/lib/shadcn_phlexcomponents/components/form/form_select.rb +65 -0
- data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +66 -0
- data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +60 -0
- data/lib/{components → shadcn_phlexcomponents/components/hover_card}/hover_card.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/hover_card}/hover_card_content.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/hover_card}/hover_card_trigger.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/input}/input.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/loading_button}/loading_button.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/popover}/popover.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/popover}/popover_content.rb +6 -6
- data/lib/{components → shadcn_phlexcomponents/components/popover}/popover_trigger.rb +2 -3
- data/lib/{components → shadcn_phlexcomponents/components/progress}/progress.rb +3 -3
- data/lib/{components → shadcn_phlexcomponents/components/radio_group}/radio_group.rb +33 -7
- data/lib/{components → shadcn_phlexcomponents/components/radio_group}/radio_group_item.rb +7 -7
- data/lib/{components → shadcn_phlexcomponents/components/select}/select.rb +22 -12
- data/lib/{components → shadcn_phlexcomponents/components/select}/select_content.rb +6 -6
- data/lib/{components → shadcn_phlexcomponents/components/select}/select_group.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/select}/select_item.rb +8 -8
- data/lib/{components → shadcn_phlexcomponents/components/select}/select_label.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/select}/select_trigger.rb +10 -10
- data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_close.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_content.rb +3 -3
- data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_trigger.rb +2 -2
- data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar.rb +3 -3
- data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_trigger.rb +2 -2
- data/lib/{components → shadcn_phlexcomponents/components/switch}/switch.rb +4 -4
- data/lib/{components → shadcn_phlexcomponents/components/tabs}/tabs.rb +2 -2
- data/lib/{components → shadcn_phlexcomponents/components/tabs}/tabs_content.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/tabs}/tabs_trigger.rb +4 -4
- data/lib/{components → shadcn_phlexcomponents/components/textarea}/textarea.rb +3 -2
- data/lib/{components → shadcn_phlexcomponents/components/theme_switcher}/theme_switcher.rb +2 -2
- data/lib/{components → shadcn_phlexcomponents/components/toast}/toast.rb +7 -7
- data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_container.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/tooltip}/tooltip.rb +3 -3
- data/lib/{components → shadcn_phlexcomponents/components/tooltip}/tooltip_content.rb +1 -1
- data/lib/{components → shadcn_phlexcomponents/components/tooltip}/tooltip_trigger.rb +1 -1
- data/lib/shadcn_phlexcomponents/version.rb +1 -1
- metadata +157 -144
- data/app/assets/tailwind/vanilla-calendar-pro.css +0 -466
- data/app/javascript/controllers/sheet_controller.js +0 -159
- data/lib/components/combobox.rb +0 -57
- data/lib/components/combobox_item.rb +0 -9
- data/lib/components/date_picker.rb +0 -94
- data/lib/components/date_range_picker.rb +0 -113
- data/lib/components/form.rb +0 -59
- /data/app/{assets/tailwind → stylesheets}/choices.css +0 -0
- /data/app/{assets/tailwind → stylesheets}/tailwindcss-animate.css +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/alert}/alert.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/alert}/alert_description.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/alert}/alert_title.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_description.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_footer.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_header.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/alert_dialog}/alert_dialog_title.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/aspect_ratio}/aspect_ratio.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_ellipsis.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_item.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_link.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_page.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/breadcrumb}/breadcrumb_separator.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/card}/card.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/card}/card_content.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/card}/card_description.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/card}/card_footer.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/card}/card_header.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/card}/card_title.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_description.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_footer.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_header.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/dialog}/dialog_title.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_item_to.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_label.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/dropdown_menu}/dropdown_menu_separator.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/form}/form_input.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/label}/label.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/link}/link.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination_ellipsis.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination_link.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination_next.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/pagination}/pagination_previous.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/separator}/separator.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_description.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_footer.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_header.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sheet}/sheet_title.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_container.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_content.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_footer.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_group.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_group_content.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_group_label.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_header.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_inset.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_button.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_item.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_sub.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_sub_button.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/sidebar}/sidebar_menu_sub_item.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/skeleton}/skeleton.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/table}/table.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/table}/table_body.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/table}/table_caption.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/table}/table_cell.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/table}/table_footer.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/table}/table_head.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/table}/table_header.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/table}/table_row.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/tabs}/tabs_list.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_action.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_action_to.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_content.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_description.rb +0 -0
- /data/lib/{components → shadcn_phlexcomponents/components/toast}/toast_title.rb +0 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShadcnPhlexcomponents
|
4
|
+
class FormCheckbox < Base
|
5
|
+
include FormHelpers
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
method = nil,
|
9
|
+
model: false,
|
10
|
+
object_name: nil,
|
11
|
+
value: nil,
|
12
|
+
name: nil,
|
13
|
+
id: nil,
|
14
|
+
label: nil,
|
15
|
+
error: nil,
|
16
|
+
hint: nil,
|
17
|
+
checked: nil,
|
18
|
+
**attributes
|
19
|
+
)
|
20
|
+
@method = method
|
21
|
+
@model = model
|
22
|
+
@object_name = object_name
|
23
|
+
@value = value
|
24
|
+
@model_value = model&.public_send(method)
|
25
|
+
@name = name
|
26
|
+
@id = id
|
27
|
+
@label = label
|
28
|
+
@error = error || (model ? model.errors.full_messages_for(method).first : nil)
|
29
|
+
@hint = hint
|
30
|
+
@aria_id = "form-field-#{SecureRandom.hex(5)}"
|
31
|
+
@checked = checked
|
32
|
+
super(**attributes)
|
33
|
+
end
|
34
|
+
|
35
|
+
def label_attributes(use_label_styles: false, **attributes)
|
36
|
+
attributes[:class] = [
|
37
|
+
use_label_styles ? Label::STYLES : nil,
|
38
|
+
"ml-6",
|
39
|
+
attributes[:class],
|
40
|
+
].compact.join(" ")
|
41
|
+
attributes[:for] ||= @id
|
42
|
+
attributes
|
43
|
+
end
|
44
|
+
|
45
|
+
def hint_attributes(**attributes)
|
46
|
+
attributes[:class] = [
|
47
|
+
"ml-6",
|
48
|
+
attributes[:class],
|
49
|
+
].compact.join(" ")
|
50
|
+
attributes
|
51
|
+
end
|
52
|
+
|
53
|
+
def view_template(&)
|
54
|
+
vanish(&)
|
55
|
+
|
56
|
+
@id ||= field_id(@object_name, @method)
|
57
|
+
@name ||= field_name(@object_name, @method)
|
58
|
+
|
59
|
+
div(class: "space-y-2") do
|
60
|
+
div(class: "flex items-top space-x-2") do
|
61
|
+
div(class: "grid gap-1.5 relative", data: label_and_hint_container_attributes) do
|
62
|
+
@attributes[:class] = "#{@attributes[:class]} -mt-[1.5px] absolute top-0 left-0"
|
63
|
+
|
64
|
+
Checkbox(
|
65
|
+
id: @id,
|
66
|
+
name: @name,
|
67
|
+
value: @value || "1",
|
68
|
+
checked: @checked || !!@model_value,
|
69
|
+
aria: aria_attributes,
|
70
|
+
disabled: @disabled,
|
71
|
+
**@attributes,
|
72
|
+
)
|
73
|
+
|
74
|
+
render_label(&)
|
75
|
+
render_hint(&)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
render_error
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShadcnPhlexcomponents
|
4
|
+
class FormCheckboxGroup < Base
|
5
|
+
include FormHelpers
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
method = nil,
|
9
|
+
model: false,
|
10
|
+
object_name: nil,
|
11
|
+
collection: [],
|
12
|
+
value_method: nil,
|
13
|
+
text_method: nil,
|
14
|
+
value: nil,
|
15
|
+
name: nil,
|
16
|
+
id: nil,
|
17
|
+
label: nil,
|
18
|
+
error: nil,
|
19
|
+
hint: nil,
|
20
|
+
disabled_items: nil,
|
21
|
+
**attributes
|
22
|
+
)
|
23
|
+
@method = method
|
24
|
+
@model = model
|
25
|
+
@object_name = object_name
|
26
|
+
|
27
|
+
@collection = if collection.first&.is_a?(Hash)
|
28
|
+
convert_collection_hash_to_struct(collection, value_method: value_method, text_method: text_method)
|
29
|
+
else
|
30
|
+
collection
|
31
|
+
end
|
32
|
+
|
33
|
+
@value_method = value_method
|
34
|
+
@text_method = text_method
|
35
|
+
|
36
|
+
@value = value
|
37
|
+
|
38
|
+
@model_value = if model
|
39
|
+
model_collection = model.public_send(method)
|
40
|
+
|
41
|
+
if model_collection.respond_to?(:map)
|
42
|
+
model_collection.map { |item| item.public_send(value_method) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@name = name
|
47
|
+
@id = id
|
48
|
+
@label = label
|
49
|
+
@error = error || (model ? model.errors.full_messages_for(method).first : nil)
|
50
|
+
@hint = hint
|
51
|
+
@disabled_items = disabled_items
|
52
|
+
@aria_id = "form-field-#{SecureRandom.hex(5)}"
|
53
|
+
super(**attributes)
|
54
|
+
end
|
55
|
+
|
56
|
+
def aria_attributes
|
57
|
+
attrs = super
|
58
|
+
attrs[:labelledby] = "#{@aria_id}-label"
|
59
|
+
attrs
|
60
|
+
end
|
61
|
+
|
62
|
+
def label_attributes(use_label_styles: false, **attributes)
|
63
|
+
attrs = super(use_label_styles: use_label_styles, **attributes)
|
64
|
+
attrs[:id] = "#{@aria_id}-label"
|
65
|
+
attrs
|
66
|
+
end
|
67
|
+
|
68
|
+
def checkbox(**attributes)
|
69
|
+
@checkbox_attributes = attributes
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def checkbox_label(**attributes)
|
74
|
+
@checkbox_label_attributes = attributes
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
|
78
|
+
def view_template(&)
|
79
|
+
vanish(&)
|
80
|
+
|
81
|
+
@id ||= field_id(@object_name, @method)
|
82
|
+
@name ||= field_name(@object_name, @method)
|
83
|
+
|
84
|
+
div(class: "space-y-2", data: label_and_hint_container_attributes) do
|
85
|
+
render_label(&)
|
86
|
+
|
87
|
+
CheckboxGroup(
|
88
|
+
id: @id,
|
89
|
+
name: @name,
|
90
|
+
value: @value || @model_value || [],
|
91
|
+
aria: aria_attributes,
|
92
|
+
item_id_prefix: @id,
|
93
|
+
**@attributes,
|
94
|
+
) do |c|
|
95
|
+
c.items(
|
96
|
+
@collection,
|
97
|
+
value_method: @value_method,
|
98
|
+
text_method: @text_method,
|
99
|
+
disabled_items: @disabled_items,
|
100
|
+
) do
|
101
|
+
if @checkbox_attributes
|
102
|
+
c.checkbox(**@checkbox_attributes)
|
103
|
+
end
|
104
|
+
|
105
|
+
if @checkbox_label_attributes
|
106
|
+
c.label(**@checkbox_label_attributes)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
render_hint(&)
|
112
|
+
render_error
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShadcnPhlexcomponents
|
4
|
+
class FormDatePicker < Base
|
5
|
+
include FormHelpers
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
method = nil,
|
9
|
+
model: false,
|
10
|
+
object_name: nil,
|
11
|
+
value: nil,
|
12
|
+
name: nil,
|
13
|
+
id: nil,
|
14
|
+
label: nil,
|
15
|
+
error: nil,
|
16
|
+
hint: nil,
|
17
|
+
**attributes
|
18
|
+
)
|
19
|
+
@method = method
|
20
|
+
@model = model
|
21
|
+
@object_name = object_name
|
22
|
+
@value = value
|
23
|
+
@model_value = model&.public_send(method)
|
24
|
+
@name = name
|
25
|
+
@id = id
|
26
|
+
@label = label
|
27
|
+
@error = error || (model ? model.errors.full_messages_for(method).first : nil)
|
28
|
+
@hint = hint
|
29
|
+
@aria_id = "form-field-#{SecureRandom.hex(5)}"
|
30
|
+
super(**attributes)
|
31
|
+
end
|
32
|
+
|
33
|
+
def view_template(&)
|
34
|
+
vanish(&)
|
35
|
+
|
36
|
+
@id ||= field_id(@object_name, @method)
|
37
|
+
@name ||= field_name(@object_name, @method)
|
38
|
+
|
39
|
+
div(class: "space-y-2", data: label_and_hint_container_attributes) do
|
40
|
+
render_label(&)
|
41
|
+
DatePicker(id: @id, name: @name, value: @value || @model_value, aria: aria_attributes, **@attributes)
|
42
|
+
render_hint(&)
|
43
|
+
render_error
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShadcnPhlexcomponents
|
4
|
+
class FormDateRangePicker < Base
|
5
|
+
include FormHelpers
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
start_date_method,
|
9
|
+
end_date_method,
|
10
|
+
model: false,
|
11
|
+
object_name: nil,
|
12
|
+
start_date: nil,
|
13
|
+
end_date: nil,
|
14
|
+
start_date_name: nil,
|
15
|
+
end_date_name: nil,
|
16
|
+
id: nil,
|
17
|
+
label: nil,
|
18
|
+
start_date_error: nil,
|
19
|
+
end_date_error: nil,
|
20
|
+
hint: nil,
|
21
|
+
**attributes
|
22
|
+
)
|
23
|
+
@start_date_method = start_date_method
|
24
|
+
@end_date_method = end_date_method
|
25
|
+
@model = model
|
26
|
+
@object_name = object_name
|
27
|
+
@start_date = start_date
|
28
|
+
@end_date = start_date
|
29
|
+
@start_date_model_value = model&.public_send(start_date_method)
|
30
|
+
@end_date_model_value = model&.public_send(end_date_method)
|
31
|
+
@start_date_name = start_date_name
|
32
|
+
@end_date_name = end_date_name
|
33
|
+
@id = id
|
34
|
+
@label = label
|
35
|
+
@start_date_error = start_date_error || (model ? model.errors.full_messages_for(start_date_method).first : nil)
|
36
|
+
@end_date_error = end_date_error || (model ? model.errors.full_messages_for(end_date_method).first : nil)
|
37
|
+
@error = (@start_date_error || @end_date_error).present?
|
38
|
+
@hint = hint
|
39
|
+
@aria_id = "form-field-#{SecureRandom.hex(5)}"
|
40
|
+
super(**attributes)
|
41
|
+
end
|
42
|
+
|
43
|
+
def render_label(&)
|
44
|
+
# It's currently not possible to separate the content of the yield in Phlex.
|
45
|
+
# So we use Javascript to remove the duplicated hint or label.
|
46
|
+
if @yield_label && @yield_hint
|
47
|
+
div(data: { remove_hint: true }, &)
|
48
|
+
elsif @yield_label
|
49
|
+
yield
|
50
|
+
elsif @label
|
51
|
+
attrs = label_attributes(use_label_styles: false)
|
52
|
+
Label(**attrs) { @label }
|
53
|
+
elsif @label != false
|
54
|
+
attrs = label_attributes(use_label_styles: true)
|
55
|
+
rails_label(@object_name, [@start_date_method, @end_date_method].to_sentence, nil, **attrs)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def render_error
|
60
|
+
if @start_date_error && @end_date_error
|
61
|
+
FormError(nil, aria_id: @aria_id) do
|
62
|
+
span { @start_date_error }
|
63
|
+
br
|
64
|
+
span { @end_date_error }
|
65
|
+
end
|
66
|
+
elsif @start_date_error
|
67
|
+
FormError(@start_date_error, aria_id: @aria_id)
|
68
|
+
elsif @end_date_error
|
69
|
+
FormError(@end_date_error, aria_id: @aria_id)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def view_template(&)
|
74
|
+
vanish(&)
|
75
|
+
|
76
|
+
@id ||= field_id(@object_name, @start_date_method)
|
77
|
+
@start_date_name ||= field_name(@object_name, @start_date_method)
|
78
|
+
@end_date_name ||= field_name(@object_name, @end_date_method)
|
79
|
+
|
80
|
+
div(class: "space-y-2", data: label_and_hint_container_attributes) do
|
81
|
+
render_label(&)
|
82
|
+
DateRangePicker(
|
83
|
+
id: @id,
|
84
|
+
start_date_name: @start_date_name,
|
85
|
+
end_date_name: @end_date_name,
|
86
|
+
start_date: @start_date || @start_date_model_value,
|
87
|
+
end_date: @end_date || @end_date_model_value,
|
88
|
+
aria: aria_attributes,
|
89
|
+
**@attributes,
|
90
|
+
)
|
91
|
+
render_hint(&)
|
92
|
+
render_error
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -4,14 +4,18 @@ module ShadcnPhlexcomponents
|
|
4
4
|
class FormError < Base
|
5
5
|
STYLES = "text-[0.8rem] font-medium text-destructive"
|
6
6
|
|
7
|
-
def initialize(message
|
7
|
+
def initialize(message, aria_id: nil, **attributes)
|
8
8
|
@message = message
|
9
9
|
@id = aria_id ? "#{aria_id}-message" : nil
|
10
10
|
super(**attributes)
|
11
11
|
end
|
12
12
|
|
13
13
|
def view_template(&)
|
14
|
-
|
14
|
+
if @message
|
15
|
+
p(id: @id, **@attributes) { @message }
|
16
|
+
else
|
17
|
+
p(id: @id, **@attributes, &)
|
18
|
+
end
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShadcnPhlexcomponents
|
4
|
+
module FormHelpers
|
5
|
+
module AliasedLabel
|
6
|
+
include Phlex::Rails::Helpers::Label
|
7
|
+
|
8
|
+
alias_method :rails_label, :label
|
9
|
+
end
|
10
|
+
|
11
|
+
include AliasedLabel
|
12
|
+
include Phlex::Rails::Helpers::FieldID
|
13
|
+
include Phlex::Rails::Helpers::FieldName
|
14
|
+
|
15
|
+
def label(text = nil, **attributes, &)
|
16
|
+
@yield_label = true
|
17
|
+
attrs = label_attributes(use_label_styles: false, **attributes)
|
18
|
+
|
19
|
+
if text
|
20
|
+
Label(**attrs) { text }
|
21
|
+
else
|
22
|
+
Label(**attrs, &)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def hint(text = nil, **attributes, &)
|
27
|
+
@yield_hint = true
|
28
|
+
attrs = hint_attributes(**attributes)
|
29
|
+
|
30
|
+
if text
|
31
|
+
FormHint(text, **attrs)
|
32
|
+
else
|
33
|
+
FormHint(**attrs, &)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def render_label(&)
|
38
|
+
# It's currently not possible to separate the content of the yield in Phlex.
|
39
|
+
# So we use Javascript to remove the duplicated hint or label.
|
40
|
+
if @yield_label && @yield_hint
|
41
|
+
div(data: { remove_hint: true }, &)
|
42
|
+
elsif @yield_label
|
43
|
+
yield
|
44
|
+
elsif @label
|
45
|
+
attrs = label_attributes(use_label_styles: false)
|
46
|
+
Label(**attrs) { @label }
|
47
|
+
elsif @label != false
|
48
|
+
attrs = label_attributes(use_label_styles: true)
|
49
|
+
rails_label(@object_name, @method, nil, **attrs)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def render_hint(&)
|
54
|
+
# It's currently not possible to separate the content of the yield in Phlex.
|
55
|
+
# So we use Javascript to remove the duplicated hint or label.
|
56
|
+
if @yield_label && @yield_hint
|
57
|
+
div(data: { remove_label: true }, &)
|
58
|
+
elsif @yield_hint
|
59
|
+
yield
|
60
|
+
elsif @hint
|
61
|
+
attrs = hint_attributes
|
62
|
+
FormHint(@hint, aria_id: @aria_id, **attrs)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def render_error
|
67
|
+
if @error
|
68
|
+
FormError(@error, aria_id: @aria_id)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def label_attributes(use_label_styles: false, **attributes)
|
73
|
+
attributes[:class] = [
|
74
|
+
use_label_styles ? Label::STYLES : nil,
|
75
|
+
@error ? "text-destructive" : nil,
|
76
|
+
attributes[:class],
|
77
|
+
].compact.join(" ")
|
78
|
+
attributes[:for] ||= @id
|
79
|
+
attributes
|
80
|
+
end
|
81
|
+
|
82
|
+
def hint_attributes(**attributes)
|
83
|
+
attributes
|
84
|
+
end
|
85
|
+
|
86
|
+
def label_and_hint_container_attributes
|
87
|
+
{
|
88
|
+
controller: @yield_label && @yield_hint ? "form-field" : nil,
|
89
|
+
}.compact
|
90
|
+
end
|
91
|
+
|
92
|
+
def aria_attributes
|
93
|
+
{
|
94
|
+
describedby: describedby,
|
95
|
+
invalid: @error.present?,
|
96
|
+
}.compact
|
97
|
+
end
|
98
|
+
|
99
|
+
def describedby
|
100
|
+
return if !@hint && !@error
|
101
|
+
|
102
|
+
[
|
103
|
+
@hint ? "#{@aria_id}-description" : nil,
|
104
|
+
@error ? "#{@aria_id}-message" : nil,
|
105
|
+
].compact.join(" ")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -4,14 +4,18 @@ module ShadcnPhlexcomponents
|
|
4
4
|
class FormHint < Base
|
5
5
|
STYLES = "text-[0.8rem] text-muted-foreground"
|
6
6
|
|
7
|
-
def initialize(message
|
7
|
+
def initialize(message = nil, aria_id: nil, **attributes)
|
8
8
|
@message = message
|
9
9
|
@id = aria_id ? "#{aria_id}-description" : nil
|
10
10
|
super(**attributes)
|
11
11
|
end
|
12
12
|
|
13
13
|
def view_template(&)
|
14
|
-
|
14
|
+
if @message
|
15
|
+
p(id: @id, **@attributes) { @message }
|
16
|
+
else
|
17
|
+
p(id: @id, **@attributes, &)
|
18
|
+
end
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShadcnPhlexcomponents
|
4
|
+
class FormRadioGroup < Base
|
5
|
+
include FormHelpers
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
method = nil,
|
9
|
+
model: false,
|
10
|
+
object_name: nil,
|
11
|
+
collection: [],
|
12
|
+
value_method: nil,
|
13
|
+
text_method: nil,
|
14
|
+
value: nil,
|
15
|
+
name: nil,
|
16
|
+
id: nil,
|
17
|
+
label: nil,
|
18
|
+
error: nil,
|
19
|
+
hint: nil,
|
20
|
+
disabled_items: nil,
|
21
|
+
**attributes
|
22
|
+
)
|
23
|
+
@method = method
|
24
|
+
@model = model
|
25
|
+
@object_name = object_name
|
26
|
+
|
27
|
+
@collection = if collection.first&.is_a?(Hash)
|
28
|
+
convert_collection_hash_to_struct(collection, value_method: value_method, text_method: text_method)
|
29
|
+
else
|
30
|
+
collection
|
31
|
+
end
|
32
|
+
|
33
|
+
@value_method = value_method
|
34
|
+
@text_method = text_method
|
35
|
+
@value = value
|
36
|
+
@model_value = model&.public_send(method)
|
37
|
+
@name = name
|
38
|
+
@id = id
|
39
|
+
@label = label
|
40
|
+
@error = error || (model ? model.errors.full_messages_for(method).first : nil)
|
41
|
+
@hint = hint
|
42
|
+
@disabled_items = disabled_items
|
43
|
+
@aria_id = "form-field-#{SecureRandom.hex(5)}"
|
44
|
+
super(**attributes)
|
45
|
+
end
|
46
|
+
|
47
|
+
def aria_attributes
|
48
|
+
attrs = super
|
49
|
+
attrs[:labelledby] = "#{@aria_id}-label"
|
50
|
+
attrs
|
51
|
+
end
|
52
|
+
|
53
|
+
def label_attributes(use_label_styles: false, **attributes)
|
54
|
+
attrs = super(use_label_styles: use_label_styles, **attributes)
|
55
|
+
attrs[:id] = "#{@aria_id}-label"
|
56
|
+
attrs
|
57
|
+
end
|
58
|
+
|
59
|
+
def radio(**attributes)
|
60
|
+
@radio_attributes = attributes
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def radio_label(**attributes)
|
65
|
+
@radio_label_attributes = attributes
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def view_template(&)
|
70
|
+
vanish(&)
|
71
|
+
|
72
|
+
@id ||= field_id(@object_name, @method)
|
73
|
+
@name ||= field_name(@object_name, @method)
|
74
|
+
|
75
|
+
div(class: "space-y-2", data: label_and_hint_container_attributes) do
|
76
|
+
render_label(&)
|
77
|
+
|
78
|
+
RadioGroup(
|
79
|
+
name: @name,
|
80
|
+
id: @id,
|
81
|
+
value: @value || @model_value,
|
82
|
+
aria: aria_attributes,
|
83
|
+
item_id_prefix: @id,
|
84
|
+
**@attributes,
|
85
|
+
) do |c|
|
86
|
+
c.items(
|
87
|
+
@collection,
|
88
|
+
value_method: @value_method,
|
89
|
+
text_method: @text_method,
|
90
|
+
disabled_items: @disabled_items,
|
91
|
+
) do
|
92
|
+
if @radio_attributes
|
93
|
+
c.radio(**@radio_attributes)
|
94
|
+
end
|
95
|
+
|
96
|
+
if @radio_label_attributes
|
97
|
+
c.label(**@radio_label_attributes)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
render_hint(&)
|
103
|
+
render_error
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShadcnPhlexcomponents
|
4
|
+
class FormSelect < Base
|
5
|
+
include FormHelpers
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
method = nil,
|
9
|
+
model: false,
|
10
|
+
object_name: nil,
|
11
|
+
collection: [],
|
12
|
+
value_method: nil,
|
13
|
+
text_method: nil,
|
14
|
+
value: nil,
|
15
|
+
name: nil,
|
16
|
+
id: nil,
|
17
|
+
label: nil,
|
18
|
+
error: nil,
|
19
|
+
hint: nil,
|
20
|
+
disabled_items: nil,
|
21
|
+
**attributes
|
22
|
+
)
|
23
|
+
@method = method
|
24
|
+
@model = model
|
25
|
+
@object_name = object_name
|
26
|
+
|
27
|
+
@collection = if collection.first&.is_a?(Hash)
|
28
|
+
convert_collection_hash_to_struct(collection, value_method: value_method, text_method: text_method)
|
29
|
+
else
|
30
|
+
collection
|
31
|
+
end
|
32
|
+
|
33
|
+
@value_method = value_method
|
34
|
+
@text_method = text_method
|
35
|
+
@value = value
|
36
|
+
@model_value = model&.public_send(method)
|
37
|
+
@name = name
|
38
|
+
@id = id
|
39
|
+
@label = label
|
40
|
+
@error = error || (model ? model.errors.full_messages_for(method).first : nil)
|
41
|
+
@hint = hint
|
42
|
+
@disabled_items = disabled_items
|
43
|
+
@aria_id = "form-field-#{SecureRandom.hex(5)}"
|
44
|
+
super(**attributes)
|
45
|
+
end
|
46
|
+
|
47
|
+
def view_template(&)
|
48
|
+
vanish(&)
|
49
|
+
|
50
|
+
@id ||= field_id(@object_name, @method)
|
51
|
+
@name ||= field_name(@object_name, @method)
|
52
|
+
|
53
|
+
div(class: "space-y-2", data: label_and_hint_container_attributes) do
|
54
|
+
render_label(&)
|
55
|
+
|
56
|
+
Select(id: @id, name: @name, value: @value || @model_value, aria: aria_attributes, **@attributes) do |s|
|
57
|
+
s.items(@collection, value_method: @value_method, text_method: @text_method, disabled_items: @disabled_items)
|
58
|
+
end
|
59
|
+
|
60
|
+
render_hint(&)
|
61
|
+
render_error
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|