codengage_view_components 0.1.7 → 0.1.8

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/codengage_view_components/body_component.html.haml +5 -0
  3. data/app/components/codengage_view_components/body_component.rb +12 -0
  4. data/app/components/codengage_view_components/card_component.css +16 -0
  5. data/app/components/codengage_view_components/card_component.html.haml +13 -0
  6. data/app/components/codengage_view_components/card_component.rb +14 -0
  7. data/app/components/codengage_view_components/column_component.html.haml +6 -0
  8. data/app/components/codengage_view_components/column_component.rb +11 -0
  9. data/app/components/codengage_view_components/dropdown_component.rb +1 -1
  10. data/app/components/codengage_view_components/empty_state_action_component.html.haml +4 -0
  11. data/app/components/codengage_view_components/empty_state_action_component.rb +11 -0
  12. data/app/components/codengage_view_components/empty_state_component.html.haml +15 -0
  13. data/app/components/codengage_view_components/empty_state_component.rb +14 -0
  14. data/app/components/codengage_view_components/flash_component.html.haml +1 -1
  15. data/app/components/codengage_view_components/flash_component.rb +2 -1
  16. data/app/components/codengage_view_components/header_component.html.haml +4 -0
  17. data/app/components/codengage_view_components/header_component.rb +11 -0
  18. data/app/components/codengage_view_components/item_table_component.html.haml +15 -0
  19. data/app/components/codengage_view_components/item_table_component.rb +11 -0
  20. data/app/components/codengage_view_components/paginator_component.html.haml +42 -0
  21. data/app/components/codengage_view_components/paginator_component.rb +10 -0
  22. data/app/components/codengage_view_components/search_form_component.css +81 -0
  23. data/app/components/codengage_view_components/search_form_component.html.haml +12 -0
  24. data/app/components/codengage_view_components/search_form_component.rb +11 -0
  25. data/app/components/codengage_view_components/tab_item_component.css +11 -0
  26. data/app/components/codengage_view_components/tab_item_component.html.haml +3 -0
  27. data/app/components/codengage_view_components/tab_item_component.rb +21 -0
  28. data/app/components/codengage_view_components/table_component.css +182 -0
  29. data/app/components/codengage_view_components/table_component.html.haml +7 -0
  30. data/app/components/codengage_view_components/table_component.rb +13 -0
  31. data/app/components/codengage_view_components/toggle_component.css +31 -0
  32. data/app/components/codengage_view_components/toggle_component.html.haml +43 -0
  33. data/app/components/codengage_view_components/toggle_component.rb +66 -0
  34. data/app/components/codengage_view_components/turbo_drawer_component.html.erb +46 -0
  35. data/app/components/codengage_view_components/turbo_drawer_component.rb +12 -0
  36. data/app/components/codengage_view_components/turbo_modal_component.html.erb +103 -0
  37. data/app/components/codengage_view_components/turbo_modal_component.rb +46 -0
  38. data/app/javascript/controllers/search_controller.js +79 -0
  39. data/app/javascript/controllers/toggle_controller.js +26 -0
  40. data/config/importmap.rb +3 -1
  41. data/lib/codengage_view_components/version.rb +1 -1
  42. metadata +36 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06a62f0948ab276ba1cf10218e6c8f18be676f2f24c21c70db98a4e4002be21f
4
- data.tar.gz: 9a677bac627df7c41aad021d70f4fef6ba1974a6d9b32c2374a2b4e755bb1969
3
+ metadata.gz: fd28f76bd68a94bd05d84dca6be35e5acae3974cbb4fcadae89d9a5d1460999d
4
+ data.tar.gz: 4f6de8757125a6c496dc40620671c15ed922ac47fcd41d1879cb6a51cba1f112
5
5
  SHA512:
6
- metadata.gz: 041ec368163945b9a169caceb40745c4eadb425e5c02ce2dec00b618ba2ebcba7c2438fbaf12525ed30d95564bf35583b7196ff9875c4ed1a0a7d541490713b9
7
- data.tar.gz: b398e038f04e01f029b86a180b8581362043160dce56f277b7048f576da0be28b45b74685c004d84e46790fe77bf177018c5373eaa36409fce4f4aa7e2e1b9b9
6
+ metadata.gz: b995a430a14fa6838130a73115e70129819d3e0f6e70d8ff5478001e84ca1d149ec624881923e96458751fd60ba702e2cbffe9469c489a21eff0e2d3f65f3362
7
+ data.tar.gz: 5ded5f4f31659036aefdb0e72ce0d02765966dba5018a83dfcb400df75a4dea61ac4ec82cac5cec63e3e7bea630e25331e138cfa1e31f8949c9b5685ffb1765a
@@ -0,0 +1,5 @@
1
+ %tbody{ id: @id, class: @classes }
2
+ - if items.present?
3
+ - items.each do |item|
4
+ = item
5
+ = content
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class BodyComponent < ApplicationComponent
5
+ renders_many :items, "CodengageViewComponents::ItemTableComponent"
6
+
7
+ def initialize(id: "items", classes: "")
8
+ @id = id
9
+ @classes = classes
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ .card {
2
+ @apply w-full overflow-hidden rounded-lg bg-white shadow;
3
+ }
4
+
5
+ .card__header,
6
+ .card__footer {
7
+ @apply p-8;
8
+ }
9
+
10
+ .card__body {
11
+ @apply px-8;
12
+ }
13
+
14
+ .card__table {
15
+ @apply py-2;
16
+ }
@@ -0,0 +1,13 @@
1
+ .card{ class: @options.fetch(:class, ''), data: @options.fetch(:data, {}) }
2
+ - if header?
3
+ %div{ class: @options.fetch(:header_class, 'card__header') }
4
+ = header
5
+ - if body?
6
+ .card__body
7
+ = body
8
+ - if table?
9
+ .card__table
10
+ = table
11
+ = if footer?
12
+ .card__footer
13
+ = footer
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class CardComponent < ApplicationComponent
5
+ renders_one :header
6
+ renders_one :body
7
+ renders_one :table
8
+ renders_one :footer
9
+
10
+ def initialize(options: {})
11
+ @options = options
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ %td{ class: "#{@options.fetch(:class, nil)}" , data: @options.fetch(:data, {}), colspan: @options.fetch(:colspan, nil) }
2
+ - if @title.present?
3
+ .block.font-medium= @title
4
+ - if @description.present?
5
+ .block.text-sm.sm:text-xs.text-gray-400= @description
6
+ = content
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class ColumnComponent < ApplicationComponent
5
+ def initialize(title: nil, description: nil, options: {})
6
+ @title = title
7
+ @description = description
8
+ @options = options
9
+ end
10
+ end
11
+ end
@@ -3,7 +3,7 @@
3
3
  module CodengageViewComponents
4
4
  class DropdownComponent < ApplicationComponent
5
5
  renders_one :trigger
6
- renders_many :items, "Dropdown::ItemComponent"
6
+ renders_many :items, "CodengageViewComponents::ItemComponent"
7
7
 
8
8
  def initialize(id:, options: {})
9
9
  @id = id
@@ -0,0 +1,4 @@
1
+ - if @href
2
+ = link_to @href, { class: "btn btn--primary flex items-center gap-2 #{@options.fetch(:class, '')}".strip, data: @options.fetch(:data, {}) } do
3
+ = lucide_icon @options.fetch(:icon, 'plus')
4
+ %span.font-medium= @value
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class EmptyStateActionComponent < ApplicationComponent
5
+ def initialize(value:, href:, options: {})
6
+ @value = value
7
+ @href = href
8
+ @options = options
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ .my-10{ id: :empty_state, class: @options.fetch(:hidden, false) && 'hidden' }
2
+ .min-h-full.px-3.py-3.sm:px-6.sm:py-3.md:grid.md:place-items-center.lg:px-8{ class: @options.fetch(:class, '') }
3
+ .mx-auto.max-w-max
4
+ .sm:flex.sm:flex-col.sm:items-center.sm:justify-center.gap-y-2
5
+ %p.sm:flex-1.flex.justify-center.sm:justify-end.font-bold.tracking-tight.text-primary
6
+ .text-gray-300
7
+ = lucide_icon @icon, size: 40
8
+ .sm:flex-1.mt-6.sm:mt-0
9
+ %h5.text-gray-500.font-semibold.text-center.sm:text-lg= @title
10
+ %p.text-sm.text-gray-500.text-center.mt-1= @message
11
+ .mt-6.flex.sm:space-x-6
12
+ - actions.each do |action|
13
+ = action
14
+
15
+
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class EmptyStateComponent < ApplicationComponent
5
+ renders_many :actions, CodengageViewComponents::EmptyStateActionComponent
6
+
7
+ def initialize(title:, message:, icon:, options: {})
8
+ @title = title
9
+ @message = message
10
+ @icon = icon
11
+ @options = options
12
+ end
13
+ end
14
+ end
@@ -1,5 +1,5 @@
1
1
  - @messages.each do |message|
2
- .flash{ class: message.bg, data: { controller: "flash-component" } }
2
+ .flash{ class: "#{message.bg} #{@classes}", data: { controller: "flash-component" } }
3
3
  .flash__icon
4
4
  = lucide_icon(message.icon, stroke: message.stroke)
5
5
  .flash__text
@@ -9,7 +9,8 @@ module CodengageViewComponents
9
9
  "alert" => { bg: "bg-red-700", stroke: "#DC3545", icon: "circle-alert" }
10
10
  }.freeze
11
11
 
12
- def initialize(flash:)
12
+ def initialize(flash:, classes:)
13
+ @classes = classes
13
14
  @messages = flash.map do |type, text|
14
15
  style = STYLES[type]
15
16
  Message.new(type:, text: text.to_s, **style)
@@ -0,0 +1,4 @@
1
+ %thead{ class: @classes }
2
+ %tr
3
+ - cols.each do |col|
4
+ = col
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class HeaderComponent < ApplicationComponent
5
+ renders_many :cols, "CodengageViewComponents::ColumnComponent"
6
+
7
+ def initialize(classes: "")
8
+ @classes = classes
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ - if @options.fetch(:href, false)
2
+ %tr.hoverable.group.print:break-inside-avoid{ id: @options.fetch(:id, object_id),
3
+ data: { controller: 'clickable',
4
+ clickable_url_value: @options.fetch(:href, ''),
5
+ clickable_turbo_value: @options.fetch(:turbo, true),
6
+ clickable_frame_value: @options.fetch(:frame, '_top')
7
+ }.merge(@options.fetch(:data, {})) }
8
+ - cols.each do |col|
9
+ = col
10
+ = content
11
+ - else
12
+ %tr.print:break-inside-avoid{ id: @options.fetch(:id, object_id), class: "#{@options.fetch(:class, '')}", data: @options.fetch(:data, {}) }
13
+ - cols.each do |col|
14
+ = col
15
+ = content
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class ItemTableComponent < ApplicationComponent
5
+ renders_many :cols, "CodengageViewComponents::ColumnComponent"
6
+
7
+ def initialize(options: {})
8
+ @options = options
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,42 @@
1
+ - return unless @paginator && @paginator.pages > 1
2
+
3
+ %nav#series-nav.pagy.series-nav.flex.items-center.justify-end.gap-4.mt-5{"aria-label" => "Pages series_nav"}
4
+ - if @paginator.page == 1
5
+ %span.text-gray-300.cursor-not-allowed.text-base= lucide_icon('chevrons-left', class: 'w-4 h-4')
6
+ %span.text-gray-300.cursor-not-allowed.text-base= lucide_icon('chevron-left', class: 'w-4 h-4')
7
+ - else
8
+ = link_to lucide_icon('chevrons-left', class: 'w-4 h-4'), @paginator.page_url(:first), aria: { label: "First" }
9
+ = link_to lucide_icon('chevron-left', class: 'w-4 h-4'), @paginator.page_url(:previous), aria: { label: "Previous" }
10
+
11
+ - current = @paginator.page
12
+ - last = @paginator.last
13
+
14
+ - if last <= 3
15
+ - pages_to_show = (1..last).to_a
16
+ - else
17
+ - case current
18
+ - when 1
19
+ - pages_to_show = [1, 2, 3]
20
+ - when last
21
+ - pages_to_show = [last - 2, last - 1, last]
22
+ - else
23
+ - pages_to_show = [current - 1, current, current + 1]
24
+
25
+ - pages_to_show = pages_to_show.map { _1.clamp(1, last) }.uniq
26
+
27
+
28
+ - pages_to_show.each do |num|
29
+ - if num == current
30
+ .bg-primary.text-white.px-2.py-1.font-semibold.text-sm{class: 'rounded-[10px]'}= num
31
+ - else
32
+ = link_to num, @paginator.page_url(num),
33
+ class: "rounded-[10px] px-2 py-1 hover:bg-gray-100 text-sm text-gray-500 font-semibold"
34
+
35
+
36
+
37
+ - if @paginator.last == @paginator.page
38
+ %span.page.text-gray-300.cursor-not-allowed= lucide_icon('chevron-right', class: 'w-4 h-4')
39
+ %span.page.text-gray-300.cursor-not-allowed= lucide_icon('chevrons-right', class: 'w-4 h-4')
40
+ - else
41
+ = link_to lucide_icon('chevron-right', class: 'w-4 h-4'), @paginator.page_url(:next), aria: { label: "Next" }
42
+ = link_to lucide_icon('chevrons-right', class: 'w-4 h-4'), @paginator.page_url(:last), aria: { label: "Last" }
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class PaginatorComponent < ApplicationComponent
5
+ def initialize(paginator:, options: {})
6
+ @paginator = paginator
7
+ @options = options
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,81 @@
1
+ .search-form {
2
+ @apply relative w-full text-gray-400 focus-within:text-gray-600;
3
+ }
4
+
5
+ .search-form__container {
6
+ @apply flex items-center w-full p-1;
7
+ }
8
+
9
+ .search-form__icon {
10
+ @apply pointer-events-none absolute inset-y-0 flex items-center pl-3;
11
+ }
12
+
13
+ .search-form__input {
14
+ @apply block outline-none w-full h-12 rounded-base border-0 border-[#E5E7EB] bg-[#F3F3F5] pl-12 pr-3 text-gray-700 ring-1 ring-gray-200 focus:ring-4 focus:ring-gray-300;
15
+ }
16
+
17
+ /* dropdown dentro de .search-form */
18
+ .search-form .dropdown > button > div:not(.active) > svg {
19
+ animation: filter-arrow-reverse 0.2s cubic-bezier(1, 0, 0, 1) 0s 1 forwards;
20
+ }
21
+
22
+ .search-form .dropdown > button > div.active > svg {
23
+ animation: filter-arrow 0.2s cubic-bezier(1, 0, 0, 1) 0s 1 forwards;
24
+ }
25
+
26
+ .clear-filter__container {
27
+ @apply w-fit ml-1 text-primary gap-x-2 items-center mt-3 cursor-pointer hover:text-brand-blue
28
+ }
29
+
30
+ @keyframes filter-arrow {
31
+ 0% {
32
+ transform: rotateX(0deg);
33
+ }
34
+ 49% {
35
+ transform: rotateX(45deg);
36
+ }
37
+ 50% {
38
+ transform: rotateX(135deg);
39
+ }
40
+ 100% {
41
+ transform: rotateX(180deg);
42
+ }
43
+ }
44
+
45
+ @keyframes filter-arrow-reverse {
46
+ 0% {
47
+ transform: rotateX(180deg);
48
+ }
49
+ 49% {
50
+ transform: rotateX(135deg);
51
+ }
52
+ 50% {
53
+ transform: rotateX(45deg);
54
+ }
55
+ 100% {
56
+ transform: rotateX(0deg);
57
+ }
58
+ }
59
+
60
+ /*!* ss-main.always_dropdown *!*/
61
+ /*.ss-main.always_dropdown,*/
62
+ /*.ss-main.always_dropdown:focus,*/
63
+ /*.ss-main.always_dropdown:hover {*/
64
+ /* @apply gap-1.5 text-base font-bold drop-shadow-none ring-0 shadow-none cursor-pointer flex relative mt-0;*/
65
+ /*}*/
66
+
67
+ /*.ss-main.always_dropdown::before {*/
68
+ /* content: "";*/
69
+ /* margin-right: calc(0.375rem + 1px);*/
70
+ /* @apply max-w-5 max-h-5 w-5 h-5 absolute bg-gray-300 rounded-full right-0 -z-10;*/
71
+ /*}*/
72
+
73
+ /*.ss-main.always_dropdown .ss-arrow path {*/
74
+ /* @apply brightness-[0.30] stroke-[14px];*/
75
+ /*}*/
76
+
77
+ /*!* ss-content.always_dropdown *!*/
78
+ /*.ss-content.always_dropdown {*/
79
+ /* --tw-ring-shadow: none;*/
80
+ /* @apply border-gray-200 shadow-md rounded-md bg-white;*/
81
+ /*}*/
@@ -0,0 +1,12 @@
1
+ = turbo_frame_tag :search_form, class: @options.fetch(:class, '') do
2
+ .flex.justify-between
3
+ .search-form__container
4
+ .search-form__icon
5
+ = lucide_icon 'search'
6
+ = @form.search_field :q, value: params[:q], class: "search-form__input", placeholder: @options.fetch(:placeholder, ''), data: { action: 'input->search#onType' }
7
+ - if defined?(form_params) && form_params.any?
8
+ - form_params.each do |k, v|
9
+ - next if v.blank?
10
+ = @form.hidden_field k, value: v
11
+ .flex.items-center.gap-4
12
+ = content
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class SearchFormComponent < ApplicationComponent
5
+ def initialize(url:, form:, options: {})
6
+ @url = url
7
+ @form = form
8
+ @options = options
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ .tab__selected{
2
+ @apply bg-linear-to-r from-[#0046CE] to-[#7A5AF8] rounded-base py-1 px-4 text-white font-semibold flex items-center gap-2;
3
+ }
4
+
5
+ .tab__not-selected{
6
+ @apply hover:bg-gray-300 rounded-base py-1 px-4 text-gray-500 font-semibold flex items-center gap-2;
7
+ }
8
+
9
+ .tab__box{
10
+ @apply bg-gray-100 border border-gray-200 shadow-sm w-fit p-2 rounded-base flex items-center gap-5;
11
+ }
@@ -0,0 +1,3 @@
1
+ = link_to @url, class: tab_item_class do
2
+ = lucide_icon("#{@icon}", class: 'w-4 h-4')
3
+ = @text
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class TabItemComponent < ApplicationComponent
5
+ def initialize(url:, tab:, icon:, text:, classes:)
6
+ @url = url
7
+ @tab = tab
8
+ @icon = icon
9
+ @text = text
10
+ @classes = classes
11
+ end
12
+
13
+ def active?
14
+ params[:tab] == @tab
15
+ end
16
+
17
+ def tab_item_class
18
+ active? ? "tab__selected #{@classes}" : "tab__not-selected #{@classes}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,182 @@
1
+ .c-table {
2
+ @apply block divide-y divide-gray-200 rounded-lg w-auto print:text-black print:w-full;
3
+ }
4
+
5
+ .c-table__head,
6
+ .c-table__body {
7
+ @apply flex flex-col divide-y;
8
+ }
9
+
10
+ .c-table__head {
11
+ @apply font-semibold overflow-hidden bg-gray-500 rounded-t-lg print:font-bold;
12
+ }
13
+
14
+ .c-table__item {
15
+ @apply flex flex-row items-center box-border flex-nowrap px-1.5;
16
+ }
17
+
18
+ .c-table__body .c-table__item {
19
+ @apply hover:bg-gray-50;
20
+ }
21
+
22
+ .c-table__body .c-table__item.disable-hover {
23
+ @apply hover:bg-white;
24
+ }
25
+
26
+ .c-table__head .c-table__item:first-child {
27
+ @apply rounded-t-lg;
28
+ }
29
+
30
+ .c-table__body > turbo-frame:last-of-type > li > .c-table__item,
31
+ .c-table__body > turbo-frame:last-of-type > .c-table__item {
32
+ @apply rounded-b-lg;
33
+ }
34
+
35
+ .c-table__column {
36
+ @apply flex items-center px-1.5 py-1.5 print:py-1.5 leading-4 whitespace-normal box-border flex-shrink-0;
37
+ min-height: 3rem;
38
+ }
39
+
40
+ .c-table__column--check {
41
+ @apply justify-center flex-shrink-0;
42
+ width: 3.5rem;
43
+ }
44
+
45
+ .c-table__column--flag {
46
+ @apply justify-center text-center flex-shrink-0;
47
+ width: 8rem;
48
+ }
49
+
50
+ .c-table__column--avatar {
51
+ @apply justify-start flex-shrink-0 w-14;
52
+ }
53
+
54
+ .c-table__column--name {
55
+ @apply items-center font-bold text-left;
56
+ }
57
+
58
+ .c-table__column--description {
59
+ @apply flex flex-col justify-center items-start flex-1 space-y-1;
60
+ }
61
+
62
+ .c-table__column--amount,
63
+ .c-table__column--type{
64
+ @apply w-32 xl:w-36 font-bold text-left;
65
+ }
66
+
67
+ .c-table__column--status {
68
+ @apply xl:w-52 font-bold text-left;
69
+ }
70
+
71
+ .c-table__column--date {
72
+ @apply w-24 xl:w-28;
73
+ }
74
+
75
+ .c-table__column--contact {
76
+ @apply w-24 xl:w-40;
77
+ }
78
+
79
+ .c-table__column--others {
80
+ @apply truncate flex-shrink-0;
81
+ width: 10rem;
82
+ }
83
+
84
+ .c-table__column--phone-number {
85
+ @apply truncate flex-shrink-0;
86
+ width: 10rem;
87
+ }
88
+
89
+ .c-table__column--person-type,
90
+ .c-table__column--seller {
91
+ @apply items-center font-bold text-center justify-center;
92
+ }
93
+
94
+ .c-table__column--cell_phone-number {
95
+ @apply truncate flex-shrink-0;
96
+ width: 10rem;
97
+ }
98
+
99
+ .c-table__column--email {
100
+ @apply truncate flex-shrink-0 w-[30%];
101
+ }
102
+
103
+ .c-table__column--datetime {
104
+ @apply whitespace-nowrap font-bold;
105
+ width: 11rem;
106
+ }
107
+
108
+ .c-table__column--document-1,
109
+ .c-table__column--document-2,
110
+ .c-table__column--id {
111
+ @apply text-left font-bold justify-center;
112
+ }
113
+
114
+ .c-table__column--actions {
115
+ @apply text-right font-bold justify-center;
116
+ }
117
+
118
+ .table-component {
119
+ @apply rounded-xl table-auto sm:table-fixed w-full print:text-black print:w-full divide-y divide-gray-200 border border-gray-200 overflow-hidden shadow-md;
120
+ }
121
+
122
+ .table-component > thead {
123
+ @apply font-semibold;
124
+ }
125
+
126
+ .table-component > thead > tr > td a:hover {
127
+ @apply text-primary underline;
128
+ }
129
+
130
+ .table-component > tbody {
131
+ @apply divide-y divide-gray-200;
132
+ }
133
+
134
+ .table-component > tbody > tr.disabled {
135
+ @apply opacity-50 cursor-not-allowed pointer-events-none line-through;
136
+ }
137
+
138
+ .table-component > tbody > tr.hoverable:hover > td {
139
+ @apply bg-gray-100;
140
+ }
141
+
142
+ .table-component > tbody > tr > td:first-child,
143
+ .table-component > thead > tr > td:first-child {
144
+ @apply pl-3;
145
+ }
146
+
147
+ .table-component > tbody > tr > td:last-child,
148
+ .table-component > thead > tr > td:last-child {
149
+ @apply pr-3;
150
+ }
151
+
152
+ .table-component td {
153
+ @apply px-1.5 py-1.5 h-12 leading-4;
154
+ }
155
+
156
+ .table-component__actions {
157
+ @apply flex items-center justify-center space-x-1.5;
158
+ }
159
+
160
+ .table-component__content {
161
+ @apply w-auto relative;
162
+ }
163
+
164
+ .table-component__content .tooltip {
165
+ @apply truncate cursor-default;
166
+ }
167
+
168
+ .table-component__content .tooltip-text {
169
+ @apply invisible bg-gray-900 text-white cursor-default text-center absolute -bottom-4 z-10 rounded-md px-3 py-1.5 w-max left-1/3;
170
+ }
171
+
172
+ .table-component__content:hover .tooltip-text {
173
+ @apply visible;
174
+ }
175
+
176
+ .table-component__form-buttons {
177
+ @apply flex items-center justify-end space-x-1.5;
178
+ }
179
+
180
+ .table-component__role-value {
181
+ @apply bg-white rounded-md h-6 w-fit border border-gray-300 text-xs font-semibold text-gray-900 flex items-center p-2;
182
+ }
@@ -0,0 +1,7 @@
1
+ %table.table-component{ class: @options.fetch(:class, ''), data: @options.fetch(:data, {}) }
2
+ - if header
3
+ = header
4
+ - if bodies.any?
5
+ - bodies.each do |body|
6
+ = body
7
+ = content
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class TableComponent < ApplicationComponent
5
+ renders_one :header, "CodengageViewComponents::HeaderComponent"
6
+ renders_many :bodies, "CodengageViewComponents::BodyComponent"
7
+
8
+ def initialize(variant: :normal, options: {})
9
+ @variant = variant
10
+ @options = options
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ .toggle {
2
+ @apply relative inline-flex h-5 w-10 flex-shrink-0 cursor-pointer items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2;
3
+ }
4
+
5
+ .toggle:disabled {
6
+ @apply opacity-50 cursor-not-allowed;
7
+ }
8
+
9
+ .toggle__bg {
10
+ @apply pointer-events-none absolute h-full w-full rounded-md bg-transparent;
11
+ }
12
+
13
+ .toggle__bar {
14
+ @apply bg-gray-200 pointer-events-none absolute mx-2 h-4 w-9 rounded-full transition-colors duration-200 ease-in-out;
15
+ }
16
+
17
+ .toggle__pin {
18
+ @apply translate-x-0 pointer-events-none absolute left-0 inline-block h-5 w-5 transform rounded-full border border-gray-200 bg-white shadow ring-0 transition-transform duration-200 ease-in-out;
19
+ }
20
+
21
+ .toggle__pin--active {
22
+ @apply translate-x-5;
23
+ }
24
+
25
+ .toggle--active > .toggle__bar {
26
+ @apply bg-primary;
27
+ }
28
+
29
+ .toggle--active > .toggle__pin {
30
+ @apply translate-x-5;
31
+ }
@@ -0,0 +1,43 @@
1
+ - if form_mode?
2
+ .nav.flex.items-center{ data: { controller: "toggle" } }
3
+ = @form.hidden_field @attribute,
4
+ value: @value,
5
+ data: { toggle_target: "input" }
6
+
7
+ - button_data = @options.fetch(:data, {}).merge(toggle_target: "button").compact
8
+ - extra_action = @options.fetch(:data, {})[:action]
9
+ - action_value = ["click->toggle#switch", extra_action].reject(&:blank?).join(" ")
10
+
11
+ - button_data[:action] = action_value if action_value.present?
12
+
13
+ = button_tag type: "button",
14
+ class: "toggle",
15
+ disabled: @disabled,
16
+ role: "switch",
17
+ id: @id,
18
+ data: button_data do
19
+ %span.toggle__bg{ "aria-hidden": true }
20
+ %span.toggle__bar{ "aria-hidden": true, data: { toggle_target: :bar } }
21
+ %span.toggle__pin{ "aria-hidden": true, data: { toggle_target: :pin } }
22
+
23
+ - elsif remote_mode?
24
+ - button_data = @options.fetch(:data, {}).merge(toggle_target: "button")
25
+ - action_value = @options.fetch(:action, "click->toggle#switch")
26
+
27
+ - button_data[:action] = action_value if action_value.present?
28
+
29
+ %div{ data: { controller: "toggle" } }
30
+ = button_to url,
31
+ method: @method,
32
+ value: @enabled,
33
+ params: @params,
34
+ class: "toggle",
35
+ role: "switch",
36
+ disabled: @disabled,
37
+ onclick: "event.stopPropagation()",
38
+ id: @id,
39
+ "aria-checked": @enabled,
40
+ data: button_data do
41
+ %span.toggle__bg{ "aria-hidden": true }
42
+ %span.toggle__bar{ "aria-hidden": true, data: { toggle_target: :bar } }
43
+ %span.toggle__pin{ "aria-hidden": true, data: { toggle_target: :pin } }
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class ToggleComponent < ViewComponent::Base
5
+ # Uso:
6
+ # - Form mode:
7
+ # = render Form::ToggleComponent.new(form: f, attribute: :status, options: { id: "user-active-toggle" })
8
+ #
9
+ # - Remote mode:
10
+ # = render Form::ToggleComponent.new(url: user_path(user), options: { method: :patch, enabled: user.active? })
11
+
12
+ def initialize(form: nil, attribute: nil, url: nil, value: nil, options: {})
13
+ @form = form
14
+ @attribute = attribute
15
+ @url = url
16
+ @value = value
17
+
18
+ # Defaults centralizados aqui
19
+ @id = options.fetch(:id, nil)
20
+ @disabled = options.fetch(:disabled, false)
21
+
22
+ @method = options.fetch(:method, :patch)
23
+ @enabled = options.fetch(:enabled, false)
24
+ @params = options.fetch(:params, {})
25
+
26
+ @options = options.except(:id, :value, :disabled, :method, :enabled, :params)
27
+
28
+ validate_configuration!
29
+ end
30
+
31
+ private
32
+
33
+ def validate_configuration!
34
+ if form_mode?
35
+ validate_form_mode!
36
+ elsif remote_mode?
37
+ validate_remote_mode!
38
+ else
39
+ raise ArgumentError,
40
+ "Você precisa fornecer `form` e `attribute`, ou `url` (modo remoto)."
41
+ end
42
+ end
43
+
44
+ def form_mode?
45
+ @form.present? && @attribute.present?
46
+ end
47
+
48
+ def remote_mode?
49
+ @url.present?
50
+ end
51
+
52
+ def validate_form_mode!
53
+ if @url.present?
54
+ raise ArgumentError,
55
+ "No modo form, não use `url`. Use apenas `form:` e `attribute:`."
56
+ end
57
+ end
58
+
59
+ def validate_remote_mode!
60
+ unless @method.respond_to?(:to_sym)
61
+ raise ArgumentError,
62
+ "O método HTTP deve ser algo como :get, :post, :patch, :put ou :delete."
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,46 @@
1
+ <%= turbo_frame_tag :drawer do %>
2
+ <%= tag.div data: { controller: "turbo-drawer", action: token_list(
3
+ @close_on_submit ? "turbo:submit-end->turbo-drawer#submitEnd" : nil,
4
+ "keyup@window->turbo-drawer#closeWithKeyboard",
5
+ "mousedown@window->turbo-drawer#closeBackground"
6
+ ) }, class: "relative z-auto" do %>
7
+ <%= tag.div class: "fixed inset-0 bg-black/50 z-40 hidden", data: { turbo_drawer_target: :backdrop, action: "click->turbo-drawer#hideDrawer" } %>
8
+ <%= tag.div class: "z-50 pointer-events-none fixed inset-y-0 right-0 flex #{@options.fetch(:max_w, 'max-w-md')} sm:max-w-full sm:pl-10" do %>
9
+ <%= tag.div id: 'drawer_body', class: "pointer-events-auto w-screen #{@options.fetch(:max_w, 'max-w-md')} hidden",
10
+ data: { turbo_drawer_target: :drawer,
11
+ transition_enter: "transition ease-in-out duration-200 transform",
12
+ transition_enter_start: "translate-x-full",
13
+ transition_enter_end: "translate-x-0",
14
+ transition_leave: "transition ease-in-out duration-100 transform",
15
+ transition_leave_start: "translate-x-0",
16
+ transition_leave_end: "translate-x-full" } do %>
17
+ <%= tag.div class: 'flex h-full flex-col bg-white shadow-xl overflow-auto' do %>
18
+ <%= tag.div class: 'py-6 px-3 sm:px-6 sticky top-0 bg-white z-50 border-b border-gray-200' do %>
19
+ <%= tag.div class: 'flex items-start justify-between' do %>
20
+ <%= tag.div class: 'block space-y-2' do %>
21
+ <%= tag.div class: 'text-2xl font-semibold text-gray-40 items-center flex gap-x-2' do %>
22
+ <%= @title %>
23
+ <% end %>
24
+ <% if @subtitle.present? %>
25
+ <%= tag.div class: 'text-sm text-gray-30' do %>
26
+ <%= @subtitle %>
27
+ <% end %>
28
+ <% end %>
29
+ <% end %>
30
+ <%= tag.div class: 'ml-3 flex h-8 items-center' do %>
31
+ <%= button_tag data: { action: "turbo-drawer#hideDrawer" }, type: "button", class: 'cursor-pointer', id: 'close_drawer' do %>
32
+ <%= lucide_icon "x" %>
33
+ <% end %>
34
+ <% end %>
35
+ <% end %>
36
+ <% end %>
37
+ <%= tag.div class: 'flex-1 mb-6 flex flex-col' do %>
38
+ <%= tag.div class: 'px-10 pt-10 sm:px-6 flex-1 flex flex-col' do %>
39
+ <%= content %>
40
+ <% end %>
41
+ <% end %>
42
+ <% end %>
43
+ <% end %>
44
+ <% end %>
45
+ <% end %>
46
+ <% end %>
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class TurboDrawerComponent < ApplicationComponent
5
+ def initialize(title:, subtitle: nil, close_on_submit: true, options: {})
6
+ @title = title
7
+ @subtitle = subtitle
8
+ @close_on_submit = close_on_submit
9
+ @options = options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,103 @@
1
+ <%= turbo_frame_tag :modal, class: "overflow-hidden print:hidden" do %>
2
+ <%= tag.div class: "relative z-30", role: "dialog",
3
+ aria: { labelledby: "modal-title", modal: true },
4
+ data: { controller: "turbo-modal #{@options.fetch(:controller, '')}",
5
+ action: token_list("turbo:submit-end->turbo-modal#submitEnd") } do %>
6
+ <!--
7
+ Background backdrop, show/hide based on modal state.
8
+ Entering: "ease-out duration-300"
9
+ From: "opacity-0"
10
+ To: "opacity-100"
11
+ Leaving: "ease-in duration-200"
12
+ From: "opacity-100"
13
+ To: "opacity-0"
14
+ -->
15
+ <%= tag.div(
16
+ class: "fixed inset-0 bg-black/60 hidden",
17
+ data: {
18
+ turbo_modal_target: "backdrop",
19
+ action: "click->turbo-modal#hideModal",
20
+ transition_enter: "transition-opacity ease-out duration-300",
21
+ transition_enter_start: "opacity-0",
22
+ transition_enter_end: "opacity-100",
23
+ transition_leave: "transition-opacity ease-in duration-200",
24
+ transition_leave_start: "opacity-100",
25
+ transition_leave_end: "opacity-0"
26
+ }
27
+ ) %>
28
+ <%= tag.div class: "fixed inset-0 z-40 overflow-y-auto" do %>
29
+ <%= tag.div class: "flex min-h-full items-stretch justify-center text-center sm:items-center" do %>
30
+ <!--
31
+ Modal panel, show/hide based on modal state.
32
+ Entering: "ease-out duration-300"
33
+ From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
34
+ To: "opacity-100 translate-y-0 sm:scale-100"
35
+ Leaving: "ease-in duration-200"
36
+ From: "opacity-100 translate-y-0 sm:scale-100"
37
+ To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
38
+ -->
39
+ <!-- HEADER -->
40
+ <%= tag.div class: "relative transform sm:rounded-lg bg-white text-left shadow-xl transition-all sm:m-6 w-full #{modal_size_class} hidden",
41
+ data: { turbo_modal_target: 'modal',
42
+ transition_enter: "ease-out duration-300",
43
+ transition_enter_start: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95",
44
+ transition_enter_end: "opacity-100 translate-y-0 sm:scale-100",
45
+ transition_leave: "ease-in duration-200",
46
+ transition_leave_start: "opacity-100 translate-y-0 sm:scale-100",
47
+ transition_leave_end: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" } do %>
48
+
49
+ <% if @title.present? %>
50
+ <!-- HEADER normal (com título) -->
51
+ <%= tag.div class: "flex items-center space-x-3 pl-7 pr-3 pt-1 print:hidden" do %>
52
+ <%= tag.div class: "block flex-1 truncate" do %>
53
+ <div class="flex items-center gap-x-2">
54
+ <% if @icon.present? %>
55
+ <%= lucide_icon @icon %>
56
+ <% end %>
57
+ <h5 class="text-primary w-fit text-nowrap font-semibold leading-6 pt-6 mt-0 <%= @options.fetch(:title_class, '') %>">
58
+ <%= @title %>
59
+ </h5>
60
+ </div>
61
+ <% end %>
62
+
63
+ <% unless @without_close.present? %>
64
+ <%= tag.div class: "block flex-shrink-0" do %>
65
+ <%= button_tag id: 'close_modal',
66
+ data: { action: "turbo-modal#hideModal" },
67
+ type: "button" do %>
68
+ <%= lucide_icon 'x' %>
69
+ <% end %>
70
+ <% end %>
71
+ <% end %>
72
+ <% end %>
73
+ <% else %>
74
+ <!-- Sem header: só o X absoluto no canto superior direito -->
75
+ <% unless @without_close.present? %>
76
+ <%= button_tag id: 'close_modal',
77
+ class: "absolute top-4 right-4 inline-flex items-center cursor-pointer justify-center print:hidden",
78
+ data: { action: "turbo-modal#hideModal" },
79
+ type: "button" do %>
80
+ <%= lucide_icon 'x' %>
81
+ <% end %>
82
+ <% end %>
83
+ <% end %>
84
+
85
+ <!-- BODY -->
86
+ <% if bodies.present? %>
87
+ <% bodies.each do |body| %>
88
+ <%= tag.div id: 'modal_body', class: "block sm:p-3 " do %>
89
+ <%= body %>
90
+ <% end %>
91
+ <% end %>
92
+ <% end %>
93
+
94
+ <% if content.present? %>
95
+ <%= tag.div class: "block p-7" do %>
96
+ <%= content %>
97
+ <% end %>
98
+ <% end %>
99
+ <% end %>
100
+ <% end %>
101
+ <% end %>
102
+ <% end %>
103
+ <% end %>
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodengageViewComponents
4
+ class TurboModalComponent < ApplicationComponent
5
+ renders_many :bodies, "CodengageViewComponents::BodyComponent"
6
+
7
+ def initialize(title: nil, icon: nil, size: :lg, without_close: false, options: {})
8
+ @title = title
9
+ @icon = icon
10
+ @size = size
11
+ @without_close = without_close
12
+ @options = options
13
+ end
14
+
15
+ def modal_size_class
16
+ case @size
17
+ when :sm
18
+ "sm:max-w-sm"
19
+ when :md
20
+ "sm:max-w-md"
21
+ when :lg
22
+ "sm:max-w-lg"
23
+ when :xl
24
+ "sm:max-w-xl"
25
+ when :xl2
26
+ "sm:max-w-2xl"
27
+ when :xl3
28
+ "sm:max-w-3xl"
29
+ when :xl4
30
+ "sm:max-w-4xl"
31
+ when :xl5
32
+ "sm:max-w-5xl"
33
+ when :xl6
34
+ "sm:max-w-6xl"
35
+ when :xl7
36
+ "sm:max-w-7xl"
37
+ when :xl8
38
+ "sm:max-w-[1500px]"
39
+ when :full
40
+ "sm:max-w-full"
41
+ else
42
+ "sm:max-w-lg"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,79 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+ import debounce from "lodash/debounce"
3
+
4
+ export default class extends Controller {
5
+ static targets = ["clear"]
6
+
7
+ connect() {
8
+ this.debouncedSubmit = debounce(() => {
9
+ this.element.querySelector("form")?.requestSubmit()
10
+ }, 300)
11
+
12
+ this.updateClearButtonVisibility()
13
+ }
14
+
15
+ onType(event) {
16
+ this.updateClearButtonVisibility()
17
+ this.debouncedSubmit()
18
+ }
19
+
20
+ onFilterChange(event) {
21
+ this.updateClearButtonVisibility()
22
+ this.element.querySelector("form")?.requestSubmit()
23
+ }
24
+
25
+ resetFilters(event) {
26
+ event.preventDefault()
27
+ const form = this.element.querySelector("form")
28
+ if (!form) return
29
+
30
+ form.reset()
31
+
32
+ const qInput = form.querySelector("input[name='q']")
33
+ if (qInput) qInput.value = ""
34
+
35
+ const selects = Array.from(form.querySelectorAll("select"))
36
+
37
+ selects.forEach(select => {
38
+ select.value = ""
39
+ select.dispatchEvent(new Event("change"))
40
+ })
41
+
42
+
43
+ if (this.hasClearTarget) {
44
+ this.clearTarget.classList.add("hidden")
45
+ this.clearTarget.classList.remove("flex")
46
+ }
47
+
48
+ form.requestSubmit()
49
+ }
50
+
51
+ updateClearButtonVisibility() {
52
+ if (!this.hasClearTarget) return
53
+
54
+ const form = this.element.querySelector("form")
55
+ const qInput = form.querySelector("input[name='q']")
56
+ const selects = Array.from(form.querySelectorAll("select"))
57
+
58
+ const hasSearch = qInput && qInput.value.trim().length > 0
59
+ const hasSelect = selects.some(select => select.value !== "")
60
+
61
+ const shouldShow = hasSearch || hasSelect
62
+
63
+ this.clearTarget.classList.toggle("hidden", !shouldShow)
64
+
65
+ if (shouldShow) {
66
+ this.clearTarget.classList.remove("hidden")
67
+ this.clearTarget.classList.add("flex")
68
+ } else {
69
+ this.clearTarget.classList.add("hidden")
70
+ this.clearTarget.classList.remove("flex")
71
+ }
72
+ }
73
+
74
+ disconnect() {
75
+ if (this.debouncedSubmit?.cancel) {
76
+ this.debouncedSubmit.cancel()
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,26 @@
1
+ import {Controller} from "@hotwired/stimulus"
2
+
3
+ export default class extends Controller {
4
+ static targets = ["bar", "pin", "button", "input"]
5
+
6
+ connect() {
7
+ if (this.hasInputTarget) {
8
+ if (this.inputTarget.value === 'true') {
9
+ this.buttonTarget.classList.add('toggle--active')
10
+ this.buttonTarget.dispatchEvent(new Event('change', { bubbles: true }))
11
+ }
12
+ } else {
13
+ if (this.buttonTarget.value === 'true') {
14
+ this.buttonTarget.classList.add('toggle--active')
15
+ this.buttonTarget.dispatchEvent(new Event('change', { bubbles: true }))
16
+ }
17
+ }
18
+ }
19
+
20
+
21
+ switch(event) {
22
+ this.buttonTarget.classList.toggle('toggle--active')
23
+ this.buttonTarget.dispatchEvent(new Event('change', { bubbles: true }))
24
+ this.inputTarget.value = this.buttonTarget.classList.contains('toggle--active')
25
+ }
26
+ }
data/config/importmap.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  pin_all_from File.expand_path("../app/javascript/controllers", __dir__), under: "controllers"
2
2
 
3
3
  pin "flowbite-datepicker", to: "https://cdn.jsdelivr.net/npm/flowbite-datepicker@1.3.0/dist/js/datepicker-full.js"
4
- pin "flowbite-datepicker-pt-BR", to: "https://cdn.jsdelivr.net/npm/flowbite-datepicker@1.3.0/dist/js/locales/pt-BR.js"
4
+ pin "flowbite-datepicker-pt-BR", to: "https://cdn.jsdelivr.net/npm/flowbite-datepicker@1.3.0/dist/js/locales/pt-BR.js"
5
+ pin "lodash", to: "https://ga.jspm.io/npm:lodash@4.17.21/lodash.js" # @4.17.21
6
+ pin "lodash/debounce", to: "https://ga.jspm.io/npm:lodash@4.17.21/debounce.js" # @4.17.21
@@ -1,3 +1,3 @@
1
1
  module CodengageViewComponents
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codengage_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Karlinski Baldo
@@ -92,16 +92,49 @@ files:
92
92
  - Rakefile
93
93
  - app/assets/stylesheets/codengage_view_components/application.css
94
94
  - app/components/codengage_view_components/application_component.rb
95
+ - app/components/codengage_view_components/body_component.html.haml
96
+ - app/components/codengage_view_components/body_component.rb
97
+ - app/components/codengage_view_components/card_component.css
98
+ - app/components/codengage_view_components/card_component.html.haml
99
+ - app/components/codengage_view_components/card_component.rb
100
+ - app/components/codengage_view_components/column_component.html.haml
101
+ - app/components/codengage_view_components/column_component.rb
95
102
  - app/components/codengage_view_components/date_field_component.css
96
103
  - app/components/codengage_view_components/date_field_component.html.haml
97
104
  - app/components/codengage_view_components/date_field_component.rb
98
105
  - app/components/codengage_view_components/dropdown_component.html.haml
99
106
  - app/components/codengage_view_components/dropdown_component.rb
107
+ - app/components/codengage_view_components/empty_state_action_component.html.haml
108
+ - app/components/codengage_view_components/empty_state_action_component.rb
109
+ - app/components/codengage_view_components/empty_state_component.html.haml
110
+ - app/components/codengage_view_components/empty_state_component.rb
100
111
  - app/components/codengage_view_components/flash_component.css
101
112
  - app/components/codengage_view_components/flash_component.html.haml
102
113
  - app/components/codengage_view_components/flash_component.rb
114
+ - app/components/codengage_view_components/header_component.html.haml
115
+ - app/components/codengage_view_components/header_component.rb
103
116
  - app/components/codengage_view_components/item_component.html.haml
104
117
  - app/components/codengage_view_components/item_component.rb
118
+ - app/components/codengage_view_components/item_table_component.html.haml
119
+ - app/components/codengage_view_components/item_table_component.rb
120
+ - app/components/codengage_view_components/paginator_component.html.haml
121
+ - app/components/codengage_view_components/paginator_component.rb
122
+ - app/components/codengage_view_components/search_form_component.css
123
+ - app/components/codengage_view_components/search_form_component.html.haml
124
+ - app/components/codengage_view_components/search_form_component.rb
125
+ - app/components/codengage_view_components/tab_item_component.css
126
+ - app/components/codengage_view_components/tab_item_component.html.haml
127
+ - app/components/codengage_view_components/tab_item_component.rb
128
+ - app/components/codengage_view_components/table_component.css
129
+ - app/components/codengage_view_components/table_component.html.haml
130
+ - app/components/codengage_view_components/table_component.rb
131
+ - app/components/codengage_view_components/toggle_component.css
132
+ - app/components/codengage_view_components/toggle_component.html.haml
133
+ - app/components/codengage_view_components/toggle_component.rb
134
+ - app/components/codengage_view_components/turbo_drawer_component.html.erb
135
+ - app/components/codengage_view_components/turbo_drawer_component.rb
136
+ - app/components/codengage_view_components/turbo_modal_component.html.erb
137
+ - app/components/codengage_view_components/turbo_modal_component.rb
105
138
  - app/controllers/codengage_view_components/application_controller.rb
106
139
  - app/controllers/codengage_view_components/pages_controller.rb
107
140
  - app/helpers/codengage_view_components/application_helper.rb
@@ -109,6 +142,8 @@ files:
109
142
  - app/javascript/controllers/datepicker_controller.js
110
143
  - app/javascript/controllers/flash_component_controller.js
111
144
  - app/javascript/controllers/index.js
145
+ - app/javascript/controllers/search_controller.js
146
+ - app/javascript/controllers/toggle_controller.js
112
147
  - app/jobs/codengage_view_components/application_job.rb
113
148
  - app/mailers/codengage_view_components/application_mailer.rb
114
149
  - app/models/codengage_view_components/application_record.rb