tramway 2.2.7 → 2.3

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -4
  3. data/app/components/{tailwinds → tramway}/back_button_component.rb +1 -1
  4. data/app/components/{tailwinds → tramway}/badge_component.rb +4 -2
  5. data/app/components/{tailwinds → tramway}/button_component.rb +3 -1
  6. data/app/components/tramway/chat_component.html.haml +28 -0
  7. data/app/components/tramway/chat_component.rb +17 -0
  8. data/app/components/tramway/chats/message_component.html.haml +26 -0
  9. data/app/components/tramway/chats/message_component.rb +58 -0
  10. data/app/components/tramway/chats/messages/container_component.html.haml +9 -0
  11. data/app/components/tramway/chats/messages/container_component.rb +32 -0
  12. data/app/components/tramway/chats/messages/table_component.html.haml +28 -0
  13. data/app/components/tramway/chats/messages/table_component.rb +12 -0
  14. data/app/components/tramway/chats.rb +7 -0
  15. data/app/components/{tailwinds/base_component.rb → tramway/colors_methods.rb} +3 -3
  16. data/app/components/{tailwinds → tramway}/containers/main_component.rb +1 -1
  17. data/app/components/{tailwinds → tramway}/containers/narrow_component.rb +1 -1
  18. data/app/components/{tailwinds → tramway}/flash_component.rb +5 -3
  19. data/app/components/{tailwinds → tramway}/form/builder.rb +8 -7
  20. data/app/components/{tailwinds → tramway}/form/checkbox_component.html.haml +1 -1
  21. data/app/components/{tailwinds → tramway}/form/checkbox_component.rb +1 -1
  22. data/app/components/{tailwinds → tramway}/form/date_field_component.html.haml +1 -1
  23. data/app/components/{tailwinds → tramway}/form/date_field_component.rb +1 -1
  24. data/app/components/{tailwinds → tramway}/form/datetime_field_component.html.haml +1 -1
  25. data/app/components/{tailwinds → tramway}/form/datetime_field_component.rb +1 -1
  26. data/app/components/{tailwinds → tramway}/form/file_field_component.rb +1 -1
  27. data/app/components/{tailwinds → tramway}/form/label_component.rb +1 -1
  28. data/app/components/{tailwinds → tramway}/form/multiselect/caret_component.rb +1 -1
  29. data/app/components/{tailwinds → tramway}/form/multiselect/dropdown_container_component.rb +1 -1
  30. data/app/components/{tailwinds → tramway}/form/multiselect/item_container_component.rb +1 -1
  31. data/app/components/{tailwinds → tramway}/form/multiselect/select_as_input_component.rb +1 -1
  32. data/app/components/{tailwinds → tramway}/form/multiselect/selected_item_template_component.rb +1 -1
  33. data/app/components/{tailwinds → tramway}/form/multiselect_component.html.haml +3 -3
  34. data/app/components/{tailwinds → tramway}/form/multiselect_component.rb +5 -5
  35. data/app/components/{tailwinds → tramway}/form/number_field_component.html.haml +1 -1
  36. data/app/components/{tailwinds → tramway}/form/number_field_component.rb +1 -1
  37. data/app/components/{tailwinds → tramway}/form/select_component.html.haml +1 -1
  38. data/app/components/{tailwinds → tramway}/form/select_component.rb +1 -1
  39. data/app/components/{tailwinds → tramway}/form/text_area_component.html.haml +1 -1
  40. data/app/components/{tailwinds → tramway}/form/text_area_component.rb +1 -1
  41. data/app/components/{tailwinds → tramway}/form/text_field_component.html.haml +1 -1
  42. data/app/components/{tailwinds → tramway}/form/text_field_component.rb +1 -1
  43. data/app/components/tramway/native_text_component.html.haml +3 -0
  44. data/app/components/tramway/native_text_component.rb +27 -0
  45. data/app/components/{tailwinds → tramway}/nav/item/button_component.rb +2 -2
  46. data/app/components/{tailwinds → tramway}/nav/item/link_component.rb +2 -2
  47. data/app/components/{tailwinds → tramway}/nav/item_component.rb +1 -1
  48. data/app/components/{tailwinds → tramway}/navbar_component.rb +1 -1
  49. data/app/components/{tailwinds → tramway}/pagination/base.rb +1 -1
  50. data/app/components/{tailwinds → tramway}/pagination/first_page_component.rb +2 -2
  51. data/app/components/{tailwinds → tramway}/pagination/gap_component.rb +1 -1
  52. data/app/components/{tailwinds → tramway}/pagination/last_page_component.rb +2 -2
  53. data/app/components/{tailwinds → tramway}/pagination/next_page_component.rb +2 -2
  54. data/app/components/{tailwinds → tramway}/pagination/page_component.rb +2 -2
  55. data/app/components/{tailwinds → tramway}/pagination/prev_page_component.rb +2 -2
  56. data/app/components/{tailwinds → tramway}/table/cell_component.rb +1 -1
  57. data/app/components/{tailwinds → tramway}/table/header_component.rb +1 -1
  58. data/app/components/{tailwinds → tramway}/table/row/preview_component.rb +1 -1
  59. data/app/components/{tailwinds → tramway}/table/row_component.rb +1 -1
  60. data/app/components/{tailwinds → tramway}/table_component.html.haml +1 -1
  61. data/app/components/{tailwinds → tramway}/table_component.rb +1 -1
  62. data/app/components/{tailwinds → tramway}/title_component.rb +1 -1
  63. data/app/views/kaminari/_first_page.html.haml +1 -1
  64. data/app/views/kaminari/_gap.html.haml +1 -1
  65. data/app/views/kaminari/_last_page.html.haml +1 -1
  66. data/app/views/kaminari/_next_page.html.haml +1 -1
  67. data/app/views/kaminari/_page.html.haml +1 -1
  68. data/app/views/kaminari/_prev_page.html.haml +1 -1
  69. data/config/locales/en.yml +4 -0
  70. data/config/tailwind.config.js +76 -1
  71. data/docs/AGENTS.md +5 -0
  72. data/lib/tramway/helpers/navbar_helper.rb +1 -1
  73. data/lib/tramway/helpers/views_helper.rb +27 -15
  74. data/lib/tramway/navbar.rb +4 -4
  75. data/lib/tramway/version.rb +1 -1
  76. metadata +88 -77
  77. /data/app/components/{tailwinds → tramway}/back_button_component.html.haml +0 -0
  78. /data/app/components/{tailwinds → tramway}/badge_component.html.haml +0 -0
  79. /data/app/components/{tailwinds → tramway}/button_component.html.haml +0 -0
  80. /data/app/components/{tailwinds → tramway}/containers/main_component.html.haml +0 -0
  81. /data/app/components/{tailwinds → tramway}/containers/narrow_component.html.haml +0 -0
  82. /data/app/components/{tailwinds → tramway}/flash_component.html.haml +0 -0
  83. /data/app/components/{tailwinds → tramway}/form/file_field_component.html.haml +0 -0
  84. /data/app/components/{tailwinds → tramway}/form/label_component.html.haml +0 -0
  85. /data/app/components/{tailwinds → tramway}/form/multiselect/caret_component.html.haml +0 -0
  86. /data/app/components/{tailwinds → tramway}/form/multiselect/dropdown_container_component.html.haml +0 -0
  87. /data/app/components/{tailwinds → tramway}/form/multiselect/item_container_component.html.haml +0 -0
  88. /data/app/components/{tailwinds → tramway}/form/multiselect/select_as_input_component.html.haml +0 -0
  89. /data/app/components/{tailwinds → tramway}/form/multiselect/selected_item_template_component.html.haml +0 -0
  90. /data/app/components/{tailwinds → tramway}/nav/item/button_component.html.haml +0 -0
  91. /data/app/components/{tailwinds → tramway}/nav/item/link_component.html.haml +0 -0
  92. /data/app/components/{tailwinds → tramway}/navbar_component.html.haml +0 -0
  93. /data/app/components/{tailwinds → tramway}/pagination/first_page_component.html.haml +0 -0
  94. /data/app/components/{tailwinds → tramway}/pagination/gap_component.html.haml +0 -0
  95. /data/app/components/{tailwinds → tramway}/pagination/last_page_component.html.haml +0 -0
  96. /data/app/components/{tailwinds → tramway}/pagination/next_page_component.html.haml +0 -0
  97. /data/app/components/{tailwinds → tramway}/pagination/page_component.html.haml +0 -0
  98. /data/app/components/{tailwinds → tramway}/pagination/prev_page_component.html.haml +0 -0
  99. /data/app/components/{tailwinds → tramway}/table/cell_component.html.haml +0 -0
  100. /data/app/components/{tailwinds → tramway}/table/header_component.html.haml +0 -0
  101. /data/app/components/{tailwinds → tramway}/table/row/preview_component.html.haml +0 -0
  102. /data/app/components/{tailwinds → tramway}/table/row_component.html.haml +0 -0
  103. /data/app/components/{tailwinds → tramway}/title_component.html.haml +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 908989b8908005e2022039beec8b7b47c4a7200166c77fe33c2dd27891d2fe58
4
- data.tar.gz: b57f2f3717522d10885d7ba83464590ff21ce87fa24af5c46deb85b0fac806cd
3
+ metadata.gz: c7533942aab1b11f547036f0ff9e819c9162d30c3cc11221e578f175d9b3215b
4
+ data.tar.gz: 52f17dda1d18d9c1c93f91e3a5a372a7a0b38957e220bbdc0fc25f7d6ff3c5d1
5
5
  SHA512:
6
- metadata.gz: 7824108d8dfe9a0c3da312a26d12a84fe1df9424550c6edb29b864634109cc793e883a9f13ff90a7ab40d2e9b833cc6068194055410837cb554dd0e467f802f7
7
- data.tar.gz: befb3fe2ad460b34f002ffd58b01ab4c1f9996ff5f402e714bb54b6fa013091004b55e7ed8b558b551dd017bba4609c01072370eae034b77c51f978a8703fa4e
6
+ metadata.gz: b7e1e85e67d07628c99411d29945c7cc102dce00278abc83c88999e8880ef11082a3a304ba792f6daca306c8ef65cdffbeaabfcabf523016ed3fb1d9c42a35cc
7
+ data.tar.gz: dba51b7a03411bac7f6cbe4b7b1e4049a13f9863e3a943ecc0fce58cae17471b29c6b14cd24d4aef6f4e7a41d44afe06bccd8d6fd6e2801d72c0550bb205a92d
data/README.md CHANGED
@@ -17,6 +17,7 @@ that helps you generate good, Tramway-native code with all the framework feature
17
17
  * [Tramway Form](https://github.com/Purple-Magic/tramway#tramway-form)
18
18
  * [Tramway Navbar](https://github.com/Purple-Magic/tramway#tramway-navbar)
19
19
  * [Tramway Flash](https://github.com/Purple-Magic/tramway#tramway-flash)
20
+ * [Tramway Chat](https://github.com/Purple-Magic/tramway#tramway-chat)
20
21
  * [Tramway Table Component](https://github.com/Purple-Magic/tramway#tramway-table-component)
21
22
  * [Tailwind-styled forms](https://github.com/Purple-Magic/tramway#tailwind-styled-forms)
22
23
  * [Stimulus-based inputs](https://github.com/Purple-Magic/tramway#stimulus-based-inputs)
@@ -856,6 +857,36 @@ custom HTML options directly (e.g., `class:`, `data:`) and they will be merged i
856
857
  Use the `type` argument is compatible to [Lantern Color Palette](https://github.com/TrinityMonsters/tramway/blob/main/README.md#lantern-color-palette) or provide a `color:` keyword to set
857
858
  the Tailwind color family explicitly.
858
859
 
860
+ ### Tramway Chat
861
+
862
+ `tramway_chat` renders the chat experience bundled with Tramway. Provide a chat ID, a list of message hashes, and the URL
863
+ that receives new messages. Each message must include an `:id` and a `:type` (either `:sent` or `:received`). Additional
864
+ message fields like `text`, `data`, or `sent_at` are forwarded to `tramway/chats/message_component`.
865
+
866
+ ```haml
867
+ -# Haml example
868
+ - messages = [
869
+ - { id: 1, type: :received, text: 'Hello 👋' },
870
+ - { id: 2, type: :sent, text: 'Hi there!' }
871
+ - ]
872
+ = tramway_chat chat_id: 'support-chat',
873
+ messages: messages,
874
+ message_form: @message_form,
875
+ send_message_path: chat_messages_path
876
+ ```
877
+
878
+ ```erb
879
+ <%# ERB example %>
880
+ <% messages = [{ id: 1, type: :received, text: 'Hello 👋' }] %>
881
+ <%= tramway_chat chat_id: 'support-chat',
882
+ messages: messages,
883
+ message_form: @message_form,
884
+ send_message_path: chat_messages_path %>
885
+ ```
886
+
887
+ If you do not want to render the message form, pass `message_form: nil`. When the form is present, `send_message_path` is
888
+ required and the helper will generate the correct POST form.
889
+
859
890
  ### Tramway Table Component
860
891
 
861
892
  Tramway provides a responsive, tailwind-styled table with light and dark themes. Use the `tramway_table`, `tramway_row`, and
@@ -877,7 +908,7 @@ implementations.
877
908
  <% end %>
878
909
  ```
879
910
 
880
- `tramway_table` accepts the same optional `options` hash as `Tailwinds::TableComponent`. The hash is forwarded as HTML
911
+ `tramway_table` accepts the same optional `options` hash as `Tramway::TableComponent`. The hash is forwarded as HTML
881
912
  attributes, so you can pass things like `id`, `data` attributes, or additional classes. If you do not supply your own width
882
913
  utility (e.g. a class that starts with `w-`), the component automatically appends `w-full` to keep the table responsive. This
883
914
  allows you to extend the default styling without losing the sensible defaults provided by the component.
@@ -901,12 +932,12 @@ Use the optional `href:` argument on `tramway_row` to turn an entire row into a
901
932
  ```
902
933
 
903
934
  When you render a header you can either pass the `headers:` array, as in the examples above, or render custom header content in
904
- the block. `Tailwinds::Table::HeaderComponent` uses the length of the `headers` array to build the grid if the array is present.
935
+ the block. `tramway_header` uses the length of the `headers` array to build the grid if the array is present.
905
936
  If you omit the array and provide custom content, pass the `columns:` argument so the component knows how many grid columns to
906
937
  generate.
907
938
 
908
939
  ```erb
909
- <%= component 'tailwinds/table/header', columns: 4 do %>
940
+ <%= tramway_header columns: 4 do %>
910
941
  <%= tramway_cell do %>
911
942
  Custom header cell
912
943
  <% end %>
@@ -1067,7 +1098,7 @@ Available form helpers:
1067
1098
 
1068
1099
  *app/views/sessions/new.html.erb*
1069
1100
  ```erb
1070
- <%= form_with url: login_path, scope: :session, local: true, builder: Tailwinds::Form::Builder do |form| %>
1101
+ <%= form_with url: login_path, scope: :session, local: true, builder: Tramway::Form::Builder do |form| %>
1071
1102
  <%= form.email_field :email %>
1072
1103
  <%= form.password_field :password %>
1073
1104
  <%= form.submit 'Log in' %>
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  # Backbutton component
5
5
  class BackButtonComponent < BaseComponent
6
6
  def back_button_classes
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  # Default Tramway badge
5
5
  #
6
- class BadgeComponent < Tailwinds::BaseComponent
6
+ class BadgeComponent < Tramway::BaseComponent
7
7
  option :text
8
8
  option :type, optional: true
9
9
  option :color, optional: true
10
10
 
11
+ include Tramway::ColorsMethods
12
+
11
13
  def classes
12
14
  theme_classes(
13
15
  classic: [
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  # Default Tramway button
5
5
  #
6
6
  class ButtonComponent < BaseComponent
@@ -14,6 +14,8 @@ module Tailwinds
14
14
  option :options, optional: true, default: -> { {} }
15
15
  option :form_options, optional: true, default: -> { {} }
16
16
 
17
+ include Tramway::ColorsMethods
18
+
17
19
  def before_render
18
20
  return if tag.present?
19
21
 
@@ -0,0 +1,28 @@
1
+ = helpers.turbo_stream_from chat_id, 'messages'
2
+
3
+ .flex-1.min-h-0.flex.flex-col
4
+ #chat.mx-auto.flex.flex-1.flex-col.w-full.rounded-2xl.border.shadow-sm.ring-gray-700.md:p-4.border-gray-100.min-h-0.overflow-hidden{ data: { controller: 'chat' } }
5
+ .flex-1.min-h-0.overflow-y-auto.p-2.md:p-6.space-y-2.md:space-y-4.md:rounded-xl.rounded-t-xl#messages{ data: { chat_target: 'messages' }, class: 'text-gray-100 bg-gray-800/60' }
6
+ - messages.each do |message|
7
+ = component "tramway/chats/message", **message
8
+ - if disabled?
9
+ = inline_svg 'icons/dots.svg', class: 'w-8 h-8 text-gray-500 mx-auto my-4'
10
+
11
+ - if message_form.present?
12
+ .shrink-0.border-gray-200.md:pt-2.border-gray-700
13
+ = form_for message_form, url: send_message_path, method: :post, html: { class: 'flex items-center md:gap-1' } do |f|
14
+ - waiting_placeholder = t('chat.placeholders.waiting')
15
+ - typing_placeholder = t('chat.placeholders.type')
16
+ = f.text_field :text,
17
+ class: 'flex-1 md:rounded-full rounded-bl-2xl md:border border-gray-300 px-4 py-2 text-sm text-gray-900 shadow-sm placeholder:text-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-200 disabled:cursor-not-allowed disabled:bg-gray-100 border-gray-600 bg-gray-800 text-white focus:border-blue-400 focus:ring-blue-500/30',
18
+ placeholder: send_messages_enabled ? typing_placeholder : waiting_placeholder,
19
+ data: { chat_target: 'input' },
20
+ disabled: !send_messages_enabled
21
+
22
+ = f.hidden_field :chat_id, value: chat_id
23
+
24
+ - options.each do |(key, value)|
25
+ = f.hidden_field key, value: value
26
+
27
+ = f.submit '🡩',
28
+ class: 'md:rounded-full bg-blue-600 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-200 bg-blue-500 hover:bg-blue-400 cursor-pointer'
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ # Renders the chat container with messages and optional input form.
5
+ class ChatComponent < Tramway::BaseComponent
6
+ option :chat_id
7
+ option :messages
8
+ option :message_form, optional: true, default: -> {}
9
+ option :options, optional: true, default: -> { {} }
10
+ option :send_message_path
11
+ option :send_messages_enabled, optional: true, default: -> { true }
12
+
13
+ def disabled?
14
+ options[:disabled]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ - if on_the_left?
2
+ = component 'tramway/chats/messages/container',
3
+ position: :left,
4
+ text:,
5
+ sent_at:,
6
+ show_sent_at: show_sent_at? do
7
+ - if data_view == :table
8
+ = component 'tramway/chats/messages/table', data:
9
+
10
+ - if on_the_right?
11
+ = component 'tramway/chats/messages/container',
12
+ position: :right,
13
+ text:,
14
+ sent_at:,
15
+ show_sent_at: show_sent_at? do
16
+
17
+ - if pending?
18
+ .pb-1
19
+ = inline_svg 'icons/spinner.svg', class: 'w-4 h-4 text-white animate-spin'
20
+
21
+ - if failed?
22
+ .pb-1
23
+ = inline_svg 'icons/cross.svg', class: 'w-6 h-6 text-red-200'
24
+
25
+ - if data_view == :table
26
+ = component 'tramway/chats/messages/table', data:
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Chats
5
+ # Renders a single chat message with alignment and state styling.
6
+ class MessageComponent < Tramway::BaseComponent
7
+ option :type
8
+ option :text, optional: true, default: -> { '' }
9
+ option :data, optional: true, default: -> { {} }
10
+ option :sent_at, optional: true, default: -> {}
11
+ option :options, optional: true, default: -> { {} }
12
+
13
+ def data_view
14
+ if data.nil?
15
+ nil
16
+ elsif array_2d?(data)
17
+ :table
18
+ end
19
+ end
20
+
21
+ def text_color
22
+ if pending?
23
+ 'text-gray-400 dark:text-gray-600'
24
+ else
25
+ 'text-black dark:text-white'
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def array_2d?(array)
32
+ array.is_a?(Array) && array.all? do |inner|
33
+ inner.is_a?(Array) && inner.none? { |e| e.is_a?(Array) }
34
+ end
35
+ end
36
+
37
+ def on_the_left?
38
+ type.to_sym == :received
39
+ end
40
+
41
+ def on_the_right?
42
+ type.to_sym == :sent
43
+ end
44
+
45
+ def show_sent_at?
46
+ sent_at.present?
47
+ end
48
+
49
+ def pending?
50
+ options[:pending]
51
+ end
52
+
53
+ def failed?
54
+ options[:failed]
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,9 @@
1
+ .flex.flex-col.gap-1{ class: position_classes }
2
+ - if text.present?
3
+ .max-w-lg.rounded-2xl.px-4.py-3.text-sm.shadow-sm.ring-1.text-white.ring-gray-700{ class: color_classes }
4
+ = component 'tramway/native_text', text:, klass: 'text-white'
5
+
6
+ - if sent_at.present?
7
+ .mt-2.text-right.text-xs.text-gray-400
8
+ = sent_at
9
+ = content
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Chats
5
+ module Messages
6
+ # Renders a message container with alignment and color styles.
7
+ class ContainerComponent < Tramway::BaseComponent
8
+ option :position
9
+ option :text
10
+ option :sent_at
11
+
12
+ def position_classes
13
+ case position.to_sym
14
+ when :left
15
+ %w[items-start]
16
+ when :right
17
+ %w[items-end]
18
+ end.join(' ')
19
+ end
20
+
21
+ def color_classes
22
+ case position.to_sym
23
+ when :left
24
+ %w[bg-gray-800 rounded-tl-md]
25
+ when :right
26
+ %w[bg-blue-600 rounded-tr-md]
27
+ end.join(' ')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ .mt-3.overflow-hidden.rounded-xl.border.border-gray-200.bg-white.shadow-sm.dark:border-gray-700.dark:bg-gray-900
2
+ = tramway_table do
3
+ - data.each_with_index do |row, index|
4
+ - if index.zero?
5
+ = tramway_header headers: row
6
+ - else
7
+ = tramway_row do
8
+ - cell_width = row.count > 1 ? "w-1/#{row.count + 1}" : 'w-full'
9
+
10
+ - row.each do |cell|
11
+ = tramway_cell do
12
+ - if cell.to_s.start_with?('http')
13
+ .underline
14
+ = link_to cell, cell, target: '_blank', class: "#{cell_width} break-all"
15
+ - elsif cell.is_a?(Hash)
16
+ - if cell['status'] == 'pending'
17
+ = tramway_cell do
18
+ = helpers.tramway_button text: t('admin.chats.messages.table.add'), path: cell.dig('button', 'path'), color: :green, method: :post
19
+ - elsif cell['status'] == 'added'
20
+ = tramway_cell do
21
+ = helpers.tramway_button text: t('admin.chats.messages.table.remove'), path: cell.dig('button', 'path'), color: :red, method: :delete
22
+ - else
23
+ = cell.inspect
24
+ - elsif cell.is_a?(String) && cell.size > 50
25
+ .text-sm
26
+ = cell
27
+ - else
28
+ = cell
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Chats
5
+ module Messages
6
+ # Renders a table view for message data payloads.
7
+ class TableComponent < BaseComponent
8
+ option :data
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ # Namespace for chat-related components.
5
+ module Chats
6
+ end
7
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
4
- # Shared base component for Tailwinds components
5
- class BaseComponent < Tramway::BaseComponent
3
+ module Tramway
4
+ # Color logic implementation
5
+ module ColorsMethods
6
6
  TYPE_COLOR_MAP = {
7
7
  default: :gray,
8
8
  life: :gray,
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Containers
5
5
  # Main container for tailwind-styled layout
6
6
  class MainComponent < Tramway::BaseComponent
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Containers
5
5
  # Default page container in Tramway
6
6
  class NarrowComponent < Tramway::BaseComponent
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
4
- # Description: A Tailwinds flash message component for displaying notifications.
5
- class FlashComponent < Tailwinds::BaseComponent
3
+ module Tramway
4
+ # Description: A Tramway flash message component for displaying notifications.
5
+ class FlashComponent < Tramway::BaseComponent
6
6
  option :text
7
7
  option :type, optional: true, default: -> {}
8
8
  option :color, optional: true, default: -> {}
9
9
  option :options, optional: true, default: -> { {} }
10
10
 
11
+ include Tramway::ColorsMethods
12
+
11
13
  def container_classes
12
14
  theme_classes(
13
15
  classic: 'fixed top-4 right-4 z-50 space-y-2'
@@ -2,12 +2,13 @@
2
2
 
3
3
  require 'tramway/utils/field'
4
4
 
5
- module Tailwinds
5
+ module Tramway
6
6
  module Form
7
7
  # Provides Tailwind-styled forms
8
8
  # rubocop:disable Metrics/ClassLength
9
9
  class Builder < Tramway::Views::FormBuilder
10
10
  include Tramway::Utils::Field
11
+ include Tramway::ColorsMethods
11
12
 
12
13
  def initialize(object_name, object, template, options)
13
14
  super
@@ -18,7 +19,7 @@ module Tailwinds
18
19
  def common_field(component_name, input_method, attribute, **options, &)
19
20
  sanitized_options = sanitize_options(options)
20
21
 
21
- component_class = "Tailwinds::Form::#{component_name.to_s.camelize}Component".constantize
22
+ component_class = "Tramway::Form::#{component_name.to_s.camelize}Component".constantize
22
23
 
23
24
  render(component_class.new(
24
25
  input: input(input_method),
@@ -47,7 +48,7 @@ module Tailwinds
47
48
  def password_field(attribute, **options, &)
48
49
  sanitized_options = sanitize_options(options)
49
50
 
50
- render(Tailwinds::Form::TextFieldComponent.new(
51
+ render(Tramway::Form::TextFieldComponent.new(
51
52
  input: input(:password_field),
52
53
  **default_options(attribute, sanitized_options)
53
54
  ), &)
@@ -65,7 +66,7 @@ module Tailwinds
65
66
  sanitized_options = sanitize_options(options)
66
67
  input = super(attribute, **sanitized_options.merge(class: :hidden))
67
68
 
68
- render(Tailwinds::Form::FileFieldComponent.new(input:, **default_options(attribute, sanitized_options)), &)
69
+ render(Tramway::Form::FileFieldComponent.new(input:, **default_options(attribute, sanitized_options)), &)
69
70
  end
70
71
 
71
72
  def check_box(attribute, **, &)
@@ -75,7 +76,7 @@ module Tailwinds
75
76
  def select(attribute, collection, **options, &)
76
77
  sanitized_options = sanitize_options(options)
77
78
 
78
- render(Tailwinds::Form::SelectComponent.new(
79
+ render(Tramway::Form::SelectComponent.new(
79
80
  input: input(:select),
80
81
  value: sanitized_options[:selected] || object.public_send(attribute),
81
82
  collection: explicitly_add_blank_option(collection, sanitized_options),
@@ -86,7 +87,7 @@ module Tailwinds
86
87
  def multiselect(attribute, collection, **options, &)
87
88
  sanitized_options = sanitize_options(options)
88
89
 
89
- render(Tailwinds::Form::MultiselectComponent.new(
90
+ render(Tramway::Form::MultiselectComponent.new(
90
91
  input: input(:text_field),
91
92
  value: sanitized_options[:value] || sanitized_options[:selected] || object.public_send(attribute),
92
93
  collection:,
@@ -98,7 +99,7 @@ module Tailwinds
98
99
  sanitized_options = sanitize_options(options)
99
100
 
100
101
  render(
101
- Tailwinds::ButtonComponent.new(
102
+ Tramway::ButtonComponent.new(
102
103
  text: action,
103
104
  size: form_size,
104
105
  type: :will,
@@ -3,5 +3,5 @@
3
3
  = @input.call @attribute, **@options.merge(class: classes)
4
4
  - if @label
5
5
  %div
6
- = component('tailwinds/form/label', for: @for) do
6
+ = component('tramway/form/label', for: @for) do
7
7
  = @label
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  # Tailwind-styled checkbox field
6
6
  class CheckboxComponent < TailwindComponent
@@ -1,6 +1,6 @@
1
1
  .mb-4
2
2
  - if @label
3
- = component('tailwinds/form/label', for: @for) do
3
+ = component('tramway/form/label', for: @for) do
4
4
  = @label
5
5
  - classes = "#{size_class(:text_input)} #{text_input_base_classes}"
6
6
  = @input.call @attribute, **@options.merge(class: classes), value: @value
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  # Tailwind-styled date field
6
6
  class DateFieldComponent < TailwindComponent
@@ -1,6 +1,6 @@
1
1
  .mb-4
2
2
  - if @label
3
- = component('tailwinds/form/label', for: @for) do
3
+ = component('tramway/form/label', for: @for) do
4
4
  = @label
5
5
  - classes = "#{size_class(:text_input)} #{text_input_base_classes}"
6
6
  = @input.call @attribute, **@options.merge(class: classes), value: @value
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  # Tailwind-styled datetime field
6
6
  class DatetimeFieldComponent < TailwindComponent
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  # Tailwind-styled file_field input
6
6
  class FileFieldComponent < TailwindComponent
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  # Form label for all tailwind-styled forms
6
6
  class LabelComponent < Tramway::BaseComponent
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  module Multiselect
6
6
  # Caret icon component
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  module Multiselect
6
6
  # Container for dropdown component
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  module Multiselect
6
6
  # Container for item in dropdown component
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  module Multiselect
6
6
  # Renders input as select
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  module Multiselect
6
6
  # Tailwind-styled multi-select field
@@ -1,6 +1,6 @@
1
1
  .mb-4.relative
2
2
  - if @label
3
- = component('tailwinds/form/label', for: @for) do
3
+ = component('tramway/form/label', for: @for) do
4
4
  = @label
5
5
  %div{ role: :combobox, data: multiselect_hash, id: "#{@for}_multiselect" }
6
6
  - classes = "#{size_class(:multiselect_input)} #{select_base_classes}"
@@ -8,6 +8,6 @@
8
8
  .flex.flex-row.flex-nowrap.overflow-x-auto.space-x-1{ data: { "multiselect-target" => "showSelectedArea" } }
9
9
  .flex.flex-col.justify-center
10
10
  .caret-down{ data: { "multiselect-target" => "caretDown" } }
11
- = component 'tailwinds/form/multiselect/caret', size: size, direction: :down
11
+ = component 'tramway/form/multiselect/caret', size: size, direction: :down
12
12
  .caret-up.hidden{ data: { "multiselect-target" => "caretUp" } }
13
- = component 'tailwinds/form/multiselect/caret', size: size, direction: :up
13
+ = component 'tramway/form/multiselect/caret', size: size, direction: :up
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Tailwinds
3
+ module Tramway
4
4
  module Form
5
5
  # Tailwind-styled multi-select field
6
6
  class MultiselectComponent < TailwindComponent
@@ -73,7 +73,7 @@ module Tailwinds
73
73
 
74
74
  def select_as_input
75
75
  component(
76
- 'tailwinds/form/multiselect/select_as_input',
76
+ 'tramway/form/multiselect/select_as_input',
77
77
  options:,
78
78
  attribute:,
79
79
  input:,
@@ -96,15 +96,15 @@ module Tailwinds
96
96
  end
97
97
 
98
98
  def selected_item_template
99
- component('tailwinds/form/multiselect/selected_item_template', size:)
99
+ component('tramway/form/multiselect/selected_item_template', size:)
100
100
  end
101
101
 
102
102
  def dropdown_container
103
- component('tailwinds/form/multiselect/dropdown_container', size:)
103
+ component('tramway/form/multiselect/dropdown_container', size:)
104
104
  end
105
105
 
106
106
  def item_container
107
- component('tailwinds/form/multiselect/item_container', size:)
107
+ component('tramway/form/multiselect/item_container', size:)
108
108
  end
109
109
  end
110
110
  end