tramway 0.1.6 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5d6641dda4dedcf7e4d1a4e0638690e21b5f72fbfdccca6c40fa423eec9e3f8
4
- data.tar.gz: c0e4e0955c58b253c5aac6198302b6c11f3393f42d5edfd4fc317dd7b1a7894b
3
+ metadata.gz: c88b945e6fe61b58431c5598687538fb9514ec49333e11bfdb4b4027ff755e94
4
+ data.tar.gz: dde0abe3237e06f5aa5119e8cd28162643301fb534e949082cb930eca4a2b5dc
5
5
  SHA512:
6
- metadata.gz: f2b1fd87395239845d1eeb4e901e44063e1487bdd83f226a247746dc1bc4fc555cfba4c8357345486dd31e5f5e8c0b5be59e2831e599a87d9c10632b221ad64e
7
- data.tar.gz: eb6e88f325e65e1c49094a197a58419c11c71a5c24f78a5132167798ea4bff644c0a6d98320b073d16cea1b8baa258fa2300583474e95223e0f4ba09e9152327
6
+ metadata.gz: 7c27968e67c7c6da3047aadb5be9e39c52eb8049d558777674c8633e34cea10f996e0bf7d3dc04d2744fdd509f9e5019d321a730c2292c55336a2a5e32575b14
7
+ data.tar.gz: a5eab082d14d3c3158745135fdeedc5bf65789b59b6996523c0584e03522ceeeba63529b25b3549ab368123b6712257865e7098dd7641ec87cbb28358089f0ab
data/README.md CHANGED
@@ -13,7 +13,58 @@ gem "view_component"
13
13
 
14
14
  ### Tailwind components
15
15
 
16
- Tramway use [Tailwind](https://tailwindcss.com/) by default. All UI helpers implemented with [ViewComponent](https://github.com/viewcomponent/view_component).
16
+ Tramway uses [Tailwind](https://tailwindcss.com/) by default. All UI helpers are implemented with [ViewComponent](https://github.com/viewcomponent/view_component).
17
+
18
+ ### Decorators
19
+
20
+ Tramway provides convenient decorators for your objects. **NOTE:** This is not the decorator pattern in its usual representation.
21
+
22
+ *app/controllers/users_controller.rb*
23
+ ```ruby
24
+ def index
25
+ # this line of code decorates the users collection with the default UserDecorator
26
+ @users = tramway_decorate User.all
27
+ end
28
+ ```
29
+
30
+ *app/decorators/user_decorator.rb*
31
+ ```ruby
32
+ class UserDecorator < Tramway::BaseDecorator
33
+ # delegates attributes to decorated object
34
+ delegate_attributes :email, :first_name, :last_name
35
+
36
+ # you can provide your own methods with access to decorated object attributes with the method `object`
37
+ def created_at
38
+ I18n.l object.created_at
39
+ end
40
+
41
+ # you can provide representations with ViewComponent to avoid implementing views with Rails Helpers
42
+ def posts_table
43
+ render TableComponent.new(object.posts)
44
+ end
45
+ end
46
+ ```
47
+
48
+ #### Decorate single object
49
+
50
+ You can use the same method to decorate a single object either
51
+
52
+ ```ruby
53
+ def show
54
+ @user = tramway_decorate User.find params[:id]
55
+ end
56
+ ```
57
+
58
+ #### Decorate with a specific decorator
59
+
60
+ You can implement a specific decorator and ask Tramway to decorate with it
61
+
62
+ ```ruby
63
+ def show
64
+ @user = tramway_decorate User.find(params[:id]), decorator: Users::ShowDecorator
65
+ end
66
+ ```
67
+
17
68
 
18
69
  ### Navbar
19
70
 
@@ -2,5 +2,6 @@
2
2
 
3
3
  require 'view_component'
4
4
 
5
+ # Base TailwindComponent. Contains base features for all tailwind components
5
6
  class TailwindComponent < ViewComponent::Base
6
7
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rules/turbo_html_attributes_rules'
4
+
3
5
  module Tailwinds
4
6
  module Nav
5
7
  # Render button styled with Tailwind using button_to or link_to methods
@@ -8,20 +10,7 @@ module Tailwinds
8
10
  def initialize(**options)
9
11
  @href = options[:href]
10
12
  @style = 'text-white hover:bg-red-300 px-4 py-2 rounded'
11
- @options = prepare(options:)
12
- end
13
-
14
- private
15
-
16
- def prepare(options:)
17
- options.reduce({}) do |hash, (key, value)|
18
- case key
19
- when :method, :confirm
20
- hash.deep_merge data: { "turbo_#{key}".to_sym => value }
21
- else
22
- hash.merge key => value
23
- end
24
- end
13
+ @options = Rules::TurboHtmlAttributesRules.prepare_turbo_html_attributes(options:)
25
14
  end
26
15
  end
27
16
  end
@@ -1,26 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tailwinds
4
- # Navbar class main class
4
+ # Background helper module
5
5
  #
6
- class NavbarComponent < TailwindComponent
7
- def initialize(**options)
8
- @title = options[:title]
9
- @left_items = options[:left_items]
10
- @right_items = options[:right_items]
11
- @color = background(options)
12
- end
13
-
14
- private
15
-
6
+ module BackgroundHelper
16
7
  CSS_COLORS = %i[aqua black blue fuchsia gray green lime maroon navy olive orange purple red
17
8
  silver teal white yellow].freeze
18
9
  MIN_INTENSITY = 100
19
10
  MAX_INTENSITY = 950
11
+ DEFAULT_BACKGROUND_COLOR = :purple
12
+ DEFAULT_BACKGROUND_INTENSITY = 700
20
13
 
21
- def background(options)
22
- color = options.dig(:background, :color) || :purple
23
- intensity = options.dig(:background, :intensity) || 700
14
+ def self.background(options)
15
+ color = options.dig(:background, :color) || DEFAULT_BACKGROUND_COLOR
16
+ intensity = options.dig(:background, :intensity) || DEFAULT_BACKGROUND_INTENSITY
24
17
 
25
18
  unless (MIN_INTENSITY..MAX_INTENSITY).cover?(intensity)
26
19
  raise "Navigation Background Color intensity should be between #{MIN_INTENSITY} and #{MAX_INTENSITY}"
@@ -33,4 +26,17 @@ module Tailwinds
33
26
  end
34
27
  end
35
28
  end
29
+
30
+ # Navbar class main class
31
+ #
32
+ class NavbarComponent < TailwindComponent
33
+ include Tailwinds::BackgroundHelper
34
+
35
+ def initialize(**options)
36
+ @title = options[:title]
37
+ @left_items = options[:left_items]
38
+ @right_items = options[:right_items]
39
+ @color = BackgroundHelper.background(options)
40
+ end
41
+ end
36
42
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rules
4
+ # Provides rules for turbo html attributes
5
+ # It allows users to :method and :confirm attributes instead of data-turbo_method and data-turbo_confirm
6
+ module TurboHtmlAttributesRules
7
+ def self.prepare_turbo_html_attributes(options:)
8
+ options.reduce({}) do |hash, (key, value)|
9
+ case key
10
+ when :method, :confirm
11
+ hash.deep_merge data: { "turbo_#{key}".to_sym => value }
12
+ else
13
+ hash.merge key => value
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tramway/decorators/collection_decorator'
4
+
5
+ module Tramway
6
+ # Provides decorate function for Tramway projects
7
+ #
8
+ class BaseDecorator
9
+ include Tramway::Decorators::CollectionDecorators
10
+
11
+ attr_reader :object, :context
12
+
13
+ def initialize(object, context)
14
+ @object = object
15
+ @context = context
16
+ end
17
+
18
+ def render(*args)
19
+ context.render(*args, layout: false)
20
+ end
21
+
22
+ class << self
23
+ def decorate(object_or_array, context)
24
+ if Tramway::Decorators::CollectionDecorators.collection?(object_or_array)
25
+ Tramway::Decorators::CollectionDecorators.decorate_collection(collection: object_or_array, context:)
26
+ else
27
+ new(object_or_array, context)
28
+ end
29
+ end
30
+
31
+ def delegate_attributes(*args)
32
+ args.each do |attribute|
33
+ delegate attribute, to: :object
34
+ end
35
+ end
36
+ end
37
+
38
+ delegate_attributes :id
39
+
40
+ def to_partial_path
41
+ underscored_class_name = object.class.name.underscore
42
+
43
+ "#{underscored_class_name.pluralize}/#{underscored_class_name}"
44
+ end
45
+
46
+ def to_param
47
+ id.to_s
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Decorators
5
+ # Provides method to determine decorators classes
6
+ module ClassHelper
7
+ module_function
8
+
9
+ def decorator_class(object_or_array, decorator)
10
+ if decorator.present?
11
+ decorator
12
+ else
13
+ klass = if Tramway::Decorators::CollectionDecorators.collection?(object_or_array)
14
+ object_or_array.first.class
15
+ else
16
+ object_or_array.class
17
+ end
18
+
19
+ "#{klass}Decorator".constantize
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Decorators
5
+ # Provides functions for collection decorating
6
+ #
7
+ module CollectionDecorators
8
+ module_function
9
+
10
+ def decorate_collection(collection:, context:)
11
+ collection.map do |item|
12
+ Tramway::Decorators::BaseDecorator.decorate item, context
13
+ end
14
+ end
15
+
16
+ def collection?(object)
17
+ object.class.name.in? ['ActiveRecord::Relation', 'Array']
18
+ end
19
+ end
20
+ end
21
+ end
@@ -7,10 +7,16 @@ module Tramway
7
7
  isolate_namespace Tramway
8
8
 
9
9
  initializer 'tramway.load_helpers' do
10
- ActiveSupport.on_load(:action_view) do
10
+ ActiveSupport.on_load(:action_view) do |loaded_class|
11
11
  require 'tramway/helpers/navbar_helper'
12
12
 
13
- ActionView::Base.include Tramway::Helpers::NavbarHelper
13
+ loaded_class.include Tramway::Helpers::NavbarHelper
14
+ end
15
+
16
+ ActiveSupport.on_load(:action_controller) do |loaded_class|
17
+ require 'tramway/helpers/decorate_helper'
18
+
19
+ loaded_class.include Tramway::Helpers::DecorateHelper
14
20
  end
15
21
  end
16
22
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tramway/decorators/class_helper'
4
+
5
+ module Tramway
6
+ module Helpers
7
+ # Provides methods into Rails ActionController
8
+ #
9
+ module DecorateHelper
10
+ def tramway_decorate(object_or_array, decorator: nil)
11
+ Tramway::Decorators::ClassHelper.decorator_class(object_or_array, decorator).decorate object_or_array, self
12
+ end
13
+ end
14
+ end
15
+ end
@@ -5,18 +5,40 @@ require 'tramway/navbar'
5
5
  module Tramway
6
6
  module Helpers
7
7
  # Providing navbar helpers for ActionView
8
- #
9
8
  module NavbarHelper
10
9
  def tramway_navbar(**options)
11
10
  if block_given?
12
- @navbar = Tramway::Navbar.new self
11
+ initialize_navbar
13
12
 
14
13
  yield @navbar
15
14
 
16
- options[:left_items] = @navbar.items[:left]
17
- options[:right_items] = @navbar.items[:right]
15
+ assign_navbar_items(options)
18
16
  end
19
17
 
18
+ render_navbar_component(options)
19
+ end
20
+
21
+ private
22
+
23
+ def initialize_navbar
24
+ @navbar = Tramway::Navbar.new(self)
25
+ end
26
+
27
+ def assign_navbar_items(options)
28
+ navbar_items = @navbar.items
29
+ navbar_items.each do |(key, value)|
30
+ key_to_merge = case key
31
+ when :left, :right
32
+ "#{key}_items".to_sym
33
+ else
34
+ key
35
+ end
36
+
37
+ options.merge! key_to_merge => value
38
+ end
39
+ end
40
+
41
+ def render_navbar_component(options)
20
42
  render(Tailwinds::NavbarComponent.new(**options))
21
43
  end
22
44
  end
@@ -1,48 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tramway
4
- # Navbar class for Tramway navbars
5
- #
4
+ # Navbar object provides left and right elements
6
5
  class Navbar
7
6
  attr_reader :items
8
7
 
9
8
  def initialize(context)
10
9
  @items = {}
11
10
  @context = context
11
+ @filling = nil
12
12
  end
13
13
 
14
14
  def left
15
15
  return unless block_given?
16
16
 
17
17
  @items[:left] = []
18
-
19
- @filling = :left
20
-
18
+ filling_side(:left)
21
19
  yield self
20
+ reset_filling
22
21
  end
23
22
 
24
23
  def right
25
24
  return unless block_given?
26
25
 
27
26
  @items[:right] = []
28
-
29
- @filling = :right
30
-
27
+ filling_side(:right)
31
28
  yield self
29
+ reset_filling
32
30
  end
33
31
 
34
32
  def item(text_or_url, url = nil, **options, &block)
35
- raise 'You can not provide argument and code block in the same time' if url.present? && block_given?
33
+ raise 'You cannot provide an argument and a code block at the same time' if provided_url_and_block?(url, &block)
36
34
 
37
35
  rendered_item = if url.present?
38
- options.merge! href: url
39
- @context.render(Tailwinds::Nav::ItemComponent.new(**options)) { text_or_url }
36
+ render_ignoring_block(text_or_url, url, options)
40
37
  else
41
- options.merge! href: text_or_url
42
- @context.render(Tailwinds::Nav::ItemComponent.new(**options), &block)
38
+ render_using_block(text_or_url, options, &block)
43
39
  end
44
40
 
45
41
  @items[@filling] << rendered_item
46
42
  end
43
+
44
+ private
45
+
46
+ def provided_url_and_block?(url)
47
+ url.present? && block_given?
48
+ end
49
+
50
+ def filling_side(side)
51
+ @filling = side
52
+ end
53
+
54
+ def reset_filling
55
+ @filling = nil
56
+ end
57
+
58
+ def render_ignoring_block(text_or_url, url, options)
59
+ options.merge!(href: url)
60
+ @context.render(Tailwinds::Nav::ItemComponent.new(**options)) { text_or_url }
61
+ end
62
+
63
+ def render_using_block(text_or_url, options, &block)
64
+ options.merge!(href: text_or_url)
65
+ @context.render(Tailwinds::Nav::ItemComponent.new(**options), &block)
66
+ end
47
67
  end
48
68
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tramway
4
- VERSION = '0.1.6'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/tramway.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'tramway/version'
4
4
  require 'tramway/engine'
5
+ require 'tramway/base_decorator'
5
6
  require 'view_component/compiler'
6
7
  require 'view_component/engine'
7
8
 
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: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kalashnikovisme
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-06-22 00:00:00.000000000 Z
12
+ date: 2023-06-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: haml-rails
@@ -84,9 +84,14 @@ files:
84
84
  - app/components/tailwinds/navbar_component.html.haml
85
85
  - app/components/tailwinds/navbar_component.rb
86
86
  - config/routes.rb
87
+ - lib/rules/turbo_html_attributes_rules.rb
87
88
  - lib/tasks/tramway_tasks.rake
88
89
  - lib/tramway.rb
90
+ - lib/tramway/base_decorator.rb
91
+ - lib/tramway/decorators/class_helper.rb
92
+ - lib/tramway/decorators/collection_decorator.rb
89
93
  - lib/tramway/engine.rb
94
+ - lib/tramway/helpers/decorate_helper.rb
90
95
  - lib/tramway/helpers/navbar_helper.rb
91
96
  - lib/tramway/navbar.rb
92
97
  - lib/tramway/version.rb