shadcn_phlexcomponents 0.1.11 → 0.1.14
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/app/javascript/controllers/accordion_controller.ts +65 -62
- data/app/javascript/controllers/alert_dialog_controller.ts +12 -0
- data/app/javascript/controllers/avatar_controller.ts +7 -2
- data/app/javascript/controllers/checkbox_controller.ts +11 -4
- data/app/javascript/controllers/collapsible_controller.ts +12 -5
- data/app/javascript/controllers/combobox_controller.ts +270 -39
- data/app/javascript/controllers/command_controller.ts +223 -51
- data/app/javascript/controllers/date_picker_controller.ts +185 -125
- data/app/javascript/controllers/date_range_picker_controller.ts +89 -79
- data/app/javascript/controllers/dialog_controller.ts +59 -57
- data/app/javascript/controllers/dropdown_menu_controller.ts +212 -36
- data/app/javascript/controllers/dropdown_menu_sub_controller.ts +31 -29
- data/app/javascript/controllers/form_field_controller.ts +6 -1
- data/app/javascript/controllers/hover_card_controller.ts +36 -26
- data/app/javascript/controllers/loading_button_controller.ts +6 -1
- data/app/javascript/controllers/popover_controller.ts +42 -65
- data/app/javascript/controllers/progress_controller.ts +9 -3
- data/app/javascript/controllers/radio_group_controller.ts +16 -9
- data/app/javascript/controllers/select_controller.ts +206 -65
- data/app/javascript/controllers/slider_controller.ts +23 -16
- data/app/javascript/controllers/switch_controller.ts +11 -4
- data/app/javascript/controllers/tabs_controller.ts +26 -18
- data/app/javascript/controllers/theme_switcher_controller.ts +6 -1
- data/app/javascript/controllers/toast_container_controller.ts +6 -1
- data/app/javascript/controllers/toast_controller.ts +7 -1
- data/app/javascript/controllers/toggle_controller.ts +28 -0
- data/app/javascript/controllers/toggle_group_controller.ts +28 -0
- data/app/javascript/controllers/tooltip_controller.ts +43 -31
- data/app/javascript/shadcn_phlexcomponents.ts +29 -25
- data/app/javascript/utils/command.ts +544 -0
- data/app/javascript/utils/floating_ui.ts +196 -0
- data/app/javascript/utils/index.ts +417 -0
- data/app/stylesheets/date_picker.css +118 -0
- data/lib/shadcn_phlexcomponents/alias.rb +3 -0
- data/lib/shadcn_phlexcomponents/components/accordion.rb +2 -1
- data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +18 -15
- data/lib/shadcn_phlexcomponents/components/base.rb +14 -0
- data/lib/shadcn_phlexcomponents/components/collapsible.rb +1 -2
- data/lib/shadcn_phlexcomponents/components/combobox.rb +87 -57
- data/lib/shadcn_phlexcomponents/components/command.rb +77 -47
- data/lib/shadcn_phlexcomponents/components/date_picker.rb +25 -81
- data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +21 -4
- data/lib/shadcn_phlexcomponents/components/dialog.rb +14 -12
- data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +5 -4
- data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +2 -1
- data/lib/shadcn_phlexcomponents/components/form/form_combobox.rb +64 -0
- data/lib/shadcn_phlexcomponents/components/form.rb +14 -0
- data/lib/shadcn_phlexcomponents/components/hover_card.rb +3 -2
- data/lib/shadcn_phlexcomponents/components/popover.rb +3 -3
- data/lib/shadcn_phlexcomponents/components/select.rb +10 -25
- data/lib/shadcn_phlexcomponents/components/sheet.rb +15 -11
- data/lib/shadcn_phlexcomponents/components/table.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/tabs.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/toast_container.rb +1 -1
- data/lib/shadcn_phlexcomponents/components/toggle.rb +54 -0
- data/lib/shadcn_phlexcomponents/components/tooltip.rb +3 -2
- data/lib/shadcn_phlexcomponents/engine.rb +1 -5
- data/lib/shadcn_phlexcomponents/version.rb +1 -1
- metadata +9 -4
- data/app/javascript/controllers/command_root_controller.ts +0 -355
- data/app/javascript/controllers/dropdown_menu_root_controller.ts +0 -234
- data/app/javascript/utils.ts +0 -437
@@ -1,3 +1,48 @@
|
|
1
|
+
[data-vc='calendar'] {
|
2
|
+
@apply relative flex flex-col outline-none;
|
3
|
+
}
|
4
|
+
|
5
|
+
[data-vc='controls'] {
|
6
|
+
@apply absolute z-20 -left-1 -right-1 -top-1.5 flex justify-between items-center pt-1.5 px-1 pointer-events-none box-content;
|
7
|
+
}
|
8
|
+
|
9
|
+
[data-vc='grid'] {
|
10
|
+
@apply grid gap-4 grid-cols-1 md:grid-cols-2;
|
11
|
+
}
|
12
|
+
|
13
|
+
[data-vc='column'] {
|
14
|
+
@apply flex flex-col;
|
15
|
+
}
|
16
|
+
|
17
|
+
[data-vc='header'] {
|
18
|
+
@apply relative flex items-center mb-4;
|
19
|
+
}
|
20
|
+
|
21
|
+
[data-vc-header='content'] {
|
22
|
+
@apply grid grid-flow-col gap-x-1 auto-cols-max items-center justify-center px-4 whitespace-pre-wrap grow;
|
23
|
+
}
|
24
|
+
|
25
|
+
[data-vc='month'],
|
26
|
+
[data-vc='year'] {
|
27
|
+
@apply inline-flex items-center justify-center whitespace-nowrap font-medium transition-all;
|
28
|
+
@apply disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4;
|
29
|
+
@apply shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px];
|
30
|
+
@apply aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive border;
|
31
|
+
@apply shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50;
|
32
|
+
@apply rounded-md gap-1.5 px-3 has-[>svg]:px-2.5 text-xs h-7 bg-transparent;
|
33
|
+
}
|
34
|
+
|
35
|
+
[data-vc-arrow='prev'],
|
36
|
+
[data-vc-arrow='next'] {
|
37
|
+
@apply inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium;
|
38
|
+
@apply transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none;
|
39
|
+
@apply [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring;
|
40
|
+
@apply focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20;
|
41
|
+
@apply dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive border shadow-xs hover:bg-accent;
|
42
|
+
@apply hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 pointer-events-auto;
|
43
|
+
@apply size-7 bg-transparent p-0 opacity-50 hover:opacity-100;
|
44
|
+
}
|
45
|
+
|
1
46
|
[data-vc-arrow='next']:before {
|
2
47
|
@apply bg-current size-4 mask-size-[auto_16px] mask-center mask-no-repeat absolute content-[''];
|
3
48
|
mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right-icon lucide-chevron-right"><path d="m9 18 6-6-6-6"/></svg>');
|
@@ -8,6 +53,79 @@
|
|
8
53
|
mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-left-icon lucide-chevron-left"><path d="m15 18-6-6 6-6"/></svg>');
|
9
54
|
}
|
10
55
|
|
56
|
+
[data-vc='wrapper'] {
|
57
|
+
@apply flex items-center content-center h-full;
|
58
|
+
}
|
59
|
+
|
60
|
+
[data-vc='content'] {
|
61
|
+
@apply flex flex-col grow h-full;
|
62
|
+
}
|
63
|
+
|
64
|
+
[data-vc='months'] {
|
65
|
+
@apply grid gap-2 grid-cols-4 items-center grow;
|
66
|
+
}
|
67
|
+
|
68
|
+
[data-vc='years'] {
|
69
|
+
@apply grid gap-2 grid-cols-5 items-center grow;
|
70
|
+
}
|
71
|
+
|
72
|
+
[data-vc-months-month],
|
73
|
+
[data-vc-years-year] {
|
74
|
+
@apply inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all;
|
75
|
+
@apply disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4;
|
76
|
+
@apply shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px];
|
77
|
+
@apply aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive;
|
78
|
+
@apply hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 h-9 px-4 py-2 has-[>svg]:px-3;
|
79
|
+
@apply aria-[selected=true]:text-primary-foreground aria-[selected=true]:bg-primary;
|
80
|
+
@apply aria-[selected=true]:hover:text-primary-foreground aria-[selected=true]:hover:bg-primary;
|
81
|
+
}
|
82
|
+
|
83
|
+
[data-vc='week'] {
|
84
|
+
@apply grid mb-2 grid-cols-[repeat(7,_1fr)] justify-items-center items-center text-center;
|
85
|
+
}
|
86
|
+
|
87
|
+
[data-vc-week-day] {
|
88
|
+
@apply text-muted-foreground rounded-md w-8 font-normal text-[0.8rem];
|
89
|
+
}
|
90
|
+
|
91
|
+
[data-vc='dates'] {
|
92
|
+
@apply grid gap-y-2 grid-cols-[repeat(7,_1fr)] justify-items-center items-center;
|
93
|
+
}
|
94
|
+
|
95
|
+
[data-vc-date-btn] {
|
96
|
+
@apply inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm transition-all;
|
97
|
+
@apply disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4;
|
98
|
+
@apply shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px];
|
99
|
+
@apply aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive;
|
100
|
+
@apply hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 has-[>svg]:px-3 size-8 p-0 font-normal;
|
101
|
+
@apply aria-[disabled]:text-muted-foreground aria-[disabled]:opacity-50 aria-[disabled]:pointer-events-none;
|
102
|
+
}
|
103
|
+
|
104
|
+
[data-vc-date-selected] [data-vc-date-btn] {
|
105
|
+
@apply bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground;
|
106
|
+
}
|
107
|
+
|
108
|
+
[data-vc-date-today] [data-vc-date-btn] {
|
109
|
+
@apply bg-accent text-accent-foreground;
|
110
|
+
}
|
111
|
+
|
112
|
+
[data-vc-date-month='prev'] [data-vc-date-btn],
|
113
|
+
[data-vc-date-month='next'] [data-vc-date-btn] {
|
114
|
+
@apply text-muted-foreground;
|
115
|
+
}
|
116
|
+
|
117
|
+
[data-vc-date-selected='middle'][data-vc-date-selected] [data-vc-date-btn] {
|
118
|
+
@apply bg-accent text-accent-foreground;
|
119
|
+
}
|
120
|
+
|
121
|
+
[data-vc-date-selected='first'][data-vc-date-selected] [data-vc-date-btn] {
|
122
|
+
@apply bg-primary text-primary-foreground;
|
123
|
+
}
|
124
|
+
|
125
|
+
[data-vc-date-hover] [data-vc-date-btn] {
|
126
|
+
@apply bg-accent text-accent-foreground;
|
127
|
+
}
|
128
|
+
|
11
129
|
[data-vc='grid'][data-vc-grid='hidden'] [data-vc='column'] {
|
12
130
|
pointer-events: none;
|
13
131
|
opacity: 0.3;
|
@@ -14,7 +14,9 @@ CheckboxGroup = ShadcnPhlexcomponents::CheckboxGroup
|
|
14
14
|
Checkbox = ShadcnPhlexcomponents::Checkbox
|
15
15
|
Collapsible = ShadcnPhlexcomponents::Collapsible
|
16
16
|
Command = ShadcnPhlexcomponents::Command
|
17
|
+
CommandItem = ShadcnPhlexcomponents::CommandItem
|
17
18
|
Combobox = ShadcnPhlexcomponents::Combobox
|
19
|
+
ComboboxItem = ShadcnPhlexcomponents::ComboboxItem
|
18
20
|
DatePicker = ShadcnPhlexcomponents::DatePicker
|
19
21
|
DateRangePicker = ShadcnPhlexcomponents::DateRangePicker
|
20
22
|
Dialog = ShadcnPhlexcomponents::Dialog
|
@@ -42,4 +44,5 @@ Textarea = ShadcnPhlexcomponents::Textarea
|
|
42
44
|
ThemeSwitcher = ShadcnPhlexcomponents::ThemeSwitcher
|
43
45
|
Toast = ShadcnPhlexcomponents::Toast
|
44
46
|
ToastContainer = ShadcnPhlexcomponents::ToastContainer
|
47
|
+
Toggle = ShadcnPhlexcomponents::Toggle
|
45
48
|
Tooltip = ShadcnPhlexcomponents::Tooltip
|
@@ -81,6 +81,7 @@ module ShadcnPhlexcomponents
|
|
81
81
|
},
|
82
82
|
data: {
|
83
83
|
state: "closed",
|
84
|
+
accordion_target: "trigger",
|
84
85
|
action: <<~HEREDOC,
|
85
86
|
click->accordion#toggle
|
86
87
|
keydown.up->accordion#focusTrigger:prevent
|
@@ -119,7 +120,7 @@ module ShadcnPhlexcomponents
|
|
119
120
|
},
|
120
121
|
data: {
|
121
122
|
state: "closed",
|
122
|
-
|
123
|
+
accordion_target: "content"
|
123
124
|
},
|
124
125
|
) do
|
125
126
|
div(**@attributes, &)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ShadcnPhlexcomponents
|
4
4
|
class AlertDialog < Base
|
5
|
-
class_variants(base: "inline-
|
5
|
+
class_variants(base: "inline-flex max-w-fit")
|
6
6
|
|
7
7
|
def initialize(open: false, **attributes)
|
8
8
|
@open = open
|
@@ -49,14 +49,18 @@ module ShadcnPhlexcomponents
|
|
49
49
|
def default_attributes
|
50
50
|
{
|
51
51
|
data: {
|
52
|
-
controller: "dialog",
|
53
|
-
|
54
|
-
}
|
55
|
-
}
|
52
|
+
controller: "alert-dialog",
|
53
|
+
alert_dialog_is_open_value: @open.to_s
|
54
|
+
}
|
55
|
+
}
|
56
56
|
end
|
57
57
|
|
58
58
|
def view_template(&)
|
59
|
-
div(**@attributes
|
59
|
+
div(**@attributes) do
|
60
|
+
overlay("alert-dialog")
|
61
|
+
|
62
|
+
yield
|
63
|
+
end
|
60
64
|
end
|
61
65
|
end
|
62
66
|
|
@@ -75,10 +79,10 @@ module ShadcnPhlexcomponents
|
|
75
79
|
expanded: "false",
|
76
80
|
controls: "#{@aria_id}-content",
|
77
81
|
},
|
78
|
-
data: {
|
79
|
-
action: "click->dialog#open",
|
80
|
-
dialog_target: "trigger",
|
82
|
+
data: {
|
81
83
|
as_child: @as_child.to_s,
|
84
|
+
alert_dialog_target: "trigger",
|
85
|
+
action: "click->alert-dialog#open"
|
82
86
|
},
|
83
87
|
}
|
84
88
|
end
|
@@ -106,7 +110,7 @@ module ShadcnPhlexcomponents
|
|
106
110
|
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
|
107
111
|
data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)]
|
108
112
|
translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg
|
109
|
-
pointer-events-auto
|
113
|
+
pointer-events-auto outline-none
|
110
114
|
HEREDOC
|
111
115
|
)
|
112
116
|
|
@@ -126,14 +130,13 @@ module ShadcnPhlexcomponents
|
|
126
130
|
},
|
127
131
|
data: {
|
128
132
|
state: "closed",
|
129
|
-
|
133
|
+
alert_dialog_target: "content"
|
130
134
|
},
|
131
135
|
}
|
132
136
|
end
|
133
137
|
|
134
138
|
def view_template(&)
|
135
|
-
|
136
|
-
div(class: "#{@class} hidden", **@attributes, &)
|
139
|
+
div(style: { display: "none" }, **@attributes, &)
|
137
140
|
end
|
138
141
|
end
|
139
142
|
|
@@ -201,7 +204,7 @@ module ShadcnPhlexcomponents
|
|
201
204
|
def default_attributes
|
202
205
|
{
|
203
206
|
data: {
|
204
|
-
action: "click->dialog#close",
|
207
|
+
action: "click->alert-dialog#close",
|
205
208
|
},
|
206
209
|
}
|
207
210
|
end
|
@@ -222,7 +225,7 @@ module ShadcnPhlexcomponents
|
|
222
225
|
def default_attributes
|
223
226
|
{
|
224
227
|
data: {
|
225
|
-
action: "click->dialog#close",
|
228
|
+
action: "click->alert-dialog#close",
|
226
229
|
},
|
227
230
|
}
|
228
231
|
end
|
@@ -141,5 +141,19 @@ module ShadcnPhlexcomponents
|
|
141
141
|
disabled
|
142
142
|
end
|
143
143
|
end
|
144
|
+
|
145
|
+
def overlay(component)
|
146
|
+
div(
|
147
|
+
style: { display: "none" },
|
148
|
+
class: "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 pointer-events-auto",
|
149
|
+
aria: {
|
150
|
+
hidden: true,
|
151
|
+
},
|
152
|
+
data: {
|
153
|
+
state: "closed",
|
154
|
+
"#{component}-target" => "overlay"
|
155
|
+
}
|
156
|
+
)
|
157
|
+
end
|
144
158
|
end
|
145
159
|
end
|
@@ -9,18 +9,24 @@ module ShadcnPhlexcomponents
|
|
9
9
|
name: nil,
|
10
10
|
value: nil,
|
11
11
|
placeholder: nil,
|
12
|
-
dir: "ltr",
|
13
12
|
include_blank: false,
|
14
13
|
disabled: false,
|
14
|
+
search_path: nil,
|
15
|
+
search_error_text: "Something went wrong, please try again.",
|
16
|
+
search_empty_text: "No results found",
|
17
|
+
search_placeholder_text: "Search...",
|
15
18
|
**attributes
|
16
19
|
)
|
17
20
|
@id = id
|
18
21
|
@name = name
|
19
22
|
@value = value
|
20
23
|
@placeholder = placeholder
|
21
|
-
@dir = dir
|
22
24
|
@include_blank = include_blank
|
23
25
|
@disabled = disabled
|
26
|
+
@search_path = search_path
|
27
|
+
@search_error_text = search_error_text
|
28
|
+
@search_empty_text = search_empty_text
|
29
|
+
@search_placeholder_text = search_placeholder_text
|
24
30
|
@aria_id = "combobox-#{SecureRandom.hex(5)}"
|
25
31
|
super(**attributes)
|
26
32
|
end
|
@@ -29,7 +35,6 @@ module ShadcnPhlexcomponents
|
|
29
35
|
ComboboxTrigger(
|
30
36
|
id: @id,
|
31
37
|
aria_id: @aria_id,
|
32
|
-
dir: @dir,
|
33
38
|
value: @value,
|
34
39
|
placeholder: @placeholder,
|
35
40
|
disabled: @disabled,
|
@@ -39,7 +44,13 @@ module ShadcnPhlexcomponents
|
|
39
44
|
|
40
45
|
def content(**attributes, &)
|
41
46
|
ComboboxContent(
|
42
|
-
|
47
|
+
include_blank: @include_blank,
|
48
|
+
search_error_text: @search_error_text,
|
49
|
+
search_empty_text: @search_empty_text,
|
50
|
+
search_placeholder_text: @search_placeholder_text,
|
51
|
+
aria_id: @aria_id,
|
52
|
+
**attributes,
|
53
|
+
&
|
43
54
|
)
|
44
55
|
end
|
45
56
|
|
@@ -69,13 +80,18 @@ module ShadcnPhlexcomponents
|
|
69
80
|
ComboboxTrigger(
|
70
81
|
id: @id,
|
71
82
|
aria_id: @aria_id,
|
72
|
-
dir: @dir,
|
73
83
|
value: @value,
|
74
84
|
placeholder: @placeholder,
|
75
85
|
disabled: @disabled,
|
76
86
|
)
|
77
87
|
|
78
|
-
ComboboxContent(
|
88
|
+
ComboboxContent(
|
89
|
+
aria_id: @aria_id,
|
90
|
+
include_blank: @include_blank,
|
91
|
+
search_error_text: @search_error_text,
|
92
|
+
search_empty_text: @search_empty_text,
|
93
|
+
search_placeholder_text: @search_placeholder_text
|
94
|
+
) do
|
79
95
|
collection.each do |item|
|
80
96
|
value = item.public_send(value_method)
|
81
97
|
text = item.public_send(text_method)
|
@@ -103,6 +119,7 @@ module ShadcnPhlexcomponents
|
|
103
119
|
data: {
|
104
120
|
aria_id: @aria_id,
|
105
121
|
controller: "combobox",
|
122
|
+
search_path: @search_path,
|
106
123
|
combobox_selected_value: @value,
|
107
124
|
},
|
108
125
|
}
|
@@ -117,25 +134,22 @@ module ShadcnPhlexcomponents
|
|
117
134
|
aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex items-center
|
118
135
|
justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs
|
119
136
|
transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50
|
120
|
-
|
121
|
-
|
122
|
-
[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
|
123
|
-
data-[placeholder]:data-[has-value=false]:text-muted-foreground w-full
|
137
|
+
h-9 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
|
138
|
+
data-[placeholder]:data-[has-value=false]:text-muted-foreground w-full disabled:dark:hover:bg-input/30
|
124
139
|
HEREDOC
|
125
140
|
)
|
126
141
|
|
127
|
-
def initialize(id: nil, value: nil, placeholder: nil,
|
142
|
+
def initialize(id: nil, value: nil, placeholder: nil, aria_id: nil, **attributes)
|
128
143
|
@id = id
|
129
144
|
@value = value
|
130
145
|
@placeholder = placeholder
|
131
|
-
@dir = dir
|
132
146
|
@aria_id = aria_id
|
133
147
|
super(**attributes)
|
134
148
|
end
|
135
149
|
|
136
150
|
def view_template
|
137
151
|
button(**@attributes) do
|
138
|
-
span(class: "pointer-events-none", data: { combobox_target: "triggerText" }) do
|
152
|
+
span(class: "pointer-events-none line-clamp-1 flex items-center gap-2", data: { combobox_target: "triggerText" }) do
|
139
153
|
@value || @placeholder
|
140
154
|
end
|
141
155
|
|
@@ -147,7 +161,6 @@ module ShadcnPhlexcomponents
|
|
147
161
|
{
|
148
162
|
type: "button",
|
149
163
|
id: @id,
|
150
|
-
dir: @dir,
|
151
164
|
role: "combobox",
|
152
165
|
aria: {
|
153
166
|
autocomplete: "none",
|
@@ -159,8 +172,6 @@ module ShadcnPhlexcomponents
|
|
159
172
|
has_value: @value.present?.to_s,
|
160
173
|
action: <<~HEREDOC,
|
161
174
|
click->combobox#toggle
|
162
|
-
keydown.space->combobox#open
|
163
|
-
keydown.enter->combobox#open
|
164
175
|
keydown.down->combobox#open:prevent
|
165
176
|
HEREDOC
|
166
177
|
combobox_target: "trigger",
|
@@ -176,27 +187,44 @@ module ShadcnPhlexcomponents
|
|
176
187
|
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
|
177
188
|
data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
|
178
189
|
data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50
|
179
|
-
|
180
|
-
|
190
|
+
min-w-[8rem] origin-(--radix-popper-transform-origin)
|
191
|
+
rounded-md border shadow-md pointer-events-auto outline-none
|
181
192
|
HEREDOC
|
182
193
|
)
|
183
194
|
|
184
|
-
def initialize(
|
195
|
+
def initialize(
|
196
|
+
include_blank: false,
|
197
|
+
side: :bottom,
|
198
|
+
align: :center,
|
199
|
+
aria_id: nil,
|
200
|
+
search_error_text: nil,
|
201
|
+
search_empty_text: nil,
|
202
|
+
search_placeholder_text: nil,
|
203
|
+
**attributes
|
204
|
+
)
|
185
205
|
@include_blank = include_blank
|
186
|
-
@dir = dir
|
187
206
|
@side = side
|
188
207
|
@align = align
|
189
|
-
@
|
208
|
+
@search_error_text = search_error_text
|
209
|
+
@search_empty_text = search_empty_text
|
210
|
+
@search_placeholder_text = search_placeholder_text
|
190
211
|
@aria_id = aria_id
|
191
212
|
super(**attributes)
|
192
213
|
end
|
193
214
|
|
194
215
|
def view_template(&)
|
195
216
|
div(
|
196
|
-
|
217
|
+
style: { display: "none" },
|
218
|
+
class: "fixed top-0 left-0 w-max z-50",
|
197
219
|
data: { combobox_target: "contentContainer" },
|
198
220
|
) do
|
199
221
|
div(**@attributes) do
|
222
|
+
template do
|
223
|
+
ComboboxGroup do
|
224
|
+
ComboboxLabel { "" }
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
200
228
|
label(
|
201
229
|
class: "sr-only",
|
202
230
|
id: "#{@aria_id}-search-label",
|
@@ -224,19 +252,29 @@ module ShadcnPhlexcomponents
|
|
224
252
|
},
|
225
253
|
data: {
|
226
254
|
combobox_target: "searchInput",
|
227
|
-
action: "input->combobox#search",
|
255
|
+
action: "keydown->combobox#inputKeydown input->combobox#search",
|
228
256
|
},
|
229
257
|
)
|
230
258
|
end
|
231
259
|
|
232
|
-
div(class: "p-1 max-h-80 overflow-y-auto",
|
233
|
-
|
234
|
-
|
235
|
-
|
260
|
+
div(class: "p-1 max-h-80 overflow-y-auto", data: { combobox_target: "listContainer"}) do
|
261
|
+
ComboboxText(target: "empty") { @search_empty_text }
|
262
|
+
ComboboxText(target: "error") { @search_error_text }
|
263
|
+
ComboboxText(target: "loading") do
|
264
|
+
div(class: "flex justify-center", aria: { label: "Loading" }) do
|
265
|
+
icon("loader-circle", class: "animate-spin")
|
236
266
|
end
|
237
267
|
end
|
238
268
|
|
239
|
-
div(data: { combobox_target: "
|
269
|
+
div(id: "#{@aria_id}-list", data: { combobox_target: "list" }) do
|
270
|
+
if @include_blank
|
271
|
+
ComboboxItem(aria_id: @aria_id, value: "", class: "h-8") do
|
272
|
+
@include_blank.is_a?(String) ? @include_blank : ""
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
yield
|
277
|
+
end
|
240
278
|
end
|
241
279
|
end
|
242
280
|
end
|
@@ -245,7 +283,6 @@ module ShadcnPhlexcomponents
|
|
245
283
|
def default_attributes
|
246
284
|
{
|
247
285
|
id: "#{@aria_id}-content",
|
248
|
-
dir: @dir,
|
249
286
|
tabindex: -1,
|
250
287
|
role: "listbox",
|
251
288
|
aria: {
|
@@ -261,7 +298,7 @@ module ShadcnPhlexcomponents
|
|
261
298
|
combobox:click:outside->combobox#clickOutside
|
262
299
|
keydown.up->combobox#highlightItem:prevent
|
263
300
|
keydown.down->combobox#highlightItem:prevent
|
264
|
-
keydown.enter->combobox#select
|
301
|
+
keydown.enter->combobox#select:prevent
|
265
302
|
HEREDOC
|
266
303
|
},
|
267
304
|
}
|
@@ -280,14 +317,6 @@ module ShadcnPhlexcomponents
|
|
280
317
|
def view_template(&)
|
281
318
|
div(**@attributes, &)
|
282
319
|
end
|
283
|
-
|
284
|
-
def default_attributes
|
285
|
-
{
|
286
|
-
data: {
|
287
|
-
combobox_target: "label",
|
288
|
-
},
|
289
|
-
}
|
290
|
-
end
|
291
320
|
end
|
292
321
|
|
293
322
|
class ComboboxItem < Base
|
@@ -365,34 +394,35 @@ module ShadcnPhlexcomponents
|
|
365
394
|
end
|
366
395
|
end
|
367
396
|
|
368
|
-
class
|
369
|
-
class_variants(base: "bg-border pointer-events-none -mx-1 my-1 h-px")
|
370
|
-
|
371
|
-
def view_template(&)
|
372
|
-
div(**@attributes, &)
|
373
|
-
end
|
374
|
-
|
375
|
-
def default_attributes
|
376
|
-
{ aria: { hidden: "true" } }
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
class ComboboxEmpty < Base
|
397
|
+
class ComboboxText < Base
|
381
398
|
class_variants(base: "py-6 text-center text-sm hidden")
|
399
|
+
|
400
|
+
def initialize(target:, **attributes)
|
401
|
+
@target = target
|
402
|
+
super(**attributes)
|
403
|
+
end
|
382
404
|
|
383
405
|
def default_attributes
|
384
406
|
{
|
385
407
|
role: "presentation",
|
386
|
-
data: { combobox_target:
|
408
|
+
data: { combobox_target: @target },
|
387
409
|
}
|
388
410
|
end
|
389
411
|
|
390
412
|
def view_template(&)
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
413
|
+
div(**@attributes, &)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
class ComboboxSeparator < Base
|
418
|
+
class_variants(base: "bg-border pointer-events-none -mx-1 my-1 h-px")
|
419
|
+
|
420
|
+
def view_template(&)
|
421
|
+
div(**@attributes, &)
|
422
|
+
end
|
423
|
+
|
424
|
+
def default_attributes
|
425
|
+
{ aria: { hidden: "true" } }
|
396
426
|
end
|
397
427
|
end
|
398
428
|
end
|