shadcn_phlexcomponents 0.1.17 → 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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +321 -23
  3. data/app/javascript/controllers/accordion_controller.js +1 -0
  4. data/app/javascript/controllers/alert_dialog_controller.js +1 -0
  5. data/app/javascript/controllers/avatar_controller.js +1 -0
  6. data/app/javascript/controllers/checkbox_controller.js +1 -0
  7. data/app/javascript/controllers/collapsible_controller.js +1 -0
  8. data/app/javascript/controllers/combobox_controller.js +1 -1
  9. data/app/javascript/controllers/command_controller.js +1 -0
  10. data/app/javascript/controllers/date_picker_controller.js +21 -5
  11. data/app/javascript/controllers/date_range_picker_controller.js +1 -0
  12. data/app/javascript/controllers/dialog_controller.js +1 -0
  13. data/app/javascript/controllers/dropdown_menu_controller.js +1 -0
  14. data/app/javascript/controllers/dropdown_menu_sub_controller.js +1 -0
  15. data/app/javascript/controllers/form_field_controller.js +1 -0
  16. data/app/javascript/controllers/hover_card_controller.js +1 -0
  17. data/app/javascript/controllers/loading_button_controller.js +1 -0
  18. data/app/javascript/controllers/popover_controller.js +1 -0
  19. data/app/javascript/controllers/progress_controller.js +1 -0
  20. data/app/javascript/controllers/radio_group_controller.js +1 -0
  21. data/app/javascript/controllers/select_controller.js +1 -0
  22. data/app/javascript/controllers/slider_controller.js +1 -0
  23. data/app/javascript/controllers/switch_controller.js +1 -0
  24. data/app/javascript/controllers/tabs_controller.js +1 -0
  25. data/app/javascript/controllers/theme_switcher_controller.js +1 -0
  26. data/app/javascript/controllers/toast_container_controller.js +1 -0
  27. data/app/javascript/controllers/toast_controller.js +1 -0
  28. data/app/javascript/controllers/toggle_controller.js +1 -0
  29. data/app/javascript/controllers/toggle_group_controller.js +1 -0
  30. data/app/javascript/controllers/tooltip_controller.js +2 -1
  31. data/app/javascript/shadcn_phlexcomponents.js +27 -60
  32. data/app/javascript/utils/command.js +0 -2
  33. data/app/javascript/utils/floating_ui.js +10 -17
  34. data/app/stylesheets/date_picker.css +1 -1
  35. data/app/stylesheets/shadcn_phlexcomponents.css +173 -0
  36. data/app/typescript/controllers/accordion_controller.ts +2 -0
  37. data/app/typescript/controllers/alert_dialog_controller.ts +2 -0
  38. data/app/typescript/controllers/avatar_controller.ts +2 -0
  39. data/app/typescript/controllers/checkbox_controller.ts +2 -0
  40. data/app/typescript/controllers/collapsible_controller.ts +2 -0
  41. data/app/typescript/controllers/combobox_controller.ts +2 -1
  42. data/app/typescript/controllers/command_controller.ts +2 -0
  43. data/app/typescript/controllers/date_picker_controller.ts +27 -7
  44. data/app/typescript/controllers/date_range_picker_controller.ts +2 -0
  45. data/app/typescript/controllers/dialog_controller.ts +2 -0
  46. data/app/typescript/controllers/dropdown_menu_controller.ts +2 -0
  47. data/app/typescript/controllers/dropdown_menu_sub_controller.ts +2 -0
  48. data/app/typescript/controllers/form_field_controller.ts +2 -0
  49. data/app/typescript/controllers/hover_card_controller.ts +2 -0
  50. data/app/typescript/controllers/loading_button_controller.ts +2 -0
  51. data/app/typescript/controllers/popover_controller.ts +2 -0
  52. data/app/typescript/controllers/progress_controller.ts +2 -0
  53. data/app/typescript/controllers/radio_group_controller.ts +2 -0
  54. data/app/typescript/controllers/select_controller.ts +2 -0
  55. data/app/typescript/controllers/slider_controller.ts +2 -0
  56. data/app/typescript/controllers/switch_controller.ts +2 -0
  57. data/app/typescript/controllers/tabs_controller.ts +2 -0
  58. data/app/typescript/controllers/theme_switcher_controller.ts +2 -0
  59. data/app/typescript/controllers/toast_container_controller.ts +2 -0
  60. data/app/typescript/controllers/toast_controller.ts +2 -0
  61. data/app/typescript/controllers/toggle_controller.ts +2 -0
  62. data/app/typescript/controllers/toggle_group_controller.ts +2 -0
  63. data/app/typescript/controllers/tooltip_controller.ts +3 -1
  64. data/app/typescript/shadcn_phlexcomponents.ts +27 -61
  65. data/app/typescript/utils/command.ts +0 -2
  66. data/app/typescript/utils/floating_ui.ts +11 -20
  67. data/app/typescript/utils/index.ts +1 -1
  68. data/lib/install/upgrade_shadcn_phlexcomponents.rb +28 -0
  69. data/lib/shadcn_phlexcomponents/components/accordion.rb +56 -13
  70. data/lib/shadcn_phlexcomponents/components/alert.rb +35 -16
  71. data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +58 -18
  72. data/lib/shadcn_phlexcomponents/components/aspect_ratio.rb +33 -2
  73. data/lib/shadcn_phlexcomponents/components/avatar.rb +24 -7
  74. data/lib/shadcn_phlexcomponents/components/badge.rb +23 -18
  75. data/lib/shadcn_phlexcomponents/components/base.rb +2 -2
  76. data/lib/shadcn_phlexcomponents/components/breadcrumb.rb +46 -6
  77. data/lib/shadcn_phlexcomponents/components/button.rb +32 -27
  78. data/lib/shadcn_phlexcomponents/components/card.rb +59 -10
  79. data/lib/shadcn_phlexcomponents/components/checkbox.rb +51 -30
  80. data/lib/shadcn_phlexcomponents/components/checkbox_group.rb +24 -4
  81. data/lib/shadcn_phlexcomponents/components/combobox.rb +224 -81
  82. data/lib/shadcn_phlexcomponents/components/command.rb +167 -63
  83. data/lib/shadcn_phlexcomponents/components/date_picker.rb +140 -48
  84. data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +26 -44
  85. data/lib/shadcn_phlexcomponents/components/dialog.rb +86 -32
  86. data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +74 -25
  87. data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +52 -24
  88. data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +1 -1
  89. data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +1 -1
  90. data/lib/shadcn_phlexcomponents/components/form/form_combobox.rb +1 -1
  91. data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +1 -1
  92. data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +1 -1
  93. data/lib/shadcn_phlexcomponents/components/form/form_error.rb +8 -1
  94. data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +3 -2
  95. data/lib/shadcn_phlexcomponents/components/form/form_hint.rb +8 -1
  96. data/lib/shadcn_phlexcomponents/components/form/form_input.rb +1 -1
  97. data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +1 -1
  98. data/lib/shadcn_phlexcomponents/components/form/form_select.rb +1 -1
  99. data/lib/shadcn_phlexcomponents/components/form/form_slider.rb +1 -1
  100. data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +1 -1
  101. data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +1 -1
  102. data/lib/shadcn_phlexcomponents/components/form.rb +22 -6
  103. data/lib/shadcn_phlexcomponents/components/hover_card.rb +48 -18
  104. data/lib/shadcn_phlexcomponents/components/input.rb +13 -8
  105. data/lib/shadcn_phlexcomponents/components/label.rb +9 -4
  106. data/lib/shadcn_phlexcomponents/components/link.rb +8 -1
  107. data/lib/shadcn_phlexcomponents/components/pagination.rb +34 -6
  108. data/lib/shadcn_phlexcomponents/components/popover.rb +43 -13
  109. data/lib/shadcn_phlexcomponents/components/progress.rb +37 -6
  110. data/lib/shadcn_phlexcomponents/components/radio_group.rb +41 -15
  111. data/lib/shadcn_phlexcomponents/components/select.rb +99 -42
  112. data/lib/shadcn_phlexcomponents/components/separator.rb +9 -4
  113. data/lib/shadcn_phlexcomponents/components/sheet.rb +94 -28
  114. data/lib/shadcn_phlexcomponents/components/skeleton.rb +8 -1
  115. data/lib/shadcn_phlexcomponents/components/switch.rb +45 -17
  116. data/lib/shadcn_phlexcomponents/components/table.rb +84 -17
  117. data/lib/shadcn_phlexcomponents/components/tabs.rb +36 -12
  118. data/lib/shadcn_phlexcomponents/components/textarea.rb +12 -7
  119. data/lib/shadcn_phlexcomponents/components/toast.rb +46 -20
  120. data/lib/shadcn_phlexcomponents/components/toast_container.rb +19 -14
  121. data/lib/shadcn_phlexcomponents/components/toggle.rb +29 -24
  122. data/lib/shadcn_phlexcomponents/components/tooltip.rb +49 -14
  123. data/lib/shadcn_phlexcomponents/configuration.rb +46 -0
  124. data/lib/shadcn_phlexcomponents/initializers/shadcn_phlexcomponents.rb +28 -0
  125. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  126. data/lib/shadcn_phlexcomponents.rb +12 -1
  127. data/lib/tasks/upgrade.rake +10 -0
  128. metadata +16 -14
  129. data/app/typescript/controllers/sidebar_controller.ts +0 -39
  130. data/app/typescript/controllers/sidebar_trigger_controller.ts +0 -21
@@ -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
@@ -42,15 +49,15 @@ module ShadcnPhlexcomponents
42
49
  {
43
50
  data: {
44
51
  controller: "dialog",
45
- dialog_is_open_value: @open.to_s
46
- }
47
- }
52
+ dialog_is_open_value: @open.to_s,
53
+ },
54
+ }
48
55
  end
49
56
 
50
57
  def view_template(&)
51
58
  div(**@attributes) do
52
59
  overlay("dialog")
53
-
60
+
54
61
  yield
55
62
  end
56
63
  end
@@ -71,10 +78,10 @@ module ShadcnPhlexcomponents
71
78
  expanded: false,
72
79
  controls: "#{@aria_id}-content",
73
80
  },
74
- data: {
81
+ data: {
75
82
  as_child: @as_child.to_s,
76
83
  dialog_target: "trigger",
77
- action: "click->dialog#open"
84
+ action: "click->dialog#open",
78
85
  },
79
86
  }
80
87
  end
@@ -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)
@@ -150,14 +162,21 @@ module ShadcnPhlexcomponents
150
162
  },
151
163
  data: {
152
164
  state: "closed",
153
- dialog_target: "content"
165
+ dialog_target: "content",
154
166
  },
155
167
  }
156
168
  end
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
@@ -2,19 +2,20 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class Table < Base
5
- class_variants(base: "w-full caption-bottom text-sm")
5
+ class_variants(
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.table&.dig(:root) ||
8
+ {
9
+ base: "w-full caption-bottom text-sm",
10
+ }
11
+ ),
12
+ )
6
13
 
7
14
  def initialize(**attributes)
8
15
  @columns = []
9
16
  super(**attributes)
10
17
  end
11
18
 
12
- def view_template(&)
13
- div(class: "relative w-full overflow-x-auto") do
14
- table(**@attributes, &)
15
- end
16
- end
17
-
18
19
  def caption(**attributes, &)
19
20
  TableCaption(**attributes, &)
20
21
  end
@@ -73,10 +74,23 @@ module ShadcnPhlexcomponents
73
74
  @columns << { header:, head_class:, cell_class:, content: }
74
75
  nil
75
76
  end
77
+
78
+ def view_template(&)
79
+ TableContainer do
80
+ table(**@attributes, &)
81
+ end
82
+ end
76
83
  end
77
84
 
78
85
  class TableCaption < Base
79
- class_variants(base: "text-muted-foreground mt-4 text-sm")
86
+ class_variants(
87
+ **(
88
+ ShadcnPhlexcomponents.configuration.table&.dig(:caption) ||
89
+ {
90
+ base: "text-muted-foreground mt-4 text-sm",
91
+ }
92
+ ),
93
+ )
80
94
 
81
95
  def view_template(&)
82
96
  caption(**@attributes, &)
@@ -84,7 +98,14 @@ module ShadcnPhlexcomponents
84
98
  end
85
99
 
86
100
  class TableHeader < Base
87
- class_variants(base: "[&_tr]:border-b")
101
+ class_variants(
102
+ **(
103
+ ShadcnPhlexcomponents.configuration.table&.dig(:header) ||
104
+ {
105
+ base: "[&_tr]:border-b",
106
+ }
107
+ ),
108
+ )
88
109
 
89
110
  def view_template(&)
90
111
  thead(**@attributes, &)
@@ -92,7 +113,14 @@ module ShadcnPhlexcomponents
92
113
  end
93
114
 
94
115
  class TableRow < Base
95
- class_variants(base: "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors")
116
+ class_variants(
117
+ **(
118
+ ShadcnPhlexcomponents.configuration.table&.dig(:row) ||
119
+ {
120
+ base: "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
121
+ }
122
+ ),
123
+ )
96
124
 
97
125
  def view_template(&)
98
126
  tr(**@attributes, &)
@@ -101,10 +129,15 @@ module ShadcnPhlexcomponents
101
129
 
102
130
  class TableHead < Base
103
131
  class_variants(
104
- base: <<~HEREDOC,
105
- text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0
106
- [&>[role=checkbox]]:translate-y-[2px]"
107
- HEREDOC
132
+ **(
133
+ ShadcnPhlexcomponents.configuration.table&.dig(:head) ||
134
+ {
135
+ base: <<~HEREDOC,
136
+ text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0
137
+ [&>[role=checkbox]]:translate-y-[2px]"
138
+ HEREDOC
139
+ }
140
+ ),
108
141
  )
109
142
 
110
143
  def view_template(&)
@@ -113,7 +146,14 @@ module ShadcnPhlexcomponents
113
146
  end
114
147
 
115
148
  class TableBody < Base
116
- class_variants(base: "[&_tr:last-child]:border-0")
149
+ class_variants(
150
+ **(
151
+ ShadcnPhlexcomponents.configuration.table&.dig(:body) ||
152
+ {
153
+ base: "[&_tr:last-child]:border-0",
154
+ }
155
+ ),
156
+ )
117
157
 
118
158
  def view_template(&)
119
159
  tbody(**@attributes, &)
@@ -122,7 +162,12 @@ module ShadcnPhlexcomponents
122
162
 
123
163
  class TableCell < Base
124
164
  class_variants(
125
- base: "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
165
+ **(
166
+ ShadcnPhlexcomponents.configuration.table&.dig(:cell) ||
167
+ {
168
+ base: "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
169
+ }
170
+ ),
126
171
  )
127
172
 
128
173
  def view_template(&)
@@ -131,10 +176,32 @@ module ShadcnPhlexcomponents
131
176
  end
132
177
 
133
178
  class TableFooter < Base
134
- class_variants(base: "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0")
179
+ class_variants(
180
+ **(
181
+ ShadcnPhlexcomponents.configuration.table&.dig(:footer) ||
182
+ {
183
+ base: "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
184
+ }
185
+ ),
186
+ )
135
187
 
136
188
  def view_template(&)
137
189
  tfoot(**@attributes, &)
138
190
  end
139
191
  end
192
+
193
+ class TableContainer < Base
194
+ class_variants(
195
+ **(
196
+ ShadcnPhlexcomponents.configuration.table&.dig(:container) ||
197
+ {
198
+ base: "relative w-full overflow-x-auto",
199
+ }
200
+ ),
201
+ )
202
+
203
+ def view_template(&)
204
+ div(**@attributes, &)
205
+ end
206
+ end
140
207
  end