tramway 2.2.3.3 → 2.2.5

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 (28) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -4
  3. data/app/assets/javascripts/tramway/multiselect_controller.js +7 -1
  4. data/app/components/tailwind_component.rb +3 -3
  5. data/app/components/tailwinds/form/multiselect/caret_component.html.haml +7 -0
  6. data/app/components/tailwinds/form/multiselect/caret_component.rb +19 -0
  7. data/app/components/tailwinds/form/multiselect/dropdown_container_component.rb +26 -0
  8. data/app/components/tailwinds/form/multiselect/{item_container.html.haml → item_container_component.html.haml} +1 -4
  9. data/app/components/tailwinds/form/multiselect/item_container_component.rb +24 -0
  10. data/app/components/tailwinds/form/multiselect/{select_as_input.rb → select_as_input_component.rb} +1 -1
  11. data/app/components/tailwinds/form/multiselect/selected_item_template_component.html.haml +6 -0
  12. data/app/components/tailwinds/form/multiselect/selected_item_template_component.rb +26 -0
  13. data/app/components/tailwinds/form/multiselect_component.html.haml +10 -7
  14. data/app/components/tailwinds/form/multiselect_component.rb +34 -38
  15. data/app/components/tailwinds/table/cell_component.rb +0 -17
  16. data/app/components/tailwinds/table/row_component.rb +18 -0
  17. data/config/tailwind.config.js +19 -1
  18. data/docs/AGENTS.md +64 -0
  19. data/lib/tramway/forms/fields.rb +19 -1
  20. data/lib/tramway/utils/field.rb +31 -11
  21. data/lib/tramway/version.rb +1 -1
  22. metadata +11 -9
  23. data/app/components/tailwinds/form/multiselect/dropdown_container.rb +0 -17
  24. data/app/components/tailwinds/form/multiselect/item_container.rb +0 -30
  25. data/app/components/tailwinds/form/multiselect/selected_item_template.html.haml +0 -6
  26. data/app/components/tailwinds/form/multiselect/selected_item_template.rb +0 -17
  27. /data/app/components/tailwinds/form/multiselect/{dropdown_container.html.haml → dropdown_container_component.html.haml} +0 -0
  28. /data/app/components/tailwinds/form/multiselect/{select_as_input.html.haml → select_as_input_component.html.haml} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4ac0f8b16c48697499fff448ea5c1afd8f10a7edb23f3202c7b2e27270ad5d5
4
- data.tar.gz: 409afb51bb0244d2bbcf609d0ce0b4a8a3b408b1daf1b1e0adc109f827a2ca49
3
+ metadata.gz: cd9400e71d346fc1c334cf2f7d2a8a52847c0000957b675cc5bc6c38132a1bb9
4
+ data.tar.gz: 8a36f11fc6dec4e76241f150f8fe0d2d3f8bd187a5ff46f71b6e50cddb660479
5
5
  SHA512:
6
- metadata.gz: 521e251f67fe5e7157ff3256c77da7372174578b936b742055ad6cc7e7337a297df74487076bd189b24a5f1634775e481c4067b62fba2bde9213f654c7143173
7
- data.tar.gz: 4812134f889e1dd2b943cbd317ce3a1b097b78cf5460a50d86dc9d4dca082844913e8b37732fc572c2982058bb419c447dc43c673bb20c14768800bb22ef5e69
6
+ metadata.gz: f6e6ae7bc9326a651b59fce3c82d88c826f1cff4712248e0c7a0b1e7abd3033b47f91151d3f6d6007a1ba33ae5097455a48aeaf835e328a45edeb329ae8160d6
7
+ data.tar.gz: b546d9583c1c97b7d75797a145de2a522b4e5edd25d09add7cf3b106ac9c6bf89ae541d43667320a4f3adaafef9e7d961bc19f542595258ec5eaed8c698da12d
data/README.md CHANGED
@@ -272,13 +272,17 @@ method name and the remaining keys are passed as named arguments.
272
272
 
273
273
  ```ruby
274
274
  class UserForm < Tramway::BaseForm
275
- properties :email, :about_me
275
+ properties :email, :about_me, :user_type
276
276
 
277
277
  fields email: :email,
278
278
  name: :text,
279
279
  about_me: {
280
280
  type: :text_area,
281
281
  rows: 5
282
+ },
283
+ user_type: {
284
+ type: :select,
285
+ collection: ['regular', 'user']
282
286
  }
283
287
  end
284
288
  ```
@@ -652,7 +656,7 @@ end
652
656
 
653
657
  ### Form inheritance
654
658
 
655
- Tramway Form supports inheritance of `properties` and `normalizations`
659
+ Tramway Form supports inheritance of `properties`, `normalizations`, and `fields`.
656
660
 
657
661
  **Example**
658
662
 
@@ -661,6 +665,9 @@ class UserForm < TramwayForm
661
665
  properties :email, :password
662
666
 
663
667
  normalizes :email, with: ->(value) { value.strip.downcase }
668
+
669
+ fields email: :email,
670
+ password: :password
664
671
  end
665
672
 
666
673
  class AdminForm < UserForm
@@ -668,7 +675,8 @@ class AdminForm < UserForm
668
675
  end
669
676
 
670
677
  AdminForm.properties # returns [:email, :password, :permissions]
671
- AdminForm.normalizations # contains the normalization of :email
678
+ AdminForm.normalizations # contains the normalization of :email
679
+ AdminForm.fields # { email: :email, password: :password }
672
680
  ```
673
681
 
674
682
  ### Make flexible and extendable forms
@@ -1079,7 +1087,7 @@ eagerLoadControllersFrom("controllers", application)
1079
1087
  application.register('multiselect', Multiselect) // register Multiselect controller class as `multiselect` stimulus controller
1080
1088
  ```
1081
1089
 
1082
- Use Stimulus `change` action with Tramway Multiselect
1090
+ In case you need to use Stimulus `change` action with Tramway Multiselect
1083
1091
 
1084
1092
  ```erb
1085
1093
  <%= tramway_form_for @user do |f| %>
@@ -1,7 +1,7 @@
1
1
  import { Controller } from "@hotwired/stimulus"
2
2
 
3
3
  export default class Multiselect extends Controller {
4
- static targets = ["dropdown", "showSelectedArea", "hiddenInput"];
4
+ static targets = ["dropdown", "showSelectedArea", "hiddenInput", "caretDown", "caretUp"]
5
5
 
6
6
  static values = {
7
7
  items: Array,
@@ -79,6 +79,9 @@ export default class Multiselect extends Controller {
79
79
  if (this.dropdown()) {
80
80
  this.dropdown().addEventListener('click', event => event.stopPropagation());
81
81
  }
82
+
83
+ this.caretDownTarget.classList.add('hidden');
84
+ this.caretUpTarget.classList.remove('hidden');
82
85
  }
83
86
 
84
87
  dropdown() {
@@ -107,6 +110,9 @@ export default class Multiselect extends Controller {
107
110
  alert(`Controller not found: ${controllerName}`); // eslint-disable-line no-undef
108
111
  }
109
112
  }
113
+
114
+ this.caretDownTarget.classList.remove('hidden');
115
+ this.caretUpTarget.classList.add('hidden');
110
116
  }
111
117
 
112
118
  get template() {
@@ -18,21 +18,21 @@ class TailwindComponent < Tramway::BaseComponent
18
18
  select_input: 'text-sm px-2 py-1',
19
19
  file_button: 'text-sm px-3 py-1',
20
20
  submit_button: 'text-sm px-3 py-1',
21
- multiselect_input: 'text-sm px-2 py-1'
21
+ multiselect_input: 'text-sm px-2 py-1 h-10'
22
22
  },
23
23
  medium: {
24
24
  text_input: 'text-base px-3 py-2',
25
25
  select_input: 'text-base px-3 py-2',
26
26
  file_button: 'text-base px-4 py-2',
27
27
  submit_button: 'text-base px-4 py-2',
28
- multiselect_input: 'text-base px-3 py-2'
28
+ multiselect_input: 'text-base px-2 py-1 h-12'
29
29
  },
30
30
  large: {
31
31
  text_input: 'text-xl px-4 py-3',
32
32
  select_input: 'text-xl px-4 py-3',
33
33
  file_button: 'text-xl px-5 py-3',
34
34
  submit_button: 'text-xl px-5 py-3',
35
- multiselect_input: 'text-xl px-4 py-3'
35
+ multiselect_input: 'text-xl px-3 py-2 h-15'
36
36
  }
37
37
  }.freeze
38
38
 
@@ -0,0 +1,7 @@
1
+ - if direction == :down
2
+ %svg{ xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", "stroke-width": "1.5", stroke: "currentColor", class: SIZE_CLASSES[size] }
3
+ %path{ "stroke-linecap": "round", "stroke-linejoin": "round", d: "m19.5 8.25-7.5 7.5-7.5-7.5" }
4
+
5
+ - if direction == :up
6
+ %svg{ xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", "stroke-width": "1.5", stroke: "currentColor", class: SIZE_CLASSES[size] }
7
+ %path{ "stroke-linecap": "round", "stroke-linejoin": "round", d: "m4.5 15.75 7.5-7.5 7.5 7.5" }
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailwinds
4
+ module Form
5
+ module Multiselect
6
+ # Caret icon component
7
+ class CaretComponent < Tramway::BaseComponent
8
+ option :direction
9
+ option :size
10
+
11
+ SIZE_CLASSES = {
12
+ small: 'w-3 h-3',
13
+ medium: 'w-4 h-4',
14
+ large: 'w-6 h-6'
15
+ }.freeze
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailwinds
4
+ module Form
5
+ module Multiselect
6
+ # Container for dropdown component
7
+ class DropdownContainerComponent < Tramway::BaseComponent
8
+ option :size
9
+
10
+ SIZE_CLASSES = {
11
+ small: 'text-sm',
12
+ medium: 'text-base',
13
+ large: 'text-lg'
14
+ }.freeze
15
+
16
+ def dropdown_classes
17
+ theme_classes(
18
+ classic: 'absolute border-b border-l border-r border-gray-700 w-full z-40 lef-0 rounded-b-xl' \
19
+ 'max-h-select overflow-y-auto bg-gray-900 shadow-md ring-1 ring-gray-700 text-white ' \
20
+ "#{SIZE_CLASSES[size]}"
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,2 @@
1
1
  %div{ class: item_classes, data: { action: "click->multiselect#toggleItem", text: "{{text}}", value: "{{value}}" } }
2
- %div{ class: item_inner_classes }
3
- %div{ class: item_text_classes }
4
- .mx-2.leading-6
5
- {{text}}
2
+ {{text}}
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailwinds
4
+ module Form
5
+ module Multiselect
6
+ # Container for item in dropdown component
7
+ class ItemContainerComponent < Tramway::BaseComponent
8
+ option :size
9
+
10
+ SIZE_CLASSES = {
11
+ small: 'p-1',
12
+ medium: 'p-2',
13
+ large: 'p-3'
14
+ }.freeze
15
+
16
+ def item_classes
17
+ theme_classes(
18
+ classic: "cursor-pointer hover:bg-gray-800 shadow-inner option #{SIZE_CLASSES[size]}"
19
+ )
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -4,7 +4,7 @@ module Tailwinds
4
4
  module Form
5
5
  module Multiselect
6
6
  # Renders input as select
7
- class SelectAsInput < Tramway::BaseComponent
7
+ class SelectAsInputComponent < Tramway::BaseComponent
8
8
  option :options
9
9
  option :attribute
10
10
  option :input
@@ -0,0 +1,6 @@
1
+ %div{ class: selected_item_classes, data: { action: "click->multiselect#toggleItem", text: "{{text}}", value: "{{value}}" } }
2
+ .font-normal.leading-none.max-w-full.flex-initial
3
+ {{text}}
4
+ .flex.flex-auto.flex-row-reverse
5
+ .cursor-pointer
6
+
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailwinds
4
+ module Form
5
+ module Multiselect
6
+ # Tailwind-styled multi-select field
7
+ class SelectedItemTemplateComponent < Tramway::BaseComponent
8
+ option :size
9
+
10
+ SIZE_CLASSES = {
11
+ small: 'text-sm',
12
+ medium: 'text-base',
13
+ large: 'text-lg'
14
+ }.freeze
15
+
16
+ def selected_item_classes
17
+ theme_classes(
18
+ classic: 'flex justify-center items-center font-medium py-1 px-2 rounded-xl border ' \
19
+ 'text-white border-gray-700 shadow-md hover:bg-gray-800 cursor-pointer space-x-1 ' \
20
+ 'selected-option ' + SIZE_CLASSES[size].to_s
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,10 +1,13 @@
1
- .mb-4
1
+ .mb-4.relative
2
2
  - if @label
3
3
  = component('tailwinds/form/label', for: @for) do
4
4
  = @label
5
- %div{ class: wrapper_classes, data: multiselect_hash, id: "#{@for}_multiselect" }
6
- .min-w-96.w-fit
7
- %div{ class: dropdown_classes, data: { "multiselect-target" => "dropdown" } }
8
- .flex.flex-auto.flex-wrap{ data: { "multiselect-target" => "showSelectedArea" } }
9
- %div{ class: dropdown_indicator_classes }
10
- ^
5
+ %div{ role: :combobox, data: multiselect_hash, id: "#{@for}_multiselect" }
6
+ - classes = "#{size_class(:multiselect_input)} #{select_base_classes}"
7
+ .flex.flex-end.justify-between{ data: dropdown_data, **dropdown_options }
8
+ .flex.flex-row.flex-nowrap.overflow-x-auto.space-x-1{ data: { "multiselect-target" => "showSelectedArea" } }
9
+ .flex.flex-col.justify-center
10
+ .caret-down{ data: { "multiselect-target" => "caretDown" } }
11
+ = component 'tailwinds/form/multiselect/caret', size: size, direction: :down
12
+ .caret-up.hidden{ data: { "multiselect-target" => "caretUp" } }
13
+ = component 'tailwinds/form/multiselect/caret', size: size, direction: :up
@@ -12,12 +12,23 @@ module Tailwinds
12
12
  end.to_json
13
13
  end
14
14
 
15
+ # rubocop:disable Metrics/MethodLength
15
16
  def multiselect_hash
16
17
  {
17
- controller:, selected_item_template:, multiselect_selected_items_value:, dropdown_container:, item_container:,
18
- items:, action:, select_as_input:, placeholder:, value:, on_change:
18
+ controller:,
19
+ selected_item_template:,
20
+ multiselect_selected_items_value:,
21
+ dropdown_container:,
22
+ item_container:,
23
+ items:,
24
+ action:,
25
+ select_as_input:,
26
+ placeholder:,
27
+ value:,
28
+ on_change:
19
29
  }.transform_keys { |key| key.to_s.gsub('_', '-') }
20
30
  end
31
+ # rubocop:enable Metrics/MethodLength
21
32
 
22
33
  def controller
23
34
  controllers = [:multiselect]
@@ -26,22 +37,20 @@ module Tailwinds
26
37
  controllers.join(' ')
27
38
  end
28
39
 
29
- def wrapper_classes
30
- theme_classes(
31
- classic: 'flex flex-col relative text-gray-200'
40
+ def dropdown_data
41
+ (options[:data] || {}).merge(
42
+ 'multiselect-target' => 'dropdown',
43
+ 'dropdown-container' => dropdown_container,
44
+ 'item-container' => item_container
32
45
  )
33
46
  end
34
47
 
35
- def dropdown_classes
36
- theme_classes(
37
- classic: 'p-1 flex border rounded-xl border-gray-700 bg-gray-900 shadow-inner'
38
- )
48
+ def dropdown_options
49
+ options.except(:data).merge(class: input_classes)
39
50
  end
40
51
 
41
- def dropdown_indicator_classes
42
- theme_classes(
43
- classic: 'w-8 py-1 pl-2 pr-1 border-l flex items-center text-gray-500 border-gray-700'
44
- )
52
+ def input_classes
53
+ "#{size_class(:multiselect_input)} #{select_base_classes}"
45
54
  end
46
55
 
47
56
  private
@@ -63,13 +72,12 @@ module Tailwinds
63
72
  end
64
73
 
65
74
  def select_as_input
66
- render(
67
- Tailwinds::Form::Multiselect::SelectAsInput.new(
68
- options:,
69
- attribute:,
70
- input:,
71
- size_class: size_class(:multiselect_input)
72
- )
75
+ component(
76
+ 'tailwinds/form/multiselect/select_as_input',
77
+ options:,
78
+ attribute:,
79
+ input:,
80
+ size_class: size_class(:multiselect_input)
73
81
  )
74
82
  end
75
83
 
@@ -87,29 +95,17 @@ module Tailwinds
87
95
  options.dig(:data, :action)
88
96
  end
89
97
 
90
- def method_missing(method_name, *, &)
91
- component = component_name(method_name)
92
-
93
- if method_name.to_s.include?('_') && Object.const_defined?(component)
94
- render(component.constantize.new(*, &))
95
- else
96
- super
97
- end
98
+ def selected_item_template
99
+ component('tailwinds/form/multiselect/selected_item_template', size:)
98
100
  end
99
101
 
100
- def respond_to_missing?(method_name, include_private = false)
101
- if method_name.to_s.include?('_') && Object.const_defined?(component_name(method_name))
102
- true
103
- else
104
- super
105
- end
102
+ def dropdown_container
103
+ component('tailwinds/form/multiselect/dropdown_container', size:)
106
104
  end
107
105
 
108
- # :reek:UtilityFunction { enabled: false }
109
- def component_name(method_name)
110
- "Tailwinds::Form::Multiselect::#{method_name.to_s.camelize}"
106
+ def item_container
107
+ component('tailwinds/form/multiselect/item_container', size:)
111
108
  end
112
- # :reek:UtilityFunction { enabled: true }
113
109
  end
114
110
  end
115
111
  end
@@ -9,23 +9,6 @@ module Tailwinds
9
9
  classic: 'div-table-cell md:block first:block hidden px-6 py-4 font-medium text-gray-100 text-base'
10
10
  )
11
11
  end
12
-
13
- def around_render
14
- ensure_view_context_accessor
15
- previous_flag = view_context.tramway_inside_cell
16
- view_context.tramway_inside_cell = true
17
- yield
18
- ensure
19
- view_context.tramway_inside_cell = previous_flag
20
- end
21
-
22
- private
23
-
24
- def ensure_view_context_accessor
25
- return if view_context.respond_to?(:tramway_inside_cell=)
26
-
27
- view_context.singleton_class.attr_accessor :tramway_inside_cell
28
- end
29
12
  end
30
13
  end
31
14
  end
@@ -44,6 +44,24 @@ module Tailwinds
44
44
  classic: 'div-table-cell px-6 py-4 font-medium text-gray-100 text-xs sm:text-base'
45
45
  )
46
46
  end
47
+
48
+ def around_render
49
+ ensure_view_context_accessor
50
+ previous_flag = view_context.tramway_inside_cell
51
+ view_context.tramway_inside_cell = href.present?
52
+
53
+ yield
54
+ ensure
55
+ view_context.tramway_inside_cell = previous_flag
56
+ end
57
+
58
+ private
59
+
60
+ def ensure_view_context_accessor
61
+ return if view_context.respond_to?(:tramway_inside_cell=)
62
+
63
+ view_context.singleton_class.attr_accessor :tramway_inside_cell
64
+ end
47
65
  end
48
66
  end
49
67
  end
@@ -247,7 +247,6 @@ module.exports = {
247
247
  'absolute',
248
248
  'relative',
249
249
  'shadow',
250
- 'top-11',
251
250
  'z-40',
252
251
  'max-h-select',
253
252
  'overflow-y-auto',
@@ -269,6 +268,25 @@ module.exports = {
269
268
  'outline-none',
270
269
  'h-full',
271
270
  'm-1',
271
+ 'p-1',
272
+ 'p-2',
273
+ 'p-3',
274
+ 'rounded-b-xl',
275
+ 'hover:bg-gray-800',
276
+ 'border-gray-700',
277
+ 'h-15',
278
+ 'h-12',
279
+ 'h-10',
280
+ 'w-2',
281
+ 'h-2',
282
+ 'w-4',
283
+ 'h-4',
284
+ 'w-6',
285
+ 'h-6',
286
+ 'px-2',
287
+ 'py-1',
288
+ 'flex-nowrap',
289
+ 'overflow-x-auto',
272
290
 
273
291
  // === Flash message styles ===
274
292
  'fixed',
data/docs/AGENTS.md CHANGED
@@ -358,6 +358,70 @@ In case you implementing API, use `api` namespaces for forms and decorators.
358
358
  ### Rule 25
359
359
  DO NOT use `#{model_name}_params` method with `permit` method inside controllers. When you use `tramway_form`, it's unnecessary.
360
360
 
361
+ ### Rule 26
362
+ DO NOT create new private methods in the controller for business logic stuff. Use service objects instead.
363
+ Create `app/services/base_service.rb` if it does not exist.
364
+
365
+ ```ruby
366
+ class BaseService
367
+ extend Dry::Initializer[undefined: false]
368
+ include Dry::Monads[:do, :result]
369
+
370
+ def self.call(...)
371
+ new(...).call
372
+ end
373
+ end
374
+ ```
375
+
376
+ And instead of this in a controller
377
+
378
+ ```ruby
379
+ def create
380
+ user = tramway_form User.new
381
+
382
+ if user.submit params[:user]
383
+ notify_admin user
384
+
385
+ # other stuff
386
+ else
387
+ end
388
+ end
389
+
390
+ private
391
+
392
+ def notify_admin(user)
393
+ # stuff
394
+ end
395
+ ```
396
+
397
+ Make this
398
+
399
+ *app/services/notify_admin.rb*
400
+ ```ruby
401
+ class NotifyAdmin < BaseService
402
+ option :user
403
+
404
+ def call
405
+ # stuff
406
+ end
407
+ end
408
+ ```
409
+
410
+ and in a controller
411
+
412
+ ```
413
+ def create
414
+ user = tramway_form User.new
415
+
416
+ if user.submit params[:user]
417
+ NotifyAdmin.call user:
418
+
419
+ # other stuff
420
+ else
421
+ end
422
+ end
423
+ ```
424
+
361
425
  ## Controller Patterns
362
426
 
363
427
  - Keep actions short and explicit with guard clauses.
@@ -7,7 +7,25 @@ module Tramway
7
7
  # Class methods for defining fields
8
8
  module ClassMethods
9
9
  def fields(**attributes)
10
- @fields.merge! attributes
10
+ attributes.any? ? __set_fields(attributes) : __fields
11
+ end
12
+
13
+ def __set_fields(attributes)
14
+ attributes.each do |(attribute, field_data)|
15
+ @fields.merge! attribute => field_data
16
+ end
17
+ end
18
+
19
+ def __fields
20
+ @fields.merge(__ancestor_fields)
21
+ end
22
+
23
+ def __ancestor_fields(klass = superclass)
24
+ superklass = klass.superclass
25
+
26
+ return {} unless superklass.respond_to?(:fields)
27
+
28
+ klass.fields.merge(__ancestor_fields(superklass))
11
29
  end
12
30
 
13
31
  def __initialize_fields(subclass)
@@ -4,27 +4,47 @@ module Tramway
4
4
  module Utils
5
5
  # Provides dynamic field rendering
6
6
  module Field
7
- def tramway_field(field_type, attribute, **, &)
8
- if field_type.is_a?(Hash)
9
- name = field_name(field_type[:type])
10
- value = field_type[:value]&.call
7
+ def tramway_field(field_data, attribute, **options, &)
8
+ input_type = field_type(field_data)
9
+ input_name = field_name input_type
10
+ input_options = field_options(field_data).merge(options)
11
11
 
12
- hash = { value:, **field_type.except(:type, :value) }.compact
12
+ case input_type.to_sym
13
+ when :select, :multiselect
14
+ collection = input_options.delete(:collection)
13
15
 
14
- public_send(name, attribute, **hash, **, &)
16
+ public_send(input_name, attribute, collection, **input_options, &)
15
17
  else
16
- public_send(field_name(field_type), attribute, **, &)
18
+ public_send(input_name, attribute, **input_options, &)
17
19
  end
18
20
  end
19
21
 
20
22
  private
21
23
 
22
- def field_name(field_type)
23
- case field_type.to_sym
24
+ def field_name(field_data)
25
+ case field_data.to_sym
24
26
  when :text_area, :select, :multiselect
25
- field_type
27
+ field_data
26
28
  else
27
- "#{field_type}_field"
29
+ "#{field_data}_field"
30
+ end
31
+ end
32
+
33
+ def field_type(field_data)
34
+ if field_data.is_a?(Hash)
35
+ field_data[:type]
36
+ else
37
+ field_data
38
+ end
39
+ end
40
+
41
+ def field_options(field_data)
42
+ if field_data.is_a?(Hash)
43
+ value = field_data[:value]&.call
44
+
45
+ field_data.merge(value:).except(:type)
46
+ else
47
+ {}
28
48
  end
29
49
  end
30
50
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tramway
4
- VERSION = '2.2.3.3'
4
+ VERSION = '2.2.5'
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: 2.2.3.3
4
+ version: 2.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - kalashnikovisme
@@ -164,14 +164,16 @@ files:
164
164
  - app/components/tailwinds/form/file_field_component.rb
165
165
  - app/components/tailwinds/form/label_component.html.haml
166
166
  - app/components/tailwinds/form/label_component.rb
167
- - app/components/tailwinds/form/multiselect/dropdown_container.html.haml
168
- - app/components/tailwinds/form/multiselect/dropdown_container.rb
169
- - app/components/tailwinds/form/multiselect/item_container.html.haml
170
- - app/components/tailwinds/form/multiselect/item_container.rb
171
- - app/components/tailwinds/form/multiselect/select_as_input.html.haml
172
- - app/components/tailwinds/form/multiselect/select_as_input.rb
173
- - app/components/tailwinds/form/multiselect/selected_item_template.html.haml
174
- - app/components/tailwinds/form/multiselect/selected_item_template.rb
167
+ - app/components/tailwinds/form/multiselect/caret_component.html.haml
168
+ - app/components/tailwinds/form/multiselect/caret_component.rb
169
+ - app/components/tailwinds/form/multiselect/dropdown_container_component.html.haml
170
+ - app/components/tailwinds/form/multiselect/dropdown_container_component.rb
171
+ - app/components/tailwinds/form/multiselect/item_container_component.html.haml
172
+ - app/components/tailwinds/form/multiselect/item_container_component.rb
173
+ - app/components/tailwinds/form/multiselect/select_as_input_component.html.haml
174
+ - app/components/tailwinds/form/multiselect/select_as_input_component.rb
175
+ - app/components/tailwinds/form/multiselect/selected_item_template_component.html.haml
176
+ - app/components/tailwinds/form/multiselect/selected_item_template_component.rb
175
177
  - app/components/tailwinds/form/multiselect_component.html.haml
176
178
  - app/components/tailwinds/form/multiselect_component.rb
177
179
  - app/components/tailwinds/form/number_field_component.html.haml
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Tailwinds
4
- module Form
5
- module Multiselect
6
- # Container for dropdown component
7
- class DropdownContainer < Tramway::BaseComponent
8
- def dropdown_classes
9
- theme_classes(
10
- classic: 'absolute shadow top-11 z-40 w-full lef-0 rounded-xl max-h-select overflow-y-auto ' \
11
- 'bg-gray-900 shadow-md ring-1 ring-gray-700'
12
- )
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Tailwinds
4
- module Form
5
- module Multiselect
6
- # Container for item in dropdown component
7
- class ItemContainer < Tramway::BaseComponent
8
- def item_classes
9
- theme_classes(
10
- classic: 'cursor-pointer w-full rounded-xl border-b border-gray-700 bg-gray-900 ' \
11
- 'hover:bg-gray-800 shadow-inner'
12
- )
13
- end
14
-
15
- def item_inner_classes
16
- theme_classes(
17
- classic: 'flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative ' \
18
- 'hover:border-gray-600'
19
- )
20
- end
21
-
22
- def item_text_classes
23
- theme_classes(
24
- classic: 'w-full items-center flex text-gray-100'
25
- )
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,6 +0,0 @@
1
- %div{ class: selected_item_classes }
2
- .text-xs.font-normal.leading-none.max-w-full.flex-initial
3
- {{text}}
4
- .flex.flex-auto.flex-row-reverse
5
- .cursor-pointer{ data: { action: "click->multiselect#toggleItem", text: "{{text}}", value: "{{value}}" } }
6
-
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Tailwinds
4
- module Form
5
- module Multiselect
6
- # Tailwind-styled multi-select field
7
- class SelectedItemTemplate < Tramway::BaseComponent
8
- def selected_item_classes
9
- theme_classes(
10
- classic: 'flex justify-center items-center m-1 font-medium py-1 px-2 rounded-full border ' \
11
- 'bg-teal-900 text-teal-100 border-teal-700 shadow-md'
12
- )
13
- end
14
- end
15
- end
16
- end
17
- end