tramway 3.1.1.3 → 3.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fdfbb8e7d69f349ee20bc52b7fe51f9a150c09bceb8d7892804d33dd926e36d8
4
- data.tar.gz: e5b62beadc816266f03fbfc49a1a72ec2ffc7883ec59930192b5bc76f2e701c2
3
+ metadata.gz: b60bf123066d7c59336dba45b1dae5ab6a90b36fd54063c73f04d4fcac17ba21
4
+ data.tar.gz: d1512dee19a6f92b27791ad9b6b40582e0b0e90b7ef2a6304e7d1846d7d05930
5
5
  SHA512:
6
- metadata.gz: b550f718d7f5c954f9606b5cea2deed8144336b4e5d05ab51ab33a16544c90fb78ffea04a378b43002c55687e723789944f196ce9f22b0335aeb436e0520829c
7
- data.tar.gz: 502e0c85c6f0a28ef46d22958147a5ba3b55b6350f8d710b34bd35354a68165be61c938c87e3414caf5436b7b78c4c802b409560a65d3fa52022e2bf64b7fab7
6
+ metadata.gz: fbe4b415c8fc353f3be1453064072dc34864181f795f92c631ff2776af7fa060f0c0ab893149b8e3fb1702365b9f56c286b038424bff034b6ec3a1a6c13156b8
7
+ data.tar.gz: 4a403cd5695f25bf309feceed280afdf9cc489eff25dd1d37bf766b2714aff4fd22cf6d0fbf460659b115258bd9b89f6b10bb5c419c228a077d97272921222c8
data/README.md CHANGED
@@ -53,7 +53,8 @@ bin/rails g tramway:install
53
53
  ```
54
54
 
55
55
  The install generator adds the required gems (`haml-rails`, `kaminari`, `view_component`, `dry-initializer`, and `dry-monads`) to your
56
- application's Gemfile—if they are not present—and appends the Tailwind safelist configuration Tramway ships with.
56
+ application's Gemfile—if they are not present—appends the Tailwind safelist configuration Tramway ships with, and injects the
57
+ Trix stylesheet and JavaScript tags into your application layout (required for `rich_text_area`).
57
58
 
58
59
  ## Getting Started
59
60
 
@@ -1203,6 +1204,7 @@ Checkboxes render dark while unchecked and use the light primary checked state.
1203
1204
  <%= f.select :role, [:admin, :user] %>
1204
1205
  <%= f.date_field :birth_date %>
1205
1206
  <%= f.datetime_field :confirmed_at %>
1207
+ <%= f.rich_text_area :bio %>
1206
1208
  <%= f.tramway_select :permissions, [['Create User', 'create_user'], ['Update user', 'update_user']] %>
1207
1209
  <%= f.file_field :file %>
1208
1210
  <%= f.submit 'Create User' %>
@@ -1238,10 +1240,12 @@ Available form helpers:
1238
1240
  * password_field
1239
1241
  * file_field
1240
1242
  * check_box
1243
+ * checkbox (alias for check_box)
1241
1244
  * select
1242
1245
  * date_field
1243
1246
  * datetime_field
1244
1247
  * time_field
1248
+ * rich_text_area (Action Text/Trix editor with Tramway dark form classes)
1245
1249
  * tramway_select ([Stimulus-based](https://github.com/Purple-Magic/tramway#stimulus-based-inputs))
1246
1250
  * submit
1247
1251
 
@@ -1283,6 +1287,60 @@ same select field.
1283
1287
  <% end %>
1284
1288
  ```
1285
1289
 
1290
+ #### Rich text area
1291
+
1292
+ `rich_text_area` (and its alias `rich_textarea`) renders a [Trix](https://trix-editor.org/) rich text editor
1293
+ with Tramway's dark-theme Tailwind styling. Trix is bundled with Rails and does not require an additional gem.
1294
+
1295
+ Before using `rich_text_area`, the Trix stylesheet and JavaScript must be present in your application layout.
1296
+ The `tramway:install` generator adds them automatically. To add them manually:
1297
+
1298
+ ```haml
1299
+ -# app/views/layouts/application.html.haml
1300
+ = stylesheet_link_tag "trix", "data-turbo-track": "reload"
1301
+ = javascript_include_tag "trix", "data-turbo-track": "reload", defer: true
1302
+ ```
1303
+
1304
+ ```erb
1305
+ <%# app/views/layouts/application.html.erb %>
1306
+ <%= stylesheet_link_tag "trix", "data-turbo-track": "reload" %>
1307
+ <%= javascript_include_tag "trix", "data-turbo-track": "reload", defer: true %>
1308
+ ```
1309
+
1310
+ Basic usage:
1311
+
1312
+ ```erb
1313
+ <%= tramway_form_for @post do |f| %>
1314
+ <%= f.rich_text_area :body %>
1315
+ <% end %>
1316
+ ```
1317
+
1318
+ Custom label and extra CSS class:
1319
+
1320
+ ```erb
1321
+ <%= tramway_form_for @post do |f| %>
1322
+ <%= f.rich_text_area :body, label: 'Post body', class: 'min-h-60' %>
1323
+ <% end %>
1324
+ ```
1325
+
1326
+ Suppress the label:
1327
+
1328
+ ```erb
1329
+ <%= tramway_form_for @post do |f| %>
1330
+ <%= f.rich_text_area :body, label: false %>
1331
+ <% end %>
1332
+ ```
1333
+
1334
+ Pass `data` attributes for Stimulus controllers:
1335
+
1336
+ ```erb
1337
+ <%= tramway_form_for @post do |f| %>
1338
+ <%= f.rich_text_area :body, data: { controller: 'mentions' } %>
1339
+ <% end %>
1340
+ ```
1341
+
1342
+ `size:` is a Tramway-level option and is not forwarded to the `<trix-editor>` element.
1343
+
1286
1344
  #### Stimulus-based inputs
1287
1345
 
1288
1346
  `tramway_form_for` provides Tailwind-styled Stimulus-based custom inputs.
@@ -1339,7 +1397,6 @@ With `remote: true`, Tramway submits the form on each input `change` via inline
1339
1397
  ### Tailwind-styled pagination for Kaminari
1340
1398
 
1341
1399
  Tramway uses [Tailwind](https://tailwindcss.com/) by default. It has tailwind-styled pagination for [kaminari](https://github.com/kaminari/kaminari).
1342
- Pagination components use hardcoded dark shadcn-style classes and do not render a separate light theme.
1343
1400
 
1344
1401
  #### How to use
1345
1402
 
@@ -56,6 +56,14 @@ module Tramway
56
56
  common_field(:text_area, :text_area, attribute, **, &)
57
57
  end
58
58
 
59
+ def rich_text_area(attribute, **, &)
60
+ rich_text_area_field(:rich_text_area, attribute, **, &)
61
+ end
62
+
63
+ def rich_textarea(attribute, **, &)
64
+ rich_text_area_field(:rich_textarea, attribute, **, &)
65
+ end
66
+
59
67
  def password_field(attribute, **options, &)
60
68
  sanitized_options = sanitize_options(options)
61
69
 
@@ -88,6 +96,8 @@ module Tramway
88
96
  common_field(:checkbox, :check_box, attribute, **, &)
89
97
  end
90
98
 
99
+ alias checkbox check_box
100
+
91
101
  def select(attribute, collection, **options, &)
92
102
  if options[:multiple] || options[:autocomplete]
93
103
  tramway_select(attribute, collection, **options, &)
@@ -138,6 +148,15 @@ module Tramway
138
148
  ), &)
139
149
  end
140
150
 
151
+ def rich_text_area_field(input_method, attribute, **options, &)
152
+ sanitized_options = sanitize_options(options)
153
+
154
+ render(Tramway::Form::RichTextAreaComponent.new(
155
+ input: input(input_method),
156
+ **default_options(attribute, sanitized_options)
157
+ ), &)
158
+ end
159
+
141
160
  def input(method_name)
142
161
  unbound_method = self.class.superclass.instance_method(method_name)
143
162
  unbound_method.bind(self)
@@ -0,0 +1,14 @@
1
+ %div{ class: default_container_classes }
2
+ :css
3
+ trix-toolbar .trix-button-group {
4
+ border-color: #52525b;
5
+ }
6
+
7
+ trix-toolbar .trix-button:not(.trix-active)::before {
8
+ filter: invert(1);
9
+ }
10
+
11
+ - if @label
12
+ = component('tramway/form/label', for: @for, class: 'mb-0') do
13
+ = @label
14
+ = @input.call @attribute, **rich_text_area_options
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Form
5
+ # Tailwind-styled rich text area
6
+ class RichTextAreaComponent < TailwindComponent
7
+ RICH_TEXT_AREA_CLASSES = [
8
+ 'trix-content',
9
+ 'prose',
10
+ 'prose-invert',
11
+ 'max-w-none',
12
+ 'w-full',
13
+ 'min-h-40',
14
+ 'rounded-md',
15
+ 'border',
16
+ 'border-zinc-800',
17
+ 'bg-zinc-950',
18
+ '!bg-zinc-950',
19
+ 'text-zinc-50',
20
+ '!text-zinc-50',
21
+ 'shadow-sm',
22
+ 'transition-colors',
23
+ 'focus-visible:outline-none',
24
+ 'focus-visible:ring-2',
25
+ 'focus-visible:ring-zinc-300',
26
+ 'focus-visible:ring-offset-2',
27
+ 'focus-visible:ring-offset-zinc-950',
28
+ 'disabled:cursor-not-allowed',
29
+ 'disabled:opacity-50'
30
+ ].freeze
31
+
32
+ private
33
+
34
+ def rich_text_area_options
35
+ options.dup.tap do |rich_text_options|
36
+ custom_class = rich_text_options.delete(:class) || rich_text_options.delete('class')
37
+ rich_text_options[:class] = [RICH_TEXT_AREA_CLASSES, custom_class].compact.join(' ')
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -8,7 +8,7 @@
8
8
  - cells = visible_cells_from(content)
9
9
 
10
10
  - if href.present?
11
- = tag.a href:, class: [desktop_row_classes(cells.count), link_row_classes].join(' '), **default_attributes do
11
+ = tag.a href:, class: [desktop_row_classes(cells.count), link_row_classes, options[:class]].join(' '), **default_attributes, **options.except(:class) do
12
12
  = content
13
13
  - else
14
14
  - if preview
@@ -18,5 +18,5 @@
18
18
 
19
19
  = cell.to_s.html_safe
20
20
 
21
- = tag.div class: desktop_row_classes(cells.count), data: { action: "click->table-row-preview#toggle", controller: "table-row-preview" }, **default_attributes do
21
+ = tag.div class: [desktop_row_classes(cells.count), options[:class]].join(' '), data: { action: "click->table-row-preview#toggle", controller: "table-row-preview" }, **default_attributes, **options.except(:class) do
22
22
  = content
@@ -9,15 +9,13 @@
9
9
 
10
10
  = yield :head
11
11
 
12
- / Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!)
13
- / = tag.link rel: "manifest", href: pwa_manifest_path(format: :json)
14
-
15
12
  %link{rel: "icon", href: "/icon.png", type: "image/png"}
16
13
  %link{rel: "icon", href: "/icon.svg", type: "image/svg+xml"}
17
14
  %link{rel: "apple-touch-icon", href: "/icon.png"}
18
15
 
19
- / Includes all stylesheet files in app/assets/stylesheets
20
16
  = stylesheet_link_tag "tailwind", "data-turbo-track": "reload"
17
+ = stylesheet_link_tag "trix", "data-turbo-track": "reload"
18
+ = javascript_include_tag "trix", "data-turbo-track": "reload", defer: true
21
19
 
22
20
  %body.bg-zinc-950.text-zinc-50
23
21
  = tramway_navbar title: 'Tramway'
@@ -27,6 +27,7 @@ module.exports = {
27
27
  'pt-16',
28
28
  'min-h-8',
29
29
  'bg-zinc-950',
30
+ '!bg-zinc-950',
30
31
  'bg-zinc-950/95',
31
32
  'bg-zinc-950/80',
32
33
  'bg-zinc-900',
@@ -34,6 +35,7 @@ module.exports = {
34
35
  'bg-zinc-900/80',
35
36
  'border-zinc-800',
36
37
  'text-zinc-50',
38
+ '!text-zinc-50',
37
39
  'text-zinc-100',
38
40
  'text-zinc-200',
39
41
  'text-zinc-400',
@@ -221,6 +223,9 @@ module.exports = {
221
223
  'hidden',
222
224
  'text-xl',
223
225
  'font-bold',
226
+ 'prose',
227
+ 'prose-invert',
228
+ 'max-w-none',
224
229
 
225
230
  // === Button base shell ===
226
231
  'inline-flex',
@@ -338,6 +343,7 @@ module.exports = {
338
343
  'min-h-10',
339
344
  'min-h-12',
340
345
  'min-h-15',
346
+ 'min-h-40',
341
347
  'max-w-full',
342
348
 
343
349
  // === Spacing utilities ===
@@ -380,7 +386,6 @@ module.exports = {
380
386
  'left-1/2',
381
387
  '-translate-x-1/2',
382
388
  'z-50',
383
- 'mb-2',
384
389
  'w-max',
385
390
  'min-w-40',
386
391
  'max-w-sm',
@@ -95,6 +95,28 @@ module Tramway
95
95
  @agents_file_path ||= File.join(destination_root, 'AGENTS.md')
96
96
  end
97
97
 
98
+ def application_layout_haml_path
99
+ @application_layout_haml_path ||= File.join(destination_root, 'app/views/layouts/application.html.haml')
100
+ end
101
+
102
+ def application_layout_erb_path
103
+ @application_layout_erb_path ||= File.join(destination_root, 'app/views/layouts/application.html.erb')
104
+ end
105
+
106
+ def trix_haml_tags
107
+ " = stylesheet_link_tag \"trix\", \"data-turbo-track\": \"reload\"\n " \
108
+ "= javascript_include_tag \"trix\", \"data-turbo-track\": \"reload\", defer: true\n"
109
+ end
110
+
111
+ def trix_erb_tags
112
+ " <%= stylesheet_link_tag \"trix\", \"data-turbo-track\": \"reload\" %>\n " \
113
+ "<%= javascript_include_tag \"trix\", \"data-turbo-track\": \"reload\", defer: true %>\n"
114
+ end
115
+
116
+ def trix_already_present?(content)
117
+ content.include?('stylesheet_link_tag "trix"') || content.include?("stylesheet_link_tag 'trix'")
118
+ end
119
+
98
120
  def codex_agents_instruction
99
121
  'If you are Codex, use the tramway-skill skill for Tramway/Rails work in this project. ' \
100
122
  'If tramway-skill is not installed, install it from https://github.com/Purple-Magic/tramway-skill/.'
@@ -323,6 +345,34 @@ module Tramway
323
345
 
324
346
  File.write(controllers_index_path, updated)
325
347
  end
348
+
349
+ def ensure_trix_in_application_layout
350
+ if File.exist?(application_layout_haml_path)
351
+ ensure_trix_in_haml_layout
352
+ elsif File.exist?(application_layout_erb_path)
353
+ ensure_trix_in_erb_layout
354
+ end
355
+ end
356
+
357
+ private
358
+
359
+ def ensure_trix_in_haml_layout
360
+ content = File.read(application_layout_haml_path)
361
+ return if trix_already_present?(content)
362
+ return unless content.match?(/^\s+%body/)
363
+
364
+ updated = content.sub(/^(\s+%body)/, "#{trix_haml_tags}\\1")
365
+ File.write(application_layout_haml_path, updated)
366
+ end
367
+
368
+ def ensure_trix_in_erb_layout
369
+ content = File.read(application_layout_erb_path)
370
+ return if trix_already_present?(content)
371
+ return unless content.include?('</head>')
372
+
373
+ updated = content.sub('</head>', "#{trix_erb_tags} </head>")
374
+ File.write(application_layout_erb_path, updated)
375
+ end
326
376
  end
327
377
  end
328
378
  end
@@ -23,7 +23,7 @@ module Tramway
23
23
 
24
24
  def field_name(field_data)
25
25
  case field_data.to_sym
26
- when :text_area, :select, :tramway_select, :check_box
26
+ when :text_area, :rich_text_area, :rich_textarea, :select, :tramway_select, :check_box
27
27
  field_data
28
28
  when :checkbox
29
29
  :check_box
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tramway
4
- VERSION = '3.1.1.3'
4
+ VERSION = '3.1.2'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tramway
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1.3
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - kalashnikovisme
@@ -183,6 +183,8 @@ files:
183
183
  - app/components/tramway/form/label_component.rb
184
184
  - app/components/tramway/form/number_field_component.html.haml
185
185
  - app/components/tramway/form/number_field_component.rb
186
+ - app/components/tramway/form/rich_text_area_component.html.haml
187
+ - app/components/tramway/form/rich_text_area_component.rb
186
188
  - app/components/tramway/form/select_component.html.haml
187
189
  - app/components/tramway/form/select_component.rb
188
190
  - app/components/tramway/form/text_area_component.html.haml