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 Combobox < Base
5
- class_variants(base: "w-full")
5
+ class_variants(
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:root) ||
8
+ {
9
+ base: "w-full",
10
+ }
11
+ ),
12
+ )
6
13
 
7
14
  def initialize(
8
15
  id: nil,
@@ -124,15 +131,20 @@ module ShadcnPhlexcomponents
124
131
 
125
132
  class ComboboxTrigger < Base
126
133
  class_variants(
127
- base: <<~HEREDOC,
128
- border-input [&_svg:not([class*='text-'])]:text-muted-foreground
129
- focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
130
- aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex items-center
131
- justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs
132
- transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50
133
- h-9 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
134
- data-[placeholder]:data-[has-value=false]:text-muted-foreground w-full disabled:dark:hover:bg-input/30
135
- HEREDOC
134
+ **(
135
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:trigger) ||
136
+ {
137
+ base: <<~HEREDOC,
138
+ border-input [&_svg:not([class*='text-'])]:text-muted-foreground
139
+ focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
140
+ aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex items-center
141
+ justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs
142
+ transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50
143
+ h-9 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
144
+ data-[placeholder]:data-[has-value=false]:text-muted-foreground w-full disabled:dark:hover:bg-input/30
145
+ HEREDOC
146
+ }
147
+ ),
136
148
  )
137
149
 
138
150
  def initialize(id: nil, value: nil, placeholder: nil, aria_id: nil, **attributes)
@@ -145,9 +157,7 @@ module ShadcnPhlexcomponents
145
157
 
146
158
  def view_template
147
159
  button(**@attributes) do
148
- span(class: "pointer-events-none line-clamp-1 flex items-center gap-2", data: { combobox_target: "triggerText" }) do
149
- @value || @placeholder
150
- end
160
+ ComboboxTriggerText(value: @value, placeholder: @placeholder)
151
161
 
152
162
  icon("chevron-down", class: "size-4 opacity-50 text-foreground")
153
163
  end
@@ -178,14 +188,19 @@ module ShadcnPhlexcomponents
178
188
 
179
189
  class ComboboxContent < Base
180
190
  class_variants(
181
- base: <<~HEREDOC,
182
- bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out
183
- data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
184
- data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
185
- data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50
186
- min-w-[8rem] origin-(--radix-popper-transform-origin)
187
- rounded-md border shadow-md pointer-events-auto outline-none
188
- HEREDOC
191
+ **(
192
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:content) ||
193
+ {
194
+ base: <<~HEREDOC,
195
+ bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out
196
+ data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
197
+ data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2
198
+ data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50
199
+ min-w-[8rem] origin-(--radix-popper-transform-origin)
200
+ rounded-md border shadow-md pointer-events-auto outline-none
201
+ HEREDOC
202
+ }
203
+ ),
189
204
  )
190
205
 
191
206
  def initialize(
@@ -209,11 +224,7 @@ module ShadcnPhlexcomponents
209
224
  end
210
225
 
211
226
  def view_template(&)
212
- div(
213
- style: { display: "none" },
214
- class: "fixed top-0 left-0 w-max z-50",
215
- data: { combobox_target: "contentContainer" },
216
- ) do
227
+ ComboboxContentContainer do
217
228
  div(**@attributes) do
218
229
  template do
219
230
  ComboboxGroup do
@@ -227,33 +238,12 @@ module ShadcnPhlexcomponents
227
238
  for: "#{@aria_id}-search",
228
239
  ) { @search_placeholder_text }
229
240
 
230
- div(class: "flex h-9 items-center gap-2 border-b px-3") do
241
+ ComboboxSearchInputContainer do
231
242
  icon("search", class: "size-4 shrink-0 opacity-50")
232
-
233
- input(
234
- class: "placeholder:text-muted-foreground flex w-full rounded-md bg-transparent py-3 text-sm
235
- outline-hidden disabled:cursor-not-allowed disabled:opacity-50 h-9",
236
- id: "#{@aria_id}-search",
237
- placeholder: @search_placeholder_text,
238
- type: :text,
239
- autocomplete: "off",
240
- autocorrect: "off",
241
- role: "combobox",
242
- spellcheck: "false",
243
- aria: {
244
- autocomplete: "list",
245
- expanded: "false",
246
- controls: "#{@aria_id}-list",
247
- labelledby: "#{@aria_id}-search-label",
248
- },
249
- data: {
250
- combobox_target: "searchInput",
251
- action: "keydown->combobox#inputKeydown input->combobox#search",
252
- },
253
- )
243
+ ComboboxSearchInput(aria_id: @aria_id, search_placeholder_text: @search_placeholder_text)
254
244
  end
255
245
 
256
- div(class: "p-1 max-h-80 overflow-y-auto", data: { combobox_target: "listContainer" }) do
246
+ ComboboxListContainer do
257
247
  ComboboxText(target: "empty") { @search_empty_text }
258
248
  ComboboxText(target: "error") { @search_error_text }
259
249
  ComboboxText(target: "loading") do
@@ -303,13 +293,14 @@ module ShadcnPhlexcomponents
303
293
 
304
294
  class ComboboxLabel < Base
305
295
  class_variants(
306
- base: "text-muted-foreground px-2 py-1.5 text-xs",
296
+ **(
297
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:label) ||
298
+ {
299
+ base: "text-muted-foreground px-2 py-1.5 text-xs",
300
+ }
301
+ ),
307
302
  )
308
303
 
309
- def initialize(**attributes)
310
- super(**attributes)
311
- end
312
-
313
304
  def view_template(&)
314
305
  div(**@attributes, &)
315
306
  end
@@ -317,13 +308,18 @@ module ShadcnPhlexcomponents
317
308
 
318
309
  class ComboboxItem < Base
319
310
  class_variants(
320
- base: <<~HEREDOC,
321
- data-[highlighted=true]:bg-accent data-[highlighted=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground
322
- relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm
323
- outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50
324
- [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
325
- *:[span]:last:items-center *:[span]:last:gap-2 group/item
326
- HEREDOC
311
+ **(
312
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:item) ||
313
+ {
314
+ base: <<~HEREDOC,
315
+ data-[highlighted=true]:bg-accent data-[highlighted=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground
316
+ relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm
317
+ outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50
318
+ [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
319
+ *:[span]:last:items-center *:[span]:last:gap-2 group/item
320
+ HEREDOC
321
+ }
322
+ ),
327
323
  )
328
324
 
329
325
  def initialize(value: nil, disabled: false, aria_id: nil, **attributes)
@@ -373,10 +369,6 @@ module ShadcnPhlexcomponents
373
369
  super(**attributes)
374
370
  end
375
371
 
376
- def view_template(&)
377
- div(**@attributes, &)
378
- end
379
-
380
372
  def default_attributes
381
373
  {
382
374
  role: "group",
@@ -388,10 +380,21 @@ module ShadcnPhlexcomponents
388
380
  },
389
381
  }
390
382
  end
383
+
384
+ def view_template(&)
385
+ div(**@attributes, &)
386
+ end
391
387
  end
392
388
 
393
389
  class ComboboxText < Base
394
- class_variants(base: "py-6 text-center text-sm hidden")
390
+ class_variants(
391
+ **(
392
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:text) ||
393
+ {
394
+ base: "py-6 text-center text-sm hidden",
395
+ }
396
+ ),
397
+ )
395
398
 
396
399
  def initialize(target:, **attributes)
397
400
  @target = target
@@ -411,14 +414,154 @@ module ShadcnPhlexcomponents
411
414
  end
412
415
 
413
416
  class ComboboxSeparator < Base
414
- class_variants(base: "bg-border pointer-events-none -mx-1 my-1 h-px")
417
+ class_variants(
418
+ **(
419
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:separator) ||
420
+ {
421
+ base: "bg-border pointer-events-none -mx-1 my-1 h-px",
422
+ }
423
+ ),
424
+ )
425
+
426
+ def default_attributes
427
+ { aria: { hidden: "true" } }
428
+ end
415
429
 
416
430
  def view_template(&)
417
431
  div(**@attributes, &)
418
432
  end
433
+ end
434
+
435
+ class ComboboxTriggerText < Base
436
+ class_variants(
437
+ **(
438
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:trigger_text) ||
439
+ {
440
+ base: "pointer-events-none line-clamp-1 flex items-center gap-2",
441
+ }
442
+ ),
443
+ )
444
+
445
+ def initialize(value: nil, placeholder: nil, **attributes)
446
+ @value = value
447
+ @placeholder = placeholder
448
+ super(**attributes)
449
+ end
419
450
 
420
451
  def default_attributes
421
- { aria: { hidden: "true" } }
452
+ { data: { combobox_target: "triggerText" } }
453
+ end
454
+
455
+ def view_template(&)
456
+ span(**@attributes) do
457
+ @value || @placeholder
458
+ end
459
+ end
460
+ end
461
+
462
+ class ComboboxContentContainer < Base
463
+ class_variants(
464
+ **(
465
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:content_container) ||
466
+ {
467
+ base: "fixed top-0 left-0 w-max z-50",
468
+ }
469
+ ),
470
+ )
471
+
472
+ def default_attributes
473
+ {
474
+ style: { display: "none" },
475
+ data: { combobox_target: "contentContainer" },
476
+ }
477
+ end
478
+
479
+ def view_template(&)
480
+ div(**@attributes, &)
481
+ end
482
+ end
483
+
484
+ class ComboboxSearchInputContainer < Base
485
+ class_variants(
486
+ **(
487
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:search_input_container) ||
488
+ {
489
+ base: "flex h-9 items-center gap-2 border-b px-3",
490
+ }
491
+ ),
492
+ )
493
+
494
+ def view_template(&)
495
+ div(**@attributes, &)
496
+ end
497
+ end
498
+
499
+ class ComboboxSearchInput < Base
500
+ class_variants(
501
+ **(
502
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:search_input) ||
503
+ {
504
+ base: "placeholder:text-muted-foreground flex w-full rounded-md bg-transparent py-3 text-sm
505
+ outline-hidden disabled:cursor-not-allowed disabled:opacity-50 h-9",
506
+ }
507
+ ),
508
+ )
509
+
510
+ def initialize(aria_id: nil, search_placeholder_text: nil, **attributes)
511
+ @aria_id = aria_id
512
+ @search_placeholder_text = search_placeholder_text
513
+ super(**attributes)
514
+ end
515
+
516
+ def default_attributes
517
+ {
518
+ id: "#{@aria_id}-search",
519
+ placeholder: @search_placeholder_text,
520
+ type: :text,
521
+ autocomplete: "off",
522
+ autocorrect: "off",
523
+ role: "combobox",
524
+ spellcheck: "false",
525
+ aria: {
526
+ autocomplete: "list",
527
+ expanded: "false",
528
+ controls: "#{@aria_id}-list",
529
+ labelledby: "#{@aria_id}-search-label",
530
+ },
531
+ data: {
532
+ combobox_target: "searchInput",
533
+ action: "keydown->combobox#inputKeydown input->combobox#search",
534
+ },
535
+ }
536
+ end
537
+
538
+ def view_template
539
+ input(**@attributes)
540
+ end
541
+ end
542
+
543
+ class ComboboxListContainer < Base
544
+ class_variants(
545
+ **(
546
+ ShadcnPhlexcomponents.configuration.combobox&.dig(:list_container) ||
547
+ {
548
+ base: "p-1 max-h-80 overflow-y-auto",
549
+ }
550
+ ),
551
+ )
552
+
553
+ def initialize(aria_id: nil, search_placeholder_text: nil, **attributes)
554
+ @aria_id = aria_id
555
+ @search_placeholder_text = search_placeholder_text
556
+ super(**attributes)
557
+ end
558
+
559
+ def default_attributes
560
+ { data: { combobox_target: "listContainer" } }
561
+ end
562
+
563
+ def view_template(&)
564
+ div(**@attributes, &)
422
565
  end
423
566
  end
424
567
  end
@@ -2,7 +2,14 @@
2
2
 
3
3
  module ShadcnPhlexcomponents
4
4
  class Command < Base
5
- class_variants(base: "inline-flex max-w-fit")
5
+ class_variants(
6
+ **(
7
+ ShadcnPhlexcomponents.configuration.command&.dig(:root) ||
8
+ {
9
+ base: "inline-flex max-w-fit",
10
+ }
11
+ ),
12
+ )
6
13
 
7
14
  MODIFIER_KEYS = [
8
15
  :ctrl,
@@ -137,12 +144,17 @@ module ShadcnPhlexcomponents
137
144
 
138
145
  class CommandContent < Base
139
146
  class_variants(
140
- base: <<~HEREDOC,
141
- bg-background bg-clip-padding dark:bg-neutral-900 dark:ring-neutral-800 data-[state=closed]:animate-out#{" "}
142
- data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0
143
- data-[state=open]:zoom-in-95 duration-200 fixed gap-4 grid left-[50%] max-w-[calc(100%-2rem)] p-2 pb-11 ring-4 ring-neutral-200/80
144
- rounded-xl shadow-2xl sm:max-w-lg top-[50%] translate-x-[-50%] translate-y-[-50%] w-full z-50 pointer-events-auto outline-none
145
- HEREDOC
147
+ **(
148
+ ShadcnPhlexcomponents.configuration.command&.dig(:content) ||
149
+ {
150
+ base: <<~HEREDOC,
151
+ bg-background bg-clip-padding dark:bg-neutral-900 dark:ring-neutral-800 data-[state=closed]:animate-out#{" "}
152
+ data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0
153
+ data-[state=open]:zoom-in-95 duration-200 fixed gap-4 grid left-[50%] max-w-[calc(100%-2rem)] p-2 pb-11 ring-4 ring-neutral-200/80
154
+ rounded-xl shadow-2xl sm:max-w-lg top-[50%] translate-x-[-50%] translate-y-[-50%] w-full z-50 pointer-events-auto outline-none
155
+ HEREDOC
156
+ }
157
+ ),
146
158
  )
147
159
 
148
160
  def initialize(
@@ -202,33 +214,13 @@ module ShadcnPhlexcomponents
202
214
  for: "#{@aria_id}-search",
203
215
  ) { @search_placeholder_text }
204
216
 
205
- div(class: "flex h-9 items-center gap-2 border px-3 bg-input/50 border-input rounded-md") do
217
+ CommandSearchInputContainer do
206
218
  icon("search", class: "size-4 shrink-0 opacity-50")
207
219
 
208
- input(
209
- class: "placeholder:text-muted-foreground flex w-full rounded-md bg-transparent py-3 text-sm
210
- outline-hidden disabled:cursor-not-allowed disabled:opacity-50 h-9",
211
- id: "#{@aria_id}-search",
212
- placeholder: @search_placeholder_text,
213
- type: :text,
214
- autocomplete: "off",
215
- autocorrect: "off",
216
- role: "combobox",
217
- spellcheck: "false",
218
- aria: {
219
- autocomplete: "list",
220
- expanded: "false",
221
- controls: "#{@aria_id}-list",
222
- labelledby: "#{@aria_id}-search-label",
223
- },
224
- data: {
225
- command_target: "searchInput",
226
- action: "keydown->command#inputKeydown input->command#search",
227
- },
228
- )
220
+ CommandSearchInput(aria_id: @aria_id, search_placeholder_text: @search_placeholder_text)
229
221
  end
230
222
 
231
- div(class: "mt-3 p-1 max-h-80 min-h-80 overflow-y-auto", data: { command_target: "listContainer" }) do
223
+ CommandListContainer do
232
224
  CommandText(target: "empty") { @search_empty_text }
233
225
  CommandText(target: "error") { @search_error_text }
234
226
  CommandText(target: "loading") do
@@ -248,13 +240,18 @@ module ShadcnPhlexcomponents
248
240
 
249
241
  class CommandItem < Base
250
242
  class_variants(
251
- base: <<~HEREDOC,
252
- data-[highlighted=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex
253
- cursor-default items-center gap-2 px-3 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none
254
- data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
255
- data-[highlighted=true]:border-input data-[highlighted=true]:bg-input/50 h-9 rounded-md border border-transparent
256
- font-medium
257
- HEREDOC
243
+ **(
244
+ ShadcnPhlexcomponents.configuration.command&.dig(:item) ||
245
+ {
246
+ base: <<~HEREDOC,
247
+ data-[highlighted=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex
248
+ cursor-default items-center gap-2 px-3 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none
249
+ data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4
250
+ data-[highlighted=true]:border-input data-[highlighted=true]:bg-input/50 h-9 rounded-md border border-transparent
251
+ font-medium
252
+ HEREDOC
253
+ }
254
+ ),
258
255
  )
259
256
 
260
257
  def initialize(value: nil, aria_id: nil, **attributes)
@@ -289,11 +286,14 @@ module ShadcnPhlexcomponents
289
286
  end
290
287
 
291
288
  class CommandLabel < Base
292
- class_variants(base: "text-muted-foreground text-xs px-3 pb-1 text-xs font-medium")
293
-
294
- def initialize(**attributes)
295
- super(**attributes)
296
- end
289
+ class_variants(
290
+ **(
291
+ ShadcnPhlexcomponents.configuration.command&.dig(:label) ||
292
+ {
293
+ base: "text-muted-foreground text-xs px-3 pb-1 text-xs font-medium",
294
+ }
295
+ ),
296
+ )
297
297
 
298
298
  def view_template(&)
299
299
  div(**@attributes, &)
@@ -301,7 +301,14 @@ module ShadcnPhlexcomponents
301
301
  end
302
302
 
303
303
  class CommandGroup < Base
304
- class_variants(base: "scroll-mt-16 first:pt-0 pt-3")
304
+ class_variants(
305
+ **(
306
+ ShadcnPhlexcomponents.configuration.command&.dig(:group) ||
307
+ {
308
+ base: "scroll-mt-16 first:pt-0 pt-3",
309
+ }
310
+ ),
311
+ )
305
312
 
306
313
  def initialize(aria_id: nil, **attributes)
307
314
  @aria_id = aria_id
@@ -326,7 +333,14 @@ module ShadcnPhlexcomponents
326
333
  end
327
334
 
328
335
  class CommandText < Base
329
- class_variants(base: "py-6 text-center text-sm hidden")
336
+ class_variants(
337
+ **(
338
+ ShadcnPhlexcomponents.configuration.command&.dig(:text) ||
339
+ {
340
+ base: "py-6 text-center text-sm hidden",
341
+ }
342
+ ),
343
+ )
330
344
 
331
345
  def initialize(target:, **attributes)
332
346
  @target = target
@@ -347,10 +361,15 @@ module ShadcnPhlexcomponents
347
361
 
348
362
  class CommandKbd < Base
349
363
  class_variants(
350
- base: <<~HEREDOC,
351
- bg-background text-muted-foreground pointer-events-none flex h-5 items-center justify-center gap-1 rounded
352
- border px-1 font-sans text-[0.7rem] font-medium select-none [&_svg:not([class*='size-'])]:size-3
353
- HEREDOC
364
+ **(
365
+ ShadcnPhlexcomponents.configuration.command&.dig(:kbd) ||
366
+ {
367
+ base: <<~HEREDOC,
368
+ bg-background text-muted-foreground pointer-events-none flex h-5 items-center justify-center gap-1 rounded
369
+ border px-1 font-sans text-[0.7rem] font-medium select-none [&_svg:not([class*='size-'])]:size-3
370
+ HEREDOC
371
+ }
372
+ ),
354
373
  )
355
374
 
356
375
  def view_template(&)
@@ -360,10 +379,15 @@ module ShadcnPhlexcomponents
360
379
 
361
380
  class CommandFooter < Base
362
381
  class_variants(
363
- base: <<~HEREDOC,
364
- text-muted-foreground absolute inset-x-0 bottom-0 z-20 flex h-10 items-center gap-2 rounded-b-xl border-t#{" "}
365
- border-t-neutral-100 bg-neutral-50 px-4 text-xs font-medium dark:border-t-neutral-700 dark:bg-neutral-800
366
- HEREDOC
382
+ **(
383
+ ShadcnPhlexcomponents.configuration.command&.dig(:footer) ||
384
+ {
385
+ base: <<~HEREDOC,
386
+ text-muted-foreground absolute inset-x-0 bottom-0 z-20 flex h-10 items-center gap-2 rounded-b-xl border-t#{" "}
387
+ border-t-neutral-100 bg-neutral-50 px-4 text-xs font-medium dark:border-t-neutral-700 dark:bg-neutral-800
388
+ HEREDOC
389
+ }
390
+ ),
367
391
  )
368
392
 
369
393
  def view_template
@@ -378,4 +402,84 @@ module ShadcnPhlexcomponents
378
402
  end
379
403
  end
380
404
  end
405
+
406
+ class CommandSearchInputContainer < Base
407
+ class_variants(
408
+ **(
409
+ ShadcnPhlexcomponents.configuration.command&.dig(:search_input_container) ||
410
+ {
411
+ base: "flex h-9 items-center gap-2 border px-3 bg-input/50 border-input rounded-md",
412
+ }
413
+ ),
414
+ )
415
+
416
+ def view_template(&)
417
+ div(**@attributes, &)
418
+ end
419
+ end
420
+
421
+ class CommandSearchInput < Base
422
+ class_variants(
423
+ **(
424
+ ShadcnPhlexcomponents.configuration.command&.dig(:search_input) ||
425
+ {
426
+ base: <<~HEREDOC,
427
+ placeholder:text-muted-foreground flex w-full rounded-md bg-transparent py-3 text-sm
428
+ outline-hidden disabled:cursor-not-allowed disabled:opacity-50 h-9
429
+ HEREDOC
430
+ }
431
+ ),
432
+ )
433
+
434
+ def initialize(aria_id: nil, search_placeholder_text: nil, **attributes)
435
+ @aria_id = aria_id
436
+ @search_placeholder_text = search_placeholder_text
437
+ super(**attributes)
438
+ end
439
+
440
+ def default_attributes
441
+ {
442
+ id: "#{@aria_id}-search",
443
+ placeholder: @search_placeholder_text,
444
+ type: :text,
445
+ autocomplete: "off",
446
+ autocorrect: "off",
447
+ role: "combobox",
448
+ spellcheck: "false",
449
+ aria: {
450
+ autocomplete: "list",
451
+ expanded: "false",
452
+ controls: "#{@aria_id}-list",
453
+ labelledby: "#{@aria_id}-search-label",
454
+ },
455
+ data: {
456
+ command_target: "searchInput",
457
+ action: "keydown->command#inputKeydown input->command#search",
458
+ },
459
+ }
460
+ end
461
+
462
+ def view_template(&)
463
+ input(**@attributes)
464
+ end
465
+ end
466
+
467
+ class CommandListContainer < Base
468
+ class_variants(
469
+ **(
470
+ ShadcnPhlexcomponents.configuration.command&.dig(:list_container) ||
471
+ {
472
+ base: "mt-3 p-1 max-h-80 min-h-80 overflow-y-auto",
473
+ }
474
+ ),
475
+ )
476
+
477
+ def default_attributes
478
+ { data: { command_target: "listContainer" } }
479
+ end
480
+
481
+ def view_template(&)
482
+ div(**@attributes, &)
483
+ end
484
+ end
381
485
  end