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.
- checksums.yaml +4 -4
- data/README.md +35 -4
- data/app/components/{tailwinds → tramway}/back_button_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/badge_component.rb +4 -2
- data/app/components/{tailwinds → tramway}/button_component.rb +3 -1
- data/app/components/tramway/chat_component.html.haml +28 -0
- data/app/components/tramway/chat_component.rb +17 -0
- data/app/components/tramway/chats/message_component.html.haml +26 -0
- data/app/components/tramway/chats/message_component.rb +58 -0
- data/app/components/tramway/chats/messages/container_component.html.haml +9 -0
- data/app/components/tramway/chats/messages/container_component.rb +32 -0
- data/app/components/tramway/chats/messages/table_component.html.haml +28 -0
- data/app/components/tramway/chats/messages/table_component.rb +12 -0
- data/app/components/tramway/chats.rb +7 -0
- data/app/components/{tailwinds/base_component.rb → tramway/colors_methods.rb} +3 -3
- data/app/components/{tailwinds → tramway}/containers/main_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/containers/narrow_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/flash_component.rb +5 -3
- data/app/components/{tailwinds → tramway}/form/builder.rb +8 -7
- data/app/components/{tailwinds → tramway}/form/checkbox_component.html.haml +1 -1
- data/app/components/{tailwinds → tramway}/form/checkbox_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/date_field_component.html.haml +1 -1
- data/app/components/{tailwinds → tramway}/form/date_field_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/datetime_field_component.html.haml +1 -1
- data/app/components/{tailwinds → tramway}/form/datetime_field_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/file_field_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/label_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/multiselect/caret_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/multiselect/dropdown_container_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/multiselect/item_container_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/multiselect/select_as_input_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/multiselect/selected_item_template_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/multiselect_component.html.haml +3 -3
- data/app/components/{tailwinds → tramway}/form/multiselect_component.rb +5 -5
- data/app/components/{tailwinds → tramway}/form/number_field_component.html.haml +1 -1
- data/app/components/{tailwinds → tramway}/form/number_field_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/select_component.html.haml +1 -1
- data/app/components/{tailwinds → tramway}/form/select_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/text_area_component.html.haml +1 -1
- data/app/components/{tailwinds → tramway}/form/text_area_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/form/text_field_component.html.haml +1 -1
- data/app/components/{tailwinds → tramway}/form/text_field_component.rb +1 -1
- data/app/components/tramway/native_text_component.html.haml +3 -0
- data/app/components/tramway/native_text_component.rb +27 -0
- data/app/components/{tailwinds → tramway}/nav/item/button_component.rb +2 -2
- data/app/components/{tailwinds → tramway}/nav/item/link_component.rb +2 -2
- data/app/components/{tailwinds → tramway}/nav/item_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/navbar_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/pagination/base.rb +1 -1
- data/app/components/{tailwinds → tramway}/pagination/first_page_component.rb +2 -2
- data/app/components/{tailwinds → tramway}/pagination/gap_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/pagination/last_page_component.rb +2 -2
- data/app/components/{tailwinds → tramway}/pagination/next_page_component.rb +2 -2
- data/app/components/{tailwinds → tramway}/pagination/page_component.rb +2 -2
- data/app/components/{tailwinds → tramway}/pagination/prev_page_component.rb +2 -2
- data/app/components/{tailwinds → tramway}/table/cell_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/table/header_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/table/row/preview_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/table/row_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/table_component.html.haml +1 -1
- data/app/components/{tailwinds → tramway}/table_component.rb +1 -1
- data/app/components/{tailwinds → tramway}/title_component.rb +1 -1
- data/app/views/kaminari/_first_page.html.haml +1 -1
- data/app/views/kaminari/_gap.html.haml +1 -1
- data/app/views/kaminari/_last_page.html.haml +1 -1
- data/app/views/kaminari/_next_page.html.haml +1 -1
- data/app/views/kaminari/_page.html.haml +1 -1
- data/app/views/kaminari/_prev_page.html.haml +1 -1
- data/config/locales/en.yml +4 -0
- data/config/tailwind.config.js +76 -1
- data/docs/AGENTS.md +5 -0
- data/lib/tramway/helpers/navbar_helper.rb +1 -1
- data/lib/tramway/helpers/views_helper.rb +27 -15
- data/lib/tramway/navbar.rb +4 -4
- data/lib/tramway/version.rb +1 -1
- metadata +88 -77
- /data/app/components/{tailwinds → tramway}/back_button_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/badge_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/button_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/containers/main_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/containers/narrow_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/flash_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/form/file_field_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/form/label_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/form/multiselect/caret_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/form/multiselect/dropdown_container_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/form/multiselect/item_container_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/form/multiselect/select_as_input_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/form/multiselect/selected_item_template_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/nav/item/button_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/nav/item/link_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/navbar_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/pagination/first_page_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/pagination/gap_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/pagination/last_page_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/pagination/next_page_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/pagination/page_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/pagination/prev_page_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/table/cell_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/table/header_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/table/row/preview_component.html.haml +0 -0
- /data/app/components/{tailwinds → tramway}/table/row_component.html.haml +0 -0
- /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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c7533942aab1b11f547036f0ff9e819c9162d30c3cc11221e578f175d9b3215b
|
|
4
|
+
data.tar.gz: 52f17dda1d18d9c1c93f91e3a5a372a7a0b38957e220bbdc0fc25f7d6ff3c5d1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 `
|
|
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. `
|
|
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
|
-
<%=
|
|
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:
|
|
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,13 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module Tramway
|
|
4
4
|
# Default Tramway badge
|
|
5
5
|
#
|
|
6
|
-
class BadgeComponent <
|
|
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
|
|
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
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
4
|
-
#
|
|
5
|
-
|
|
3
|
+
module Tramway
|
|
4
|
+
# Color logic implementation
|
|
5
|
+
module ColorsMethods
|
|
6
6
|
TYPE_COLOR_MAP = {
|
|
7
7
|
default: :gray,
|
|
8
8
|
life: :gray,
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
4
|
-
# Description: A
|
|
5
|
-
class FlashComponent <
|
|
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
|
|
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 = "
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
102
|
+
Tramway::ButtonComponent.new(
|
|
102
103
|
text: action,
|
|
103
104
|
size: form_size,
|
|
104
105
|
type: :will,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
.mb-4
|
|
2
2
|
- if @label
|
|
3
|
-
= component('
|
|
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
|
.mb-4
|
|
2
2
|
- if @label
|
|
3
|
-
= component('
|
|
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
|
.mb-4.relative
|
|
2
2
|
- if @label
|
|
3
|
-
= component('
|
|
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 '
|
|
11
|
+
= component 'tramway/form/multiselect/caret', size: size, direction: :down
|
|
12
12
|
.caret-up.hidden{ data: { "multiselect-target" => "caretUp" } }
|
|
13
|
-
= component '
|
|
13
|
+
= component 'tramway/form/multiselect/caret', size: size, direction: :up
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
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
|
-
'
|
|
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('
|
|
99
|
+
component('tramway/form/multiselect/selected_item_template', size:)
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
def dropdown_container
|
|
103
|
-
component('
|
|
103
|
+
component('tramway/form/multiselect/dropdown_container', size:)
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def item_container
|
|
107
|
-
component('
|
|
107
|
+
component('tramway/form/multiselect/item_container', size:)
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
end
|