tramway 3.1.2.7 → 4.0

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +79 -16
  3. data/app/assets/builds/tailwind.css +2 -0
  4. data/app/assets/javascripts/tramway/tramway.js +193 -5
  5. data/app/assets/stylesheets/font-awesome.css +2337 -0
  6. data/app/assets/tailwind/application.css +29 -0
  7. data/app/components/tramway/chat_component.html.haml +1 -1
  8. data/app/components/tramway/containers/main_component.rb +1 -3
  9. data/app/components/tramway/containers/narrow_component.rb +5 -4
  10. data/app/components/tramway/flash_component.html.haml +6 -0
  11. data/app/components/tramway/form/builder.rb +1 -2
  12. data/app/components/tramway/grid/card_component.html.haml +2 -0
  13. data/app/components/tramway/grid/card_component.rb +37 -0
  14. data/app/components/tramway/grid_component.html.haml +18 -0
  15. data/app/components/tramway/grid_component.rb +76 -0
  16. data/app/components/tramway/native_text_component.rb +1 -2
  17. data/app/components/tramway/nav/item_component.rb +4 -2
  18. data/app/components/tramway/navbar_component.html.haml +104 -110
  19. data/app/components/tramway/navbar_component.rb +84 -2
  20. data/app/components/tramway/table/cell_component.rb +9 -1
  21. data/app/components/tramway/table/header_component.rb +23 -2
  22. data/app/components/tramway/table/row_component.rb +27 -10
  23. data/app/components/tramway/table_component.rb +28 -1
  24. data/app/controllers/tramway/entities_controller.rb +6 -6
  25. data/app/views/tramway/layouts/application.html.haml +8 -6
  26. data/config/routes.rb +1 -2
  27. data/config/tailwind.config.js +57 -0
  28. data/lib/generators/tramway/install/font_awesome_helpers.rb +39 -0
  29. data/lib/generators/tramway/install/install_generator.rb +131 -65
  30. data/lib/generators/tramway/install/layout_helpers.rb +95 -0
  31. data/lib/tramway/engine.rb +12 -0
  32. data/lib/tramway/forms/validations.rb +1 -2
  33. data/lib/tramway/helpers/navbar_helper.rb +3 -1
  34. data/lib/tramway/helpers/table_helper.rb +27 -0
  35. data/lib/tramway/helpers/views_helper.rb +26 -2
  36. data/lib/tramway/version.rb +1 -1
  37. metadata +28 -4
@@ -2,12 +2,47 @@
2
2
 
3
3
  require 'rails/generators'
4
4
  require 'fileutils'
5
+ require_relative 'font_awesome_helpers'
6
+ require_relative 'layout_helpers'
5
7
 
6
8
  module Tramway
7
9
  module Generators
8
10
  # nodoc
9
- # rubocop:disable Metrics/ModuleLength
11
+ # rubocop:disable-next Metrics/ModuleLength
10
12
  module InstallGeneratorHelpers
13
+ TAILWIND_SCROLLBAR_UTILITY = <<~CSS.chomp
14
+ @layer utilities {
15
+ .tramway-scrollbar {
16
+ scrollbar-width: thin;
17
+ scrollbar-color: rgba(82, 82, 91, 0.9) rgba(9, 9, 11, 0.92);
18
+ }
19
+
20
+ .tramway-scrollbar::-webkit-scrollbar {
21
+ width: 0.5rem;
22
+ }
23
+
24
+ .tramway-scrollbar::-webkit-scrollbar-track {
25
+ background: rgba(9, 9, 11, 0.92);
26
+ }
27
+
28
+ .tramway-scrollbar::-webkit-scrollbar-thumb {
29
+ border-radius: 9999px;
30
+ background: rgba(82, 82, 91, 0.9);
31
+ }
32
+
33
+ .tramway-scrollbar::-webkit-scrollbar-thumb:hover {
34
+ background: rgba(113, 113, 122, 0.95);
35
+ }
36
+
37
+ .tramway-scrollbar::-webkit-scrollbar-corner {
38
+ background: transparent;
39
+ }
40
+ }
41
+ CSS
42
+
43
+ TAILWIND_APPLICATION_STYLESHEET_CONTENT =
44
+ "@import \"tailwindcss\";\n\n#{TAILWIND_SCROLLBAR_UTILITY}\n".freeze
45
+
11
46
  private
12
47
 
13
48
  def gem_dependencies
@@ -78,12 +113,13 @@ module Tramway
78
113
 
79
114
  def stimulus_controller_imports
80
115
  [
81
- 'import { TramwaySelect, TableRowPreview, UiCheckbox, Tooltip } from "@tramway/tramway"'
116
+ 'import { Navbar, TramwaySelect, TableRowPreview, UiCheckbox, Tooltip } from "@tramway/tramway"'
82
117
  ]
83
118
  end
84
119
 
85
120
  def stimulus_controller_registrations
86
121
  [
122
+ "application.register('tramway-navbar', Navbar)",
87
123
  "application.register('tramway-select', TramwaySelect)",
88
124
  "application.register('table-row-preview', TableRowPreview)",
89
125
  "application.register('ui--checkbox', UiCheckbox)",
@@ -95,28 +131,6 @@ module Tramway
95
131
  @agents_file_path ||= File.join(destination_root, 'AGENTS.md')
96
132
  end
97
133
 
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
-
120
134
  def codex_agents_instruction
121
135
  'If you are Codex, use the tramway-skill skill for Tramway/Rails work in this project. ' \
122
136
  'If tramway-skill is not installed, install it from https://github.com/Purple-Magic/tramway-skill/.'
@@ -134,15 +148,16 @@ module Tramway
134
148
  end
135
149
 
136
150
  def safelist_section(content)
137
- match = content.match(/safelist\s*:\s*\[(.*?)\]\s*,?/m)
138
- match&.[](1)
151
+ open_index, close_index = safelist_bracket_range(content)
152
+ return nil unless open_index
153
+
154
+ content[(open_index + 1)...close_index]
139
155
  end
140
156
 
141
157
  def insert_entries(content, entries)
142
- match = content.match(/safelist\s*:\s*\[(.*?)\](\s*,?)/m)
143
- return content unless match
158
+ _open_index, closing_index = safelist_bracket_range(content)
159
+ return content unless closing_index
144
160
 
145
- closing_index = match.begin(0) + match[0].rindex(']')
146
161
  indentation = closing_indentation(content, closing_index)
147
162
  formatted_entries = entries.map { |entry| "#{indentation}'#{entry}',\n" }.join
148
163
 
@@ -154,6 +169,33 @@ module Tramway
154
169
  content.dup.insert(closing_index, insertion)
155
170
  end
156
171
 
172
+ # Finds the `[`/`]` pair that delimits the `safelist` array, ignoring brackets that
173
+ # appear inside quoted entries (e.g. `'md:transition-[width]'`) since a naive regex
174
+ # would otherwise stop at the first `]`, wherever it occurs.
175
+ def safelist_bracket_range(content)
176
+ start_index = content =~ /safelist\s*:\s*\[/
177
+ return [nil, nil] unless start_index
178
+
179
+ open_index = content.index('[', start_index)
180
+ close_index = matching_bracket_index(content, open_index)
181
+
182
+ [open_index, close_index]
183
+ end
184
+
185
+ def matching_bracket_index(content, open_index)
186
+ depth = 0
187
+
188
+ content[open_index..].to_enum(:scan, /'[^']*'|"[^"]*"|[\[\]]/).each do
189
+ token = Regexp.last_match[0]
190
+ next unless ['[', ']'].include?(token)
191
+
192
+ depth += token == '[' ? 1 : -1
193
+ return open_index + Regexp.last_match.end(0) - 1 if depth.zero?
194
+ end
195
+
196
+ nil
197
+ end
198
+
157
199
  def closing_indentation(content, index)
158
200
  line_start = content.rindex("\n", index - 1) || 0
159
201
  line = content[line_start..index]
@@ -171,30 +213,39 @@ module Tramway
171
213
  content.end_with?("\n") ? "\n" : "\n\n"
172
214
  end
173
215
 
174
- # rubocop:disable Metrics/MethodLength
175
216
  def append_missing_imports(content)
176
217
  content = remove_legacy_stimulus_imports(content)
218
+ content = normalize_tramway_stimulus_imports(content)
177
219
  missing_imports = stimulus_controller_imports.reject { |line| content.include?(line) }
178
220
  return content if missing_imports.empty?
179
221
 
180
222
  import_lines = content.each_line.with_index.filter_map do |line, index|
181
223
  index if line.lstrip.start_with?('import ')
182
224
  end
183
- insertion = "#{missing_imports.join("\n")}\n"
225
+ insert_missing_imports(content, missing_imports.join("\n"), import_lines)
226
+ end
227
+
228
+ def insert_missing_imports(content, imports, import_lines)
229
+ insertion = "#{imports}\n"
184
230
  updated = content.dup
185
231
 
186
- if import_lines.any?
187
- insertion_index = updated.lines[0..import_lines.max].join.length
188
- updated.insert(insertion_index, insertion)
189
- else
190
- updated.prepend(insertion)
191
- end
232
+ return updated.prepend(insertion) unless import_lines.any?
192
233
 
234
+ insertion_index = updated.lines[0..import_lines.max].join.length
235
+ updated.insert(insertion_index, insertion)
193
236
  updated
194
237
  end
195
- # rubocop:enable Metrics/MethodLength
238
+
239
+ def normalize_tramway_stimulus_imports(content)
240
+ tramway_import_lines = content.each_line.select { |line| tramway_stimulus_import_line?(line) }
241
+ return content unless tramway_import_lines.any?
242
+ return content if normalized_tramway_import_lines?(tramway_import_lines)
243
+
244
+ content.each_line.reject { |line| tramway_stimulus_import_line?(line) }.join
245
+ end
196
246
 
197
247
  def append_missing_registrations(content)
248
+ content = normalize_tramway_stimulus_registrations(content)
198
249
  missing_registrations = stimulus_controller_registrations.reject { |line| content.include?(line) }
199
250
  return content if missing_registrations.empty?
200
251
 
@@ -221,6 +272,36 @@ module Tramway
221
272
  content.each_line.reject { |line| legacy_imports.include?(line.strip) }.join
222
273
  end
223
274
 
275
+ def tramway_stimulus_import_line?(line)
276
+ line.strip.match?(%r{^import \{.*\} from ["']@tramway/tramway["']$})
277
+ end
278
+
279
+ def normalize_tramway_stimulus_registrations(content)
280
+ tramway_registration_lines = content.each_line.select { |line| tramway_stimulus_registration_line?(line) }
281
+ return content if tramway_registration_lines.sort == stimulus_controller_registrations.sort
282
+ return content unless tramway_registration_lines.any?
283
+
284
+ content.each_line.reject { |line| tramway_stimulus_registration_line?(line) }.join
285
+ end
286
+
287
+ def tramway_stimulus_registration_line?(line)
288
+ tramway_registration_prefixes.any? { |prefix| line.strip.start_with?(prefix) }
289
+ end
290
+
291
+ def normalized_tramway_import_lines?(tramway_import_lines)
292
+ tramway_import_lines.one? && tramway_import_lines.first.strip == stimulus_controller_imports.first
293
+ end
294
+
295
+ def tramway_registration_prefixes
296
+ [
297
+ "application.register('tramway-navbar'",
298
+ "application.register('tramway-select'",
299
+ "application.register('table-row-preview'",
300
+ "application.register('ui--checkbox'",
301
+ "application.register('tramway-tooltip'"
302
+ ]
303
+ end
304
+
224
305
  def remove_legacy_importmap_pins(content)
225
306
  content.each_line.reject { |line| legacy_importmap_pins.include?(line.strip) }.join
226
307
  end
@@ -255,12 +336,12 @@ module Tramway
255
336
  say_status(:warning, "Skipping AGENTS.md update: #{e.message}")
256
337
  end
257
338
  end
258
- # rubocop:enable Metrics/ModuleLength
259
339
 
260
- # Running `rails generate tramway:install` will invoke this generator
261
- #
340
+ # Installs Tramway dependencies and app wiring for a host Rails app.
262
341
  class InstallGenerator < Rails::Generators::Base
263
342
  include InstallGeneratorHelpers
343
+ include InstallGeneratorFontAwesomeHelpers
344
+ include InstallGeneratorLayoutHelpers
264
345
 
265
346
  desc 'Installs Tramway dependencies and Tailwind safelist configuration.'
266
347
 
@@ -310,15 +391,14 @@ module Tramway
310
391
  path = tailwind_application_stylesheet_path
311
392
  FileUtils.mkdir_p(File.dirname(path))
312
393
 
313
- return create_file(path, "#{tailwind_css_import_line}\n") unless File.exist?(path)
394
+ return create_file(path, TAILWIND_APPLICATION_STYLESHEET_CONTENT) unless File.exist?(path)
314
395
 
315
396
  content = File.read(path)
316
- return if content.include?(tailwind_css_import_line)
397
+ return if content.include?(tailwind_css_import_line) && content.include?(TAILWIND_SCROLLBAR_UTILITY)
317
398
 
318
- File.open(path, 'a') do |file|
319
- file.write("\n") unless content.empty? || content.end_with?("\n")
320
- file.write("#{tailwind_css_import_line}\n")
321
- end
399
+ updated = content.include?(tailwind_css_import_line) ? content : "#{content}\n#{tailwind_css_import_line}\n"
400
+ updated = "#{updated}\n#{TAILWIND_SCROLLBAR_UTILITY}\n" unless updated.include?(TAILWIND_SCROLLBAR_UTILITY)
401
+ File.write(path, updated)
322
402
  end
323
403
 
324
404
  def ensure_importmap_pin
@@ -348,30 +428,16 @@ module Tramway
348
428
 
349
429
  def ensure_trix_in_application_layout
350
430
  if File.exist?(application_layout_haml_path)
431
+ ensure_font_awesome_in_haml_layout
351
432
  ensure_trix_in_haml_layout
352
433
  elsif File.exist?(application_layout_erb_path)
434
+ ensure_font_awesome_in_erb_layout
353
435
  ensure_trix_in_erb_layout
354
436
  end
355
437
  end
356
438
 
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)
439
+ def ensure_navbar_sidebar_offset_in_application_layout
440
+ ensure_navbar_sidebar_offset
375
441
  end
376
442
  end
377
443
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Generators
5
+ # Layout helpers for Tramway generator template updates.
6
+ module InstallGeneratorLayoutHelpers
7
+ private
8
+
9
+ def application_layout_haml_path
10
+ @application_layout_haml_path ||= File.join(destination_root, 'app/views/layouts/application.html.haml')
11
+ end
12
+
13
+ def application_layout_erb_path
14
+ @application_layout_erb_path ||= File.join(destination_root, 'app/views/layouts/application.html.erb')
15
+ end
16
+
17
+ def trix_haml_tags
18
+ " = stylesheet_link_tag \"trix\", \"data-turbo-track\": \"reload\"\n " \
19
+ "= javascript_include_tag \"trix\", \"data-turbo-track\": \"reload\", defer: true\n"
20
+ end
21
+
22
+ def trix_erb_tags
23
+ " <%= stylesheet_link_tag \"trix\", \"data-turbo-track\": \"reload\" %>\n " \
24
+ "<%= javascript_include_tag \"trix\", \"data-turbo-track\": \"reload\", defer: true %>\n"
25
+ end
26
+
27
+ def trix_already_present?(content)
28
+ content.include?('stylesheet_link_tag "trix"') || content.include?("stylesheet_link_tag 'trix'")
29
+ end
30
+
31
+ def font_awesome_already_present?(content)
32
+ content.include?('stylesheet_link_tag "font-awesome"') ||
33
+ content.include?("stylesheet_link_tag 'font-awesome'")
34
+ end
35
+
36
+ def navbar_sidebar_offset_class
37
+ 'md:pl-72 transition-all duration-300 ease-in-out'
38
+ end
39
+
40
+ def ensure_trix_in_haml_layout
41
+ content = File.read(application_layout_haml_path)
42
+ return if trix_already_present?(content)
43
+ return unless content.match?(/^\s+%body/)
44
+
45
+ updated = content.sub(/^(\s+%body)/, "#{trix_haml_tags}\\1")
46
+ File.write(application_layout_haml_path, updated)
47
+ end
48
+
49
+ def ensure_trix_in_erb_layout
50
+ content = File.read(application_layout_erb_path)
51
+ return if trix_already_present?(content)
52
+ return unless content.include?('</head>')
53
+
54
+ updated = content.sub('</head>', "#{trix_erb_tags} </head>")
55
+ File.write(application_layout_erb_path, updated)
56
+ end
57
+
58
+ def ensure_navbar_sidebar_offset
59
+ if File.exist?(application_layout_haml_path)
60
+ ensure_navbar_sidebar_offset_in_haml_layout
61
+ elsif File.exist?(application_layout_erb_path)
62
+ ensure_navbar_sidebar_offset_in_erb_layout
63
+ end
64
+ end
65
+
66
+ def ensure_navbar_sidebar_offset_in_haml_layout
67
+ content = File.read(application_layout_haml_path)
68
+ return if content.include?(navbar_sidebar_offset_class)
69
+ return unless content.match?(/= tramway_main_container(?: class: '[^']*')? do/)
70
+
71
+ File.write(
72
+ application_layout_haml_path,
73
+ content.sub(
74
+ /= tramway_main_container(?: class: '[^']*')? do/,
75
+ "= tramway_main_container class: '#{navbar_sidebar_offset_class}' do"
76
+ )
77
+ )
78
+ end
79
+
80
+ def ensure_navbar_sidebar_offset_in_erb_layout
81
+ content = File.read(application_layout_erb_path)
82
+ return if content.include?(navbar_sidebar_offset_class)
83
+ return unless content.match?(/<%= tramway_main_container(?: class: '[^']*')? do %>/)
84
+
85
+ File.write(
86
+ application_layout_erb_path,
87
+ content.sub(
88
+ /<%= tramway_main_container(?: class: '[^']*')? do %>/,
89
+ "<%= tramway_main_container class: '#{navbar_sidebar_offset_class}' do %>"
90
+ )
91
+ )
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'font-awesome-rails'
4
+
3
5
  module Tramway
4
6
  # Rails plugin is the Engine
5
7
  #
@@ -17,8 +19,14 @@ module Tramway
17
19
  end
18
20
 
19
21
  initializer 'tramway.assets.precompile' do |app|
22
+ font_awesome_font_paths.each do |path|
23
+ path_string = path.to_s
24
+ app.config.assets.paths << path_string unless app.config.assets.paths.include?(path_string)
25
+ end
26
+
20
27
  app.config.assets.precompile += %w[
21
28
  tramway/tramway.js
29
+ font-awesome.css
22
30
  ]
23
31
  end
24
32
 
@@ -88,6 +96,10 @@ module Tramway
88
96
  end
89
97
  end
90
98
 
99
+ def font_awesome_font_paths
100
+ [FontAwesome::Rails::Engine.root.join('app/assets/fonts')]
101
+ end
102
+
91
103
  def configure_pagination
92
104
  ActiveSupport.on_load(:action_controller) do
93
105
  # Detecting tramway views path
@@ -16,11 +16,10 @@ module Tramway
16
16
  def __initialize_validations(_subclass); end
17
17
  end
18
18
 
19
- # rubocop:disable Naming/PredicateMethod
19
+ # rubocop:disable-next Naming/PredicateMethod
20
20
  def __apply_validations(_params)
21
21
  valid?
22
22
  end
23
- # rubocop:enable Naming/PredicateMethod
24
23
  end
25
24
  end
26
25
  end
@@ -6,11 +6,13 @@ module Tramway
6
6
  module Helpers
7
7
  # Provides navbar helpers for ActionView
8
8
  module NavbarHelper
9
- def tramway_navbar(with_entities: true, **options)
9
+ def tramway_navbar(with_entities: true, direction: :vertical, **options)
10
+ @tramway_navbar_direction = direction.presence&.to_sym || :vertical
10
11
  initialize_navbar(with_entities:)
11
12
 
12
13
  yield @navbar if block_given?
13
14
 
15
+ options[:direction] = direction if options[:direction].nil?
14
16
  assign_navbar_items(options)
15
17
 
16
18
  render_navbar_component(options)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Helpers
5
+ # Provides size helpers for Tramway tables
6
+ module TableHelper
7
+ TABLE_SIZES = %i[small medium large].freeze
8
+
9
+ def tramway_table_size
10
+ context = tramway_table_context
11
+ return :medium unless context.respond_to?(:tramway_table_size)
12
+
13
+ TABLE_SIZES.include?(context.tramway_table_size) ? context.tramway_table_size : :medium
14
+ end
15
+
16
+ def normalize_table_size(size)
17
+ TABLE_SIZES.include?(size) ? size : :medium
18
+ end
19
+
20
+ def tramway_table_context
21
+ return __vc_original_view_context if respond_to?(:__vc_original_view_context)
22
+
23
+ view_context if respond_to?(:view_context)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tramway/helpers/table_helper'
4
+
3
5
  module Tramway
4
6
  module Helpers
5
7
  # Provides view-oriented helpers for ActionView
6
8
  module ViewsHelper
7
9
  include Tramway::Helpers::ComponentHelper
10
+ include Tramway::Helpers::TableHelper
8
11
 
9
12
  FORM_SIZES = %i[small medium large].freeze
10
13
 
@@ -19,8 +22,16 @@ module Tramway
19
22
  ), &)
20
23
  end
21
24
 
22
- def tramway_table(**options, &)
23
- component 'tramway/table', options:, &
25
+ def tramway_table(size: :medium, **options, &)
26
+ component 'tramway/table', size: normalize_table_size(size), options:, &
27
+ end
28
+
29
+ def tramway_grid(rows:, columns:, outline: false, **options, &)
30
+ component 'tramway/grid', rows:, columns:, outline:, options:, &
31
+ end
32
+
33
+ def tramway_card(size: [1, 1], **options, &)
34
+ component 'tramway/grid/card', size:, options:, &
24
35
  end
25
36
 
26
37
  def tramway_header(headers: nil, columns: nil, **options, &)
@@ -63,6 +74,8 @@ module Tramway
63
74
  end
64
75
 
65
76
  def tramway_main_container(**options, &)
77
+ options[:id] ||= 'tramway-main-container'
78
+ options[:class] = tramway_main_container_classes(options[:class])
66
79
  component 'tramway/containers/main', options:, &
67
80
  end
68
81
 
@@ -102,6 +115,17 @@ module Tramway
102
115
  def normalize_form_size(size)
103
116
  FORM_SIZES.include?(size) ? size : :medium
104
117
  end
118
+
119
+ def tramway_main_container_classes(value)
120
+ classes = Array(value).flat_map { _1.to_s.split }
121
+
122
+ return classes.join(' ') if @tramway_navbar_direction.nil?
123
+
124
+ classes = classes.reject { _1.start_with?('md:pl-') || _1.start_with?('md:pr-') }
125
+ classes << 'md:pl-72' if @tramway_navbar_direction == :vertical
126
+
127
+ classes.join(' ')
128
+ end
105
129
  end
106
130
  end
107
131
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tramway
4
- VERSION = '3.1.2.7'
4
+ VERSION = '4.0'
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.2.7
4
+ version: '4.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - kalashnikovisme
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: font-awesome-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: haml-rails
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,7 +100,7 @@ dependencies:
86
100
  requirements:
87
101
  - - ">="
88
102
  - !ruby/object:Gem::Version
89
- version: '7'
103
+ version: '8'
90
104
  - - "<"
91
105
  - !ruby/object:Gem::Version
92
106
  version: '9'
@@ -96,7 +110,7 @@ dependencies:
96
110
  requirements:
97
111
  - - ">="
98
112
  - !ruby/object:Gem::Version
99
- version: '7'
113
+ version: '8'
100
114
  - - "<"
101
115
  - !ruby/object:Gem::Version
102
116
  version: '9'
@@ -138,7 +152,10 @@ files:
138
152
  - MIT-LICENSE
139
153
  - README.md
140
154
  - Rakefile
155
+ - app/assets/builds/tailwind.css
141
156
  - app/assets/javascripts/tramway/tramway.js
157
+ - app/assets/stylesheets/font-awesome.css
158
+ - app/assets/tailwind/application.css
142
159
  - app/components/tailwind_component.html.haml
143
160
  - app/components/tailwind_component.rb
144
161
  - app/components/tramway/actions_buttons_container_component.html.haml
@@ -207,6 +224,10 @@ files:
207
224
  - app/components/tramway/form/tramway_select/selected_item_template_component.rb
208
225
  - app/components/tramway/form/tramway_select_component.html.haml
209
226
  - app/components/tramway/form/tramway_select_component.rb
227
+ - app/components/tramway/grid/card_component.html.haml
228
+ - app/components/tramway/grid/card_component.rb
229
+ - app/components/tramway/grid_component.html.haml
230
+ - app/components/tramway/grid_component.rb
210
231
  - app/components/tramway/native_text_component.html.haml
211
232
  - app/components/tramway/native_text_component.rb
212
233
  - app/components/tramway/nav/item/button_component.html.haml
@@ -266,7 +287,9 @@ files:
266
287
  - config/routes.rb
267
288
  - config/tailwind.config.js
268
289
  - docs/AGENTS.md
290
+ - lib/generators/tramway/install/font_awesome_helpers.rb
269
291
  - lib/generators/tramway/install/install_generator.rb
292
+ - lib/generators/tramway/install/layout_helpers.rb
270
293
  - lib/kaminari/helpers/tag.rb
271
294
  - lib/rules/turbo_html_attributes_rules.rb
272
295
  - lib/tasks/tramway_tasks.rake
@@ -296,6 +319,7 @@ files:
296
319
  - lib/tramway/helpers/form_helper.rb
297
320
  - lib/tramway/helpers/navbar_helper.rb
298
321
  - lib/tramway/helpers/routes_helper.rb
322
+ - lib/tramway/helpers/table_helper.rb
299
323
  - lib/tramway/helpers/views_helper.rb
300
324
  - lib/tramway/navbar.rb
301
325
  - lib/tramway/searchable.rb
@@ -326,7 +350,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
326
350
  - !ruby/object:Gem::Version
327
351
  version: '0'
328
352
  requirements: []
329
- rubygems_version: 4.0.16
353
+ rubygems_version: 4.0.20
330
354
  specification_version: 4
331
355
  summary: Tramway Rails Engine
332
356
  test_files: []