shadcn_phlexcomponents 0.1.18 → 0.1.19

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.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +321 -23
  3. data/app/javascript/controllers/accordion_controller.js +101 -90
  4. data/app/javascript/controllers/alert_dialog_controller.js +5 -4
  5. data/app/javascript/controllers/avatar_controller.js +12 -11
  6. data/app/javascript/controllers/checkbox_controller.js +26 -26
  7. data/app/javascript/controllers/collapsible_controller.js +35 -36
  8. data/app/javascript/controllers/combobox_controller.js +262 -231
  9. data/app/javascript/controllers/command_controller.js +205 -184
  10. data/app/javascript/controllers/date_picker_controller.js +252 -253
  11. data/app/javascript/controllers/date_range_picker_controller.js +189 -200
  12. data/app/javascript/controllers/dialog_controller.js +79 -78
  13. data/app/javascript/controllers/dropdown_menu_controller.js +229 -208
  14. data/app/javascript/controllers/dropdown_menu_sub_controller.js +111 -97
  15. data/app/javascript/controllers/form_field_controller.js +17 -16
  16. data/app/javascript/controllers/hover_card_controller.js +69 -71
  17. data/app/javascript/controllers/loading_button_controller.js +11 -10
  18. data/app/javascript/controllers/popover_controller.js +85 -78
  19. data/app/javascript/controllers/progress_controller.js +12 -11
  20. data/app/javascript/controllers/radio_group_controller.js +75 -74
  21. data/app/javascript/controllers/select_controller.js +247 -232
  22. data/app/javascript/controllers/sidebar_controller.js +26 -27
  23. data/app/javascript/controllers/sidebar_trigger_controller.js +12 -9
  24. data/app/javascript/controllers/slider_controller.js +74 -74
  25. data/app/javascript/controllers/switch_controller.js +23 -23
  26. data/app/javascript/controllers/tabs_controller.js +61 -61
  27. data/app/javascript/controllers/theme_switcher_controller.js +28 -27
  28. data/app/javascript/controllers/toast_container_controller.js +45 -31
  29. data/app/javascript/controllers/toast_controller.js +19 -18
  30. data/app/javascript/controllers/toggle_controller.js +17 -17
  31. data/app/javascript/controllers/toggle_group_controller.js +17 -17
  32. data/app/javascript/controllers/tooltip_controller.js +75 -77
  33. data/app/javascript/shadcn_phlexcomponents.js +27 -60
  34. data/app/javascript/utils/command.js +390 -334
  35. data/app/javascript/utils/floating_ui.js +139 -107
  36. data/app/javascript/utils/index.js +253 -190
  37. data/app/typescript/controllers/accordion_controller.ts +2 -0
  38. data/app/typescript/controllers/alert_dialog_controller.ts +2 -0
  39. data/app/typescript/controllers/avatar_controller.ts +2 -0
  40. data/app/typescript/controllers/checkbox_controller.ts +2 -0
  41. data/app/typescript/controllers/collapsible_controller.ts +2 -0
  42. data/app/typescript/controllers/combobox_controller.ts +2 -0
  43. data/app/typescript/controllers/command_controller.ts +2 -0
  44. data/app/typescript/controllers/date_picker_controller.ts +2 -0
  45. data/app/typescript/controllers/date_range_picker_controller.ts +2 -0
  46. data/app/typescript/controllers/dialog_controller.ts +2 -0
  47. data/app/typescript/controllers/dropdown_menu_controller.ts +2 -0
  48. data/app/typescript/controllers/dropdown_menu_sub_controller.ts +2 -0
  49. data/app/typescript/controllers/form_field_controller.ts +2 -0
  50. data/app/typescript/controllers/hover_card_controller.ts +2 -0
  51. data/app/typescript/controllers/loading_button_controller.ts +2 -0
  52. data/app/typescript/controllers/popover_controller.ts +2 -0
  53. data/app/typescript/controllers/progress_controller.ts +2 -0
  54. data/app/typescript/controllers/radio_group_controller.ts +2 -0
  55. data/app/typescript/controllers/select_controller.ts +2 -0
  56. data/app/typescript/controllers/slider_controller.ts +2 -0
  57. data/app/typescript/controllers/switch_controller.ts +2 -0
  58. data/app/typescript/controllers/tabs_controller.ts +2 -0
  59. data/app/typescript/controllers/theme_switcher_controller.ts +2 -0
  60. data/app/typescript/controllers/toast_container_controller.ts +2 -0
  61. data/app/typescript/controllers/toast_controller.ts +2 -0
  62. data/app/typescript/controllers/toggle_controller.ts +2 -0
  63. data/app/typescript/controllers/toggle_group_controller.ts +2 -0
  64. data/app/typescript/controllers/tooltip_controller.ts +2 -0
  65. data/app/typescript/shadcn_phlexcomponents.ts +27 -61
  66. data/app/typescript/utils/index.ts +7 -0
  67. data/lib/install/upgrade_shadcn_phlexcomponents.rb +28 -0
  68. data/lib/shadcn_phlexcomponents/components/accordion.rb +55 -12
  69. data/lib/shadcn_phlexcomponents/components/alert.rb +35 -16
  70. data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +52 -12
  71. data/lib/shadcn_phlexcomponents/components/aspect_ratio.rb +33 -2
  72. data/lib/shadcn_phlexcomponents/components/avatar.rb +24 -7
  73. data/lib/shadcn_phlexcomponents/components/badge.rb +23 -18
  74. data/lib/shadcn_phlexcomponents/components/breadcrumb.rb +46 -6
  75. data/lib/shadcn_phlexcomponents/components/button.rb +32 -27
  76. data/lib/shadcn_phlexcomponents/components/card.rb +59 -10
  77. data/lib/shadcn_phlexcomponents/components/checkbox.rb +51 -30
  78. data/lib/shadcn_phlexcomponents/components/checkbox_group.rb +24 -4
  79. data/lib/shadcn_phlexcomponents/components/combobox.rb +212 -69
  80. data/lib/shadcn_phlexcomponents/components/command.rb +156 -52
  81. data/lib/shadcn_phlexcomponents/components/date_picker.rb +134 -48
  82. data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +20 -42
  83. data/lib/shadcn_phlexcomponents/components/dialog.rb +80 -26
  84. data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +74 -25
  85. data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +52 -24
  86. data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +1 -1
  87. data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +1 -1
  88. data/lib/shadcn_phlexcomponents/components/form/form_combobox.rb +1 -1
  89. data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +1 -1
  90. data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +1 -1
  91. data/lib/shadcn_phlexcomponents/components/form/form_error.rb +8 -1
  92. data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +3 -2
  93. data/lib/shadcn_phlexcomponents/components/form/form_hint.rb +8 -1
  94. data/lib/shadcn_phlexcomponents/components/form/form_input.rb +1 -1
  95. data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +1 -1
  96. data/lib/shadcn_phlexcomponents/components/form/form_select.rb +1 -1
  97. data/lib/shadcn_phlexcomponents/components/form/form_slider.rb +1 -1
  98. data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +1 -1
  99. data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +1 -1
  100. data/lib/shadcn_phlexcomponents/components/form.rb +22 -6
  101. data/lib/shadcn_phlexcomponents/components/hover_card.rb +48 -18
  102. data/lib/shadcn_phlexcomponents/components/input.rb +13 -8
  103. data/lib/shadcn_phlexcomponents/components/label.rb +9 -4
  104. data/lib/shadcn_phlexcomponents/components/link.rb +8 -1
  105. data/lib/shadcn_phlexcomponents/components/pagination.rb +34 -6
  106. data/lib/shadcn_phlexcomponents/components/popover.rb +43 -13
  107. data/lib/shadcn_phlexcomponents/components/progress.rb +37 -6
  108. data/lib/shadcn_phlexcomponents/components/radio_group.rb +41 -15
  109. data/lib/shadcn_phlexcomponents/components/select.rb +99 -42
  110. data/lib/shadcn_phlexcomponents/components/separator.rb +9 -4
  111. data/lib/shadcn_phlexcomponents/components/sheet.rb +87 -21
  112. data/lib/shadcn_phlexcomponents/components/skeleton.rb +8 -1
  113. data/lib/shadcn_phlexcomponents/components/switch.rb +45 -17
  114. data/lib/shadcn_phlexcomponents/components/table.rb +84 -17
  115. data/lib/shadcn_phlexcomponents/components/tabs.rb +36 -12
  116. data/lib/shadcn_phlexcomponents/components/textarea.rb +12 -7
  117. data/lib/shadcn_phlexcomponents/components/toast.rb +46 -20
  118. data/lib/shadcn_phlexcomponents/components/toast_container.rb +19 -14
  119. data/lib/shadcn_phlexcomponents/components/toggle.rb +28 -23
  120. data/lib/shadcn_phlexcomponents/components/tooltip.rb +49 -14
  121. data/lib/shadcn_phlexcomponents/configuration.rb +46 -0
  122. data/lib/shadcn_phlexcomponents/initializers/shadcn_phlexcomponents.rb +28 -0
  123. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  124. data/lib/shadcn_phlexcomponents.rb +12 -1
  125. data/lib/tasks/upgrade.rake +10 -0
  126. metadata +15 -14
  127. data/app/typescript/controllers/sidebar_controller.ts +0 -39
  128. data/app/typescript/controllers/sidebar_trigger_controller.ts +0 -21
@@ -2,7 +2,14 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class Progress < Base
5
- class_variants(base: "bg-primary/20 relative h-2 w-full overflow-hidden rounded-full")
5
+ class_variants(
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.progress&.dig(:root) ||
8
+ {
9
+ base: "bg-primary/20 relative h-2 w-full overflow-hidden rounded-full",
10
+ }
11
+ ),
12
+ )
6
13
 
7
14
  def initialize(value: 0, **attributes)
8
15
  @value = value
@@ -26,12 +33,36 @@ module ShadcnPhlexcomponents
26
33
 
27
34
  def view_template
28
35
  div(**@attributes) do
29
- div(
30
- class: "bg-primary h-full w-full flex-1 transition-all",
31
- style: "transform: translateX(-#{100 - @value}%)",
32
- data: { progress_target: "indicator" },
33
- )
36
+ ProgressIndicator(value: @value)
34
37
  end
35
38
  end
36
39
  end
40
+
41
+ class ProgressIndicator < Base
42
+ class_variants(
43
+ **(
44
+ ShadcnPhlexcomponents.configuration.progress&.dig(:indicator) ||
45
+ {
46
+ base: "bg-primary h-full w-full flex-1 transition-all",
47
+ }
48
+ ),
49
+ )
50
+
51
+ def initialize(value: nil, **attributes)
52
+ @value = value
53
+ super(**attributes)
54
+ end
55
+
56
+ def default_attributes
57
+ value = @value || 0
58
+ {
59
+ style: "transform: translateX(-#{100 - value}%)",
60
+ data: { progress_target: "indicator" },
61
+ }
62
+ end
63
+
64
+ def view_template
65
+ div(**@attributes)
66
+ end
67
+ end
37
68
  end
@@ -2,7 +2,14 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class RadioGroup < Base
5
- class_variants(base: "grid gap-3 outline-none")
5
+ class_variants(
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.radio_group&.dig(:root) ||
8
+ {
9
+ base: "grid gap-3 outline-none",
10
+ }
11
+ ),
12
+ )
6
13
 
7
14
  def initialize(name: nil, value: nil, dir: "ltr", include_hidden: true, **attributes)
8
15
  @name = name
@@ -87,12 +94,17 @@ module ShadcnPhlexcomponents
87
94
 
88
95
  class RadioGroupItem < Base
89
96
  class_variants(
90
- base: <<~HEREDOC,
91
- border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20
92
- dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4
93
- shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px]
94
- disabled:cursor-not-allowed disabled:opacity-50 relative
95
- HEREDOC
97
+ **(
98
+ ShadcnPhlexcomponents.configuration.radio_group&.dig(:item) ||
99
+ {
100
+ base: <<~HEREDOC,
101
+ border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20
102
+ dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4
103
+ shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px]
104
+ disabled:cursor-not-allowed disabled:opacity-50 relative
105
+ HEREDOC
106
+ }
107
+ ),
96
108
  )
97
109
 
98
110
  def initialize(name: nil, value: nil, checked: false, **attributes)
@@ -104,14 +116,7 @@ module ShadcnPhlexcomponents
104
116
 
105
117
  def view_template(&)
106
118
  button(**@attributes) do
107
- span(
108
- class: "relative flex items-center justify-center",
109
- data: {
110
- radio_group_target: "indicator",
111
- },
112
- ) do
113
- icon("circle", class: "fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2")
114
- end
119
+ RadioGroupItemIndicator()
115
120
 
116
121
  input(
117
122
  type: "radio",
@@ -152,4 +157,25 @@ module ShadcnPhlexcomponents
152
157
  }
153
158
  end
154
159
  end
160
+
161
+ class RadioGroupItemIndicator < Base
162
+ class_variants(
163
+ **(
164
+ ShadcnPhlexcomponents.configuration.radio_group&.dig(:item_indicator) ||
165
+ {
166
+ base: "relative flex items-center justify-center",
167
+ }
168
+ ),
169
+ )
170
+
171
+ def default_attributes
172
+ { data: { radio_group_target: "indicator" } }
173
+ end
174
+
175
+ def view_template(&)
176
+ span(**@attributes) do
177
+ icon("circle", class: "fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2")
178
+ end
179
+ end
180
+ end
155
181
  end
@@ -178,17 +178,22 @@ module ShadcnPhlexcomponents
178
178
 
179
179
  class SelectTrigger < Base
180
180
  class_variants(
181
- base: <<~HEREDOC,
182
- border-input [&_svg:not([class*='text-'])]:text-muted-foreground
183
- focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
184
- aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex items-center
185
- justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs
186
- transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50
187
- data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[select-target=triggerText]:line-clamp-1#{" "}
188
- *:data-[select-target=triggerText]:flex *:data-[select-target=triggerText]:items-center *:data-[select-target=triggerText]:gap-2
189
- [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
190
- data-[placeholder]:data-[has-value=false]:text-muted-foreground w-full
191
- HEREDOC
181
+ **(
182
+ ShadcnPhlexcomponents.configuration.select&.dig(:trigger) ||
183
+ {
184
+ base: <<~HEREDOC,
185
+ border-input [&_svg:not([class*='text-'])]:text-muted-foreground
186
+ focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
187
+ aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex items-center
188
+ justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs
189
+ transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50
190
+ data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[select-target=triggerText]:line-clamp-1#{" "}
191
+ *:data-[select-target=triggerText]:flex *:data-[select-target=triggerText]:items-center *:data-[select-target=triggerText]:gap-2
192
+ [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
193
+ data-[placeholder]:data-[has-value=false]:text-muted-foreground w-full
194
+ HEREDOC
195
+ }
196
+ ),
192
197
  )
193
198
 
194
199
  def initialize(id: nil, value: nil, placeholder: nil, aria_id: nil, **attributes)
@@ -236,14 +241,19 @@ module ShadcnPhlexcomponents
236
241
 
237
242
  class SelectContent < Base
238
243
  class_variants(
239
- base: <<~HEREDOC,
240
- bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out
241
- data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
242
- data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
243
- data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50
244
- max-h-(--radix-popper-available-height) min-w-[8rem] origin-(--radix-popper-transform-origin)
245
- overflow-x-hidden overflow-y-auto rounded-md border shadow-md p-1 pointer-events-auto outline-none
246
- HEREDOC
244
+ **(
245
+ ShadcnPhlexcomponents.configuration.select&.dig(:content) ||
246
+ {
247
+ base: <<~HEREDOC,
248
+ bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out
249
+ data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
250
+ data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
251
+ data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50
252
+ max-h-(--radix-popper-available-height) min-w-[8rem] origin-(--radix-popper-transform-origin)
253
+ overflow-x-hidden overflow-y-auto rounded-md border shadow-md p-1 pointer-events-auto outline-none
254
+ HEREDOC
255
+ }
256
+ ),
247
257
  )
248
258
 
249
259
  def initialize(include_blank: false, native: false, side: :bottom, align: :center, aria_id: nil, **attributes)
@@ -256,11 +266,7 @@ module ShadcnPhlexcomponents
256
266
  end
257
267
 
258
268
  def view_template(&)
259
- div(
260
- style: { display: "none" },
261
- class: "fixed top-0 left-0 w-max z-50",
262
- data: { select_target: "contentContainer" },
263
- ) do
269
+ SelectContentContainer do
264
270
  div(**@attributes) do
265
271
  if @include_blank && !@native
266
272
  SelectItem(aria_id: @aria_id, value: "", class: "h-8") do
@@ -299,13 +305,14 @@ module ShadcnPhlexcomponents
299
305
 
300
306
  class SelectLabel < Base
301
307
  class_variants(
302
- base: "text-muted-foreground px-2 py-1.5 text-xs",
308
+ **(
309
+ ShadcnPhlexcomponents.configuration.select&.dig(:label) ||
310
+ {
311
+ base: "text-muted-foreground px-2 py-1.5 text-xs",
312
+ }
313
+ ),
303
314
  )
304
315
 
305
- def initialize(**attributes)
306
- super(**attributes)
307
- end
308
-
309
316
  def view_template(&)
310
317
  div(**@attributes, &)
311
318
  end
@@ -313,13 +320,18 @@ module ShadcnPhlexcomponents
313
320
 
314
321
  class SelectItem < Base
315
322
  class_variants(
316
- base: <<~HEREDOC,
317
- focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground
318
- relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm
319
- outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50
320
- [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
321
- *:[span]:last:items-center *:[span]:last:gap-2 group/item
322
- HEREDOC
323
+ **(
324
+ ShadcnPhlexcomponents.configuration.select&.dig(:item) ||
325
+ {
326
+ base: <<~HEREDOC,
327
+ focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground
328
+ relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm
329
+ outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50
330
+ [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
331
+ *:[span]:last:items-center *:[span]:last:gap-2 group/item
332
+ HEREDOC
333
+ }
334
+ ),
323
335
  )
324
336
 
325
337
  def initialize(value: nil, disabled: false, aria_id: nil, **attributes)
@@ -333,11 +345,7 @@ module ShadcnPhlexcomponents
333
345
  def view_template(&)
334
346
  div(**@attributes) do
335
347
  span(id: @aria_labelledby, &)
336
-
337
- span(class: "absolute right-2 h-3.5 w-3.5 items-center hidden justify-center
338
- group-aria-[selected=true]/item:flex group-data-[value='']/item:hidden") do
339
- icon("check", class: "size-4")
340
- end
348
+ SelectItemIndicator()
341
349
  end
342
350
  end
343
351
 
@@ -393,7 +401,14 @@ module ShadcnPhlexcomponents
393
401
  end
394
402
 
395
403
  class SelectSeparator < Base
396
- class_variants(base: "bg-border pointer-events-none -mx-1 my-1 h-px")
404
+ class_variants(
405
+ **(
406
+ ShadcnPhlexcomponents.configuration.select&.dig(:separator) ||
407
+ {
408
+ base: "bg-border pointer-events-none -mx-1 my-1 h-px",
409
+ }
410
+ ),
411
+ )
397
412
 
398
413
  def view_template(&)
399
414
  div(**@attributes, &)
@@ -403,4 +418,46 @@ module ShadcnPhlexcomponents
403
418
  { aria: { hidden: "true" } }
404
419
  end
405
420
  end
421
+
422
+ class SelectContentContainer < Base
423
+ class_variants(
424
+ **(
425
+ ShadcnPhlexcomponents.configuration.select&.dig(:content_container) ||
426
+ {
427
+ base: "fixed top-0 left-0 w-max z-50",
428
+ }
429
+ ),
430
+ )
431
+
432
+ def default_attributes
433
+ {
434
+ style: { display: "none" },
435
+ data: { select_target: "contentContainer" },
436
+ }
437
+ end
438
+
439
+ def view_template(&)
440
+ div(**@attributes, &)
441
+ end
442
+ end
443
+
444
+ class SelectItemIndicator < Base
445
+ class_variants(
446
+ **(
447
+ ShadcnPhlexcomponents.configuration.select&.dig(:item_indicator) ||
448
+ {
449
+ base: <<~HEREDOC,
450
+ absolute right-2 h-3.5 w-3.5 items-center hidden justify-center#{" "}
451
+ group-aria-[selected=true]/item:flex group-data-[value='']/item:hidden#{" "}
452
+ HEREDOC
453
+ }
454
+ ),
455
+ )
456
+
457
+ def view_template
458
+ span(**@attributes) do
459
+ icon("check", class: "size-4")
460
+ end
461
+ end
462
+ end
406
463
  end
@@ -3,10 +3,15 @@
3
3
  module ShadcnPhlexcomponents
4
4
  class Separator < Base
5
5
  class_variants(
6
- base: <<~HEREDOC,
7
- bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full
8
- data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px
9
- HEREDOC
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.separator ||
8
+ {
9
+ base: <<~HEREDOC,
10
+ bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full
11
+ data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px
12
+ HEREDOC
13
+ }
14
+ ),
10
15
  )
11
16
 
12
17
  def initialize(orientation: :horizontal, **attributes)
@@ -2,7 +2,14 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class Sheet < Base
5
- class_variants(base: "inline-flex max-w-fit")
5
+ class_variants(
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.sheet&.dig(:root) ||
8
+ {
9
+ base: "inline-flex max-w-fit",
10
+ }
11
+ ),
12
+ )
6
13
 
7
14
  def initialize(open: false, **attributes)
8
15
  @open = open
@@ -97,22 +104,27 @@ module ShadcnPhlexcomponents
97
104
 
98
105
  class SheetContent < Base
99
106
  class_variants(
100
- base: <<~HEREDOC,
101
- bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4
102
- shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500
103
- pointer-events-auto outline-none
104
- HEREDOC
105
- variants: {
106
- side: {
107
- top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
108
- left: "h-screen data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 w-3/4 border-r sm:max-w-sm",
109
- right: "h-screen data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 w-3/4 border-l sm:max-w-sm",
110
- bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
111
- },
112
- },
113
- defaults: {
114
- side: :right,
115
- },
107
+ **(
108
+ ShadcnPhlexcomponents.configuration.sheet&.dig(:content) ||
109
+ {
110
+ base: <<~HEREDOC,
111
+ bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4
112
+ shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500
113
+ pointer-events-auto outline-none
114
+ HEREDOC
115
+ variants: {
116
+ side: {
117
+ top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
118
+ left: "h-screen data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 w-3/4 border-r sm:max-w-sm",
119
+ right: "h-screen data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 w-3/4 border-l sm:max-w-sm",
120
+ bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
121
+ },
122
+ },
123
+ defaults: {
124
+ side: :right,
125
+ },
126
+ }
127
+ ),
116
128
  )
117
129
 
118
130
  def initialize(side: :right, aria_id: nil, **attributes)
@@ -157,7 +169,14 @@ module ShadcnPhlexcomponents
157
169
  end
158
170
 
159
171
  class SheetHeader < Base
160
- class_variants(base: "flex flex-col gap-1.5 p-4")
172
+ class_variants(
173
+ **(
174
+ ShadcnPhlexcomponents.configuration.sheet&.dig(:header) ||
175
+ {
176
+ base: "flex flex-col gap-1.5 p-4",
177
+ }
178
+ ),
179
+ )
161
180
 
162
181
  def view_template(&)
163
182
  div(**@attributes, &)
@@ -165,7 +184,14 @@ module ShadcnPhlexcomponents
165
184
  end
166
185
 
167
186
  class SheetTitle < Base
168
- class_variants(base: "text-foreground font-semibold")
187
+ class_variants(
188
+ **(
189
+ ShadcnPhlexcomponents.configuration.sheet&.dig(:title) ||
190
+ {
191
+ base: "text-foreground font-semibold",
192
+ }
193
+ ),
194
+ )
169
195
 
170
196
  def initialize(aria_id: nil, **attributes)
171
197
  @aria_id = aria_id
@@ -184,7 +210,14 @@ module ShadcnPhlexcomponents
184
210
  end
185
211
 
186
212
  class SheetDescription < Base
187
- class_variants(base: "text-muted-foreground text-sm")
213
+ class_variants(
214
+ **(
215
+ ShadcnPhlexcomponents.configuration.sheet&.dig(:description) ||
216
+ {
217
+ base: "text-muted-foreground text-sm",
218
+ }
219
+ ),
220
+ )
188
221
 
189
222
  def initialize(aria_id: nil, **attributes)
190
223
  @aria_id = aria_id
@@ -203,7 +236,14 @@ module ShadcnPhlexcomponents
203
236
  end
204
237
 
205
238
  class SheetFooter < Base
206
- class_variants(base: "mt-auto flex flex-col gap-2 p-4")
239
+ class_variants(
240
+ **(
241
+ ShadcnPhlexcomponents.configuration.sheet&.dig(:footer) ||
242
+ {
243
+ base: "mt-auto flex flex-col gap-2 p-4",
244
+ }
245
+ ),
246
+ )
207
247
 
208
248
  def view_template(&)
209
249
  div(**@attributes, &)
@@ -240,4 +280,30 @@ module ShadcnPhlexcomponents
240
280
  }
241
281
  end
242
282
  end
283
+
284
+ class SheetCloseIcon < Base
285
+ class_variants(
286
+ **(
287
+ ShadcnPhlexcomponents.configuration.sheet&.dig(:close_icon) ||
288
+ {
289
+ base: <<~HEREDOC,
290
+ ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs
291
+ opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden
292
+ disabled:pointer-events-none
293
+ HEREDOC
294
+ }
295
+ ),
296
+ )
297
+
298
+ def default_attributes
299
+ { data: { action: "click->dialog#close" } }
300
+ end
301
+
302
+ def view_template
303
+ button(**@attributes) do
304
+ icon("x", class: "size-4")
305
+ span(class: "sr-only") { "close" }
306
+ end
307
+ end
308
+ end
243
309
  end
@@ -2,7 +2,14 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class Skeleton < Base
5
- class_variants(base: "bg-accent animate-pulse rounded-md")
5
+ class_variants(
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.skeleton ||
8
+ {
9
+ base: "bg-accent animate-pulse rounded-md",
10
+ }
11
+ ),
12
+ )
6
13
 
7
14
  def view_template(&)
8
15
  div(**@attributes, &)
@@ -3,12 +3,17 @@
3
3
  module ShadcnPhlexcomponents
4
4
  class Switch < Base
5
5
  class_variants(
6
- base: <<~HEREDOC,
7
- peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring
8
- focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem]
9
- w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all
10
- outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 relative
11
- HEREDOC
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.switch&.dig(:root) ||
8
+ {
9
+ base: <<~HEREDOC,
10
+ peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring
11
+ focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem]
12
+ w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all
13
+ outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 relative
14
+ HEREDOC
15
+ }
16
+ ),
12
17
  )
13
18
 
14
19
  def initialize(name: nil, value: "1", unchecked_value: "0", checked: false, include_hidden: true, disabled: false, **attributes)
@@ -23,17 +28,7 @@ module ShadcnPhlexcomponents
23
28
 
24
29
  def view_template(&)
25
30
  button(**@attributes) do
26
- span(
27
- class: <<~HEREDOC,
28
- bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground
29
- pointer-events-none block size-4 rounded-full ring-0 transition-transform
30
- data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0
31
- HEREDOC
32
- data: {
33
- switch_target: "thumb",
34
- state: @checked ? "checked" : "unchecked",
35
- },
36
- )
31
+ SwitchThumb(checked: @checked)
37
32
 
38
33
  if @include_hidden
39
34
  input(name: @name, type: "hidden", value: @unchecked_value, autocomplete: "off")
@@ -72,4 +67,37 @@ module ShadcnPhlexcomponents
72
67
  }
73
68
  end
74
69
  end
70
+
71
+ class SwitchThumb < Base
72
+ class_variants(
73
+ **(
74
+ ShadcnPhlexcomponents.configuration.switch&.dig(:thumb) ||
75
+ {
76
+ base: <<~HEREDOC,
77
+ bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground
78
+ pointer-events-none block size-4 rounded-full ring-0 transition-transform
79
+ data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0
80
+ HEREDOC
81
+ }
82
+ ),
83
+ )
84
+
85
+ def initialize(checked: false, **attributes)
86
+ @checked = checked
87
+ super(**attributes)
88
+ end
89
+
90
+ def default_attributes
91
+ {
92
+ data: {
93
+ switch_target: "thumb",
94
+ state: @checked ? "checked" : "unchecked",
95
+ },
96
+ }
97
+ end
98
+
99
+ def view_template
100
+ span(**@attributes)
101
+ end
102
+ end
75
103
  end