tailmix 0.2.0 → 0.4.6
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/.rubocop.yml +3 -0
- data/README.md +147 -85
- data/app/javascript/tailmix/finder.js +15 -0
- data/app/javascript/tailmix/index.js +7 -0
- data/app/javascript/tailmix/mutator.js +28 -0
- data/app/javascript/tailmix/runner.js +7 -0
- data/app/javascript/tailmix/stimulus_adapter.js +37 -0
- data/examples/_modal_component.arb +36 -0
- data/examples/modal_component.rb +209 -0
- data/lib/generators/tailmix/install_generator.rb +19 -0
- data/lib/tailmix/configuration.rb +13 -0
- data/lib/tailmix/definition/context_builder.rb +39 -0
- data/lib/tailmix/definition/contexts/action_builder.rb +31 -0
- data/lib/tailmix/definition/contexts/actions/element_builder.rb +30 -0
- data/lib/tailmix/definition/contexts/attribute_builder.rb +21 -0
- data/lib/tailmix/definition/contexts/dimension_builder.rb +34 -0
- data/lib/tailmix/definition/contexts/element_builder.rb +41 -0
- data/lib/tailmix/definition/contexts/stimulus_builder.rb +101 -0
- data/lib/tailmix/definition/contexts/variant_builder.rb +35 -0
- data/lib/tailmix/definition/merger.rb +86 -0
- data/lib/tailmix/definition/result.rb +78 -0
- data/lib/tailmix/definition.rb +11 -0
- data/lib/tailmix/dev/docs.rb +88 -0
- data/lib/tailmix/dev/stimulus_generator.rb +124 -0
- data/lib/tailmix/dev/tools.rb +30 -0
- data/lib/tailmix/dsl.rb +35 -0
- data/lib/tailmix/engine.rb +17 -0
- data/lib/tailmix/html/attributes.rb +94 -0
- data/lib/tailmix/html/class_list.rb +79 -0
- data/lib/tailmix/html/data_map.rb +97 -0
- data/lib/tailmix/html/selector.rb +19 -0
- data/lib/tailmix/html/stimulus_builder.rb +65 -0
- data/lib/tailmix/runtime/action.rb +51 -0
- data/lib/tailmix/runtime/context.rb +74 -0
- data/lib/tailmix/runtime/facade_builder.rb +23 -0
- data/lib/tailmix/runtime/stimulus/compiler.rb +59 -0
- data/lib/tailmix/runtime.rb +14 -0
- data/lib/tailmix/version.rb +1 -1
- data/lib/tailmix.rb +18 -23
- metadata +37 -12
- data/examples/interactive_component.rb +0 -42
- data/examples/status_badge_component.rb +0 -44
- data/lib/tailmix/action.rb +0 -27
- data/lib/tailmix/dimension.rb +0 -18
- data/lib/tailmix/element.rb +0 -24
- data/lib/tailmix/manager.rb +0 -86
- data/lib/tailmix/part.rb +0 -39
- data/lib/tailmix/resolver.rb +0 -28
- data/lib/tailmix/schema.rb +0 -41
- data/lib/tailmix/utils.rb +0 -15
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tailmix
|
|
4
|
+
module Runtime
|
|
5
|
+
class FacadeBuilder
|
|
6
|
+
def self.build(definition)
|
|
7
|
+
Class.new(Tailmix::Runtime::Context) do
|
|
8
|
+
definition.elements.each_key do |element_name|
|
|
9
|
+
define_method(element_name) do |runtime_dimensions = {}|
|
|
10
|
+
attributes_for(element_name, runtime_dimensions)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def inspect
|
|
15
|
+
component_name = @component_instance.class.name || "AnonymousComponent"
|
|
16
|
+
elements_list = @definition.elements.keys.join(", ")
|
|
17
|
+
"#<Tailmix::UI for #{component_name} elements=[#{elements_list}] dimensions=#{@dimensions.inspect}>"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tailmix
|
|
4
|
+
module Runtime
|
|
5
|
+
module Stimulus
|
|
6
|
+
class Compiler
|
|
7
|
+
|
|
8
|
+
def self.call(definition:, data_map:, root_definition:, component:)
|
|
9
|
+
(definition.definitions || []).each do |rule|
|
|
10
|
+
builder = data_map.stimulus
|
|
11
|
+
|
|
12
|
+
case rule[:type]
|
|
13
|
+
when :controller
|
|
14
|
+
builder.controller(rule[:name])
|
|
15
|
+
when :action
|
|
16
|
+
action_data = rule[:data]
|
|
17
|
+
controller_name = rule[:controller]
|
|
18
|
+
|
|
19
|
+
action_string = case action_data[:type]
|
|
20
|
+
when :raw
|
|
21
|
+
action_data[:content]
|
|
22
|
+
when :hash
|
|
23
|
+
action_data[:content].map { |event, method| "#{event}->#{controller_name}##{method}" }.join(" ")
|
|
24
|
+
when :tuple
|
|
25
|
+
event, method = action_data[:content]
|
|
26
|
+
"#{event}->#{controller_name}##{method}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
builder.context(controller_name).action(action_string)
|
|
30
|
+
when :target
|
|
31
|
+
builder.context(rule[:controller]).target(rule[:name])
|
|
32
|
+
when :value
|
|
33
|
+
source = rule[:source]
|
|
34
|
+
|
|
35
|
+
resolved_value = case source[:type]
|
|
36
|
+
when :literal
|
|
37
|
+
source[:content]
|
|
38
|
+
when :proc
|
|
39
|
+
source[:content].call
|
|
40
|
+
when :method
|
|
41
|
+
component.public_send(source[:content])
|
|
42
|
+
else
|
|
43
|
+
# type code here
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
builder.context(rule[:controller]).value(rule[:name], resolved_value)
|
|
47
|
+
|
|
48
|
+
when :param
|
|
49
|
+
builder.context(rule[:controller]).param(rule[:params])
|
|
50
|
+
when :action_payload
|
|
51
|
+
action = root_definition.actions.fetch(rule[:action_name])
|
|
52
|
+
builder.context(rule[:controller]).value(rule[:value_name], action.to_h)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set"
|
|
4
|
+
require_relative "runtime/context"
|
|
5
|
+
require_relative "runtime/facade_builder"
|
|
6
|
+
require_relative "runtime/stimulus/compiler"
|
|
7
|
+
require_relative "html/attributes"
|
|
8
|
+
require_relative "runtime/action"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
module Tailmix
|
|
12
|
+
module Runtime
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/tailmix/version.rb
CHANGED
data/lib/tailmix.rb
CHANGED
|
@@ -1,38 +1,33 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "tailmix/version"
|
|
4
|
-
require_relative "tailmix/
|
|
5
|
-
require_relative "tailmix/
|
|
6
|
-
require_relative "tailmix/
|
|
7
|
-
require_relative "tailmix/
|
|
8
|
-
require_relative "tailmix/dimension"
|
|
9
|
-
require_relative "tailmix/element"
|
|
10
|
-
require_relative "tailmix/utils"
|
|
11
|
-
require_relative "tailmix/action"
|
|
4
|
+
require_relative "tailmix/configuration"
|
|
5
|
+
require_relative "tailmix/dsl"
|
|
6
|
+
require_relative "tailmix/definition"
|
|
7
|
+
require_relative "tailmix/runtime"
|
|
12
8
|
|
|
13
9
|
module Tailmix
|
|
14
|
-
|
|
15
|
-
base.extend(ClassMethods)
|
|
16
|
-
base.instance_variable_set(:@tailmix_schema, nil)
|
|
10
|
+
class Error < StandardError; end
|
|
17
11
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end
|
|
12
|
+
class << self
|
|
13
|
+
attr_writer :configuration
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
@
|
|
15
|
+
def configuration
|
|
16
|
+
@configuration ||= Configuration.new
|
|
24
17
|
end
|
|
25
|
-
end
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
self.tailmix_schema = Schema.new(&block)
|
|
19
|
+
def configure
|
|
20
|
+
yield(configuration)
|
|
30
21
|
end
|
|
31
22
|
end
|
|
32
23
|
|
|
33
|
-
|
|
24
|
+
def self.included(base)
|
|
25
|
+
base.extend(DSL)
|
|
26
|
+
end
|
|
34
27
|
|
|
35
|
-
def tailmix(
|
|
36
|
-
|
|
28
|
+
def tailmix(dimensions = {})
|
|
29
|
+
self.class.tailmix_facade_class.new(self, self.class.tailmix_definition, dimensions)
|
|
37
30
|
end
|
|
38
31
|
end
|
|
32
|
+
|
|
33
|
+
require_relative "tailmix/engine" if defined?(Rails)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tailmix
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexander Fokin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-08-
|
|
11
|
+
date: 2025-08-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -68,17 +68,42 @@ files:
|
|
|
68
68
|
- LICENSE.txt
|
|
69
69
|
- README.md
|
|
70
70
|
- Rakefile
|
|
71
|
-
-
|
|
72
|
-
-
|
|
71
|
+
- app/javascript/tailmix/finder.js
|
|
72
|
+
- app/javascript/tailmix/index.js
|
|
73
|
+
- app/javascript/tailmix/mutator.js
|
|
74
|
+
- app/javascript/tailmix/runner.js
|
|
75
|
+
- app/javascript/tailmix/stimulus_adapter.js
|
|
76
|
+
- examples/_modal_component.arb
|
|
77
|
+
- examples/modal_component.rb
|
|
78
|
+
- lib/generators/tailmix/install_generator.rb
|
|
73
79
|
- lib/tailmix.rb
|
|
74
|
-
- lib/tailmix/
|
|
75
|
-
- lib/tailmix/
|
|
76
|
-
- lib/tailmix/
|
|
77
|
-
- lib/tailmix/
|
|
78
|
-
- lib/tailmix/
|
|
79
|
-
- lib/tailmix/
|
|
80
|
-
- lib/tailmix/
|
|
81
|
-
- lib/tailmix/
|
|
80
|
+
- lib/tailmix/configuration.rb
|
|
81
|
+
- lib/tailmix/definition.rb
|
|
82
|
+
- lib/tailmix/definition/context_builder.rb
|
|
83
|
+
- lib/tailmix/definition/contexts/action_builder.rb
|
|
84
|
+
- lib/tailmix/definition/contexts/actions/element_builder.rb
|
|
85
|
+
- lib/tailmix/definition/contexts/attribute_builder.rb
|
|
86
|
+
- lib/tailmix/definition/contexts/dimension_builder.rb
|
|
87
|
+
- lib/tailmix/definition/contexts/element_builder.rb
|
|
88
|
+
- lib/tailmix/definition/contexts/stimulus_builder.rb
|
|
89
|
+
- lib/tailmix/definition/contexts/variant_builder.rb
|
|
90
|
+
- lib/tailmix/definition/merger.rb
|
|
91
|
+
- lib/tailmix/definition/result.rb
|
|
92
|
+
- lib/tailmix/dev/docs.rb
|
|
93
|
+
- lib/tailmix/dev/stimulus_generator.rb
|
|
94
|
+
- lib/tailmix/dev/tools.rb
|
|
95
|
+
- lib/tailmix/dsl.rb
|
|
96
|
+
- lib/tailmix/engine.rb
|
|
97
|
+
- lib/tailmix/html/attributes.rb
|
|
98
|
+
- lib/tailmix/html/class_list.rb
|
|
99
|
+
- lib/tailmix/html/data_map.rb
|
|
100
|
+
- lib/tailmix/html/selector.rb
|
|
101
|
+
- lib/tailmix/html/stimulus_builder.rb
|
|
102
|
+
- lib/tailmix/runtime.rb
|
|
103
|
+
- lib/tailmix/runtime/action.rb
|
|
104
|
+
- lib/tailmix/runtime/context.rb
|
|
105
|
+
- lib/tailmix/runtime/facade_builder.rb
|
|
106
|
+
- lib/tailmix/runtime/stimulus/compiler.rb
|
|
82
107
|
- lib/tailmix/version.rb
|
|
83
108
|
- sig/tailmix.rbs
|
|
84
109
|
homepage: https://github.com/alexander-s-f/tailmix
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../lib/tailmix"
|
|
4
|
-
|
|
5
|
-
class InteractiveComponent
|
|
6
|
-
include Tailmix
|
|
7
|
-
|
|
8
|
-
tailmix do
|
|
9
|
-
element :container, "p-4 rounded-md"
|
|
10
|
-
element :label, "font-bold"
|
|
11
|
-
|
|
12
|
-
action :highlight, behavior: :toggle do
|
|
13
|
-
element :container, "ring-2 ring-blue-500 bg-blue-50"
|
|
14
|
-
element :label, "text-blue-700"
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
attr_reader :classes
|
|
19
|
-
|
|
20
|
-
def initialize
|
|
21
|
-
@classes = tailmix
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def toggle_highlight
|
|
25
|
-
@classes.actions.highlight.apply!
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def render
|
|
29
|
-
# ...
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
component = InteractiveComponent.new
|
|
34
|
-
puts "Initial container: '#{component.classes.container}'"
|
|
35
|
-
# => Initial container: 'p-4 rounded-md'
|
|
36
|
-
|
|
37
|
-
component.toggle_highlight
|
|
38
|
-
puts "After highlight: '#{component.classes.container}'"
|
|
39
|
-
# => After highlight: 'p-4 rounded-md ring-2 ring-blue-500 bg-blue-50'
|
|
40
|
-
|
|
41
|
-
puts "JSON Recipe: #{component.classes.actions.highlight.to_json}"
|
|
42
|
-
# => JSON Recipe: {"behavior":"toggle","classes":{"container":"ring-2...","label":"text-blue-700"}}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "../lib/tailmix"
|
|
4
|
-
|
|
5
|
-
class StatusBadgeComponent
|
|
6
|
-
include Tailmix
|
|
7
|
-
|
|
8
|
-
tailmix do
|
|
9
|
-
element :badge, "inline-flex items-center font-medium px-2.5 py-0.5 rounded-full" do
|
|
10
|
-
size do
|
|
11
|
-
option :sm, "text-xs", default: true
|
|
12
|
-
option :lg, "text-base"
|
|
13
|
-
end
|
|
14
|
-
status do
|
|
15
|
-
option :success, "bg-green-100 text-green-800", default: true
|
|
16
|
-
option :warning, "bg-yellow-100 text-yellow-800"
|
|
17
|
-
option :error, "bg-red-100 text-red-800"
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
attr_reader :classes
|
|
23
|
-
|
|
24
|
-
def initialize(status: :success, size: :sm)
|
|
25
|
-
@classes = tailmix(status: status, size: size)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def highlight!
|
|
29
|
-
@classes.badge.add("ring-2 ring-offset-2 ring-blue-500")
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def render
|
|
33
|
-
"<span class='#{@classes.badge}'>Status</span>"
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
badge1 = StatusBadgeComponent.new(status: :error, size: :lg)
|
|
38
|
-
puts "Error badge: #{badge1.render}"
|
|
39
|
-
# => Error badge: <span class='inline-flex ... text-base bg-red-100 text-red-800'>Status</span>
|
|
40
|
-
|
|
41
|
-
badge2 = StatusBadgeComponent.new(status: :success)
|
|
42
|
-
badge2.highlight!
|
|
43
|
-
puts "Success badge (highlighted): #{badge2.render}"
|
|
44
|
-
# => Success badge (highlighted): <span class='inline-flex ... text-xs bg-green-100 text-green-800 ring-2 ring-offset-2 ring-blue-500'>Status</span>
|
data/lib/tailmix/action.rb
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "json"
|
|
4
|
-
|
|
5
|
-
module Tailmix
|
|
6
|
-
class Action
|
|
7
|
-
def initialize(manager, behavior:, classes_by_part:)
|
|
8
|
-
@manager = manager
|
|
9
|
-
@behavior = behavior
|
|
10
|
-
@classes_by_part = classes_by_part
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def apply!
|
|
14
|
-
@classes_by_part.each do |part_name, classes|
|
|
15
|
-
part_object = @manager.public_send(part_name)
|
|
16
|
-
part_object.public_send(@behavior, classes)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def to_json(*_args)
|
|
21
|
-
{
|
|
22
|
-
behavior: @behavior,
|
|
23
|
-
classes: @classes_by_part
|
|
24
|
-
}.to_json
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
data/lib/tailmix/dimension.rb
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Tailmix
|
|
4
|
-
class Dimension
|
|
5
|
-
attr_reader :options, :default_option
|
|
6
|
-
|
|
7
|
-
def initialize(&block)
|
|
8
|
-
@options = {}
|
|
9
|
-
@default_option = nil
|
|
10
|
-
instance_eval(&block) if block_given?
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def option(name, classes, default: false)
|
|
14
|
-
@options[name.to_sym] = classes
|
|
15
|
-
@default_option = name.to_sym if default
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
data/lib/tailmix/element.rb
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "dimension"
|
|
4
|
-
|
|
5
|
-
module Tailmix
|
|
6
|
-
class Element
|
|
7
|
-
attr_reader :base_classes, :dimensions
|
|
8
|
-
|
|
9
|
-
def initialize(base_classes, &block)
|
|
10
|
-
@base_classes = base_classes
|
|
11
|
-
@dimensions = {}
|
|
12
|
-
instance_eval(&block) if block_given?
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def method_missing(method_name, &block)
|
|
16
|
-
dimension_name = method_name.to_sym
|
|
17
|
-
@dimensions[dimension_name] = Dimension.new(&block)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def respond_to_missing?(method_name, include_private = false)
|
|
21
|
-
true
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
data/lib/tailmix/manager.rb
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "resolver"
|
|
4
|
-
require_relative "part"
|
|
5
|
-
require_relative "utils"
|
|
6
|
-
require_relative "action"
|
|
7
|
-
|
|
8
|
-
module Tailmix
|
|
9
|
-
class Manager
|
|
10
|
-
def initialize(schema, initial_variants = {})
|
|
11
|
-
@schema = schema
|
|
12
|
-
@current_variants = {}
|
|
13
|
-
@part_objects = {}
|
|
14
|
-
|
|
15
|
-
defaults = get_defaults_from_schema
|
|
16
|
-
combine(Utils.deep_merge(defaults, initial_variants))
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def combine(variants_to_apply = {})
|
|
20
|
-
@current_variants = Utils.deep_merge(@current_variants, variants_to_apply)
|
|
21
|
-
rebuild_parts!
|
|
22
|
-
self
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def method_missing(method_name, *args, &block)
|
|
26
|
-
part_name = method_name.to_sym
|
|
27
|
-
if @part_objects.key?(part_name)
|
|
28
|
-
@part_objects[part_name]
|
|
29
|
-
else
|
|
30
|
-
super
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def respond_to_missing?(method_name, include_private = false)
|
|
35
|
-
@part_objects.key?(method_name.to_sym) || super
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def actions
|
|
39
|
-
@action_proxy ||= ActionProxy.new(self, @schema)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
class ActionProxy
|
|
43
|
-
def initialize(manager, schema)
|
|
44
|
-
@manager = manager
|
|
45
|
-
@schema = schema
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def method_missing(method_name, *args, &block)
|
|
49
|
-
action_name = method_name.to_sym
|
|
50
|
-
|
|
51
|
-
if @schema.actions.key?(action_name)
|
|
52
|
-
action_definition = @schema.actions[action_name]
|
|
53
|
-
|
|
54
|
-
Action.new(@manager, **action_definition)
|
|
55
|
-
else
|
|
56
|
-
super
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def respond_to_missing?(method_name, include_private = false)
|
|
61
|
-
@schema.actions.key?(method_name.to_sym) || super
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
private
|
|
66
|
-
|
|
67
|
-
def rebuild_parts!
|
|
68
|
-
resolved_struct = Resolver.call(@schema, @current_variants)
|
|
69
|
-
@part_objects = {}
|
|
70
|
-
|
|
71
|
-
resolved_struct.to_h.each do |part_name, class_string|
|
|
72
|
-
@part_objects[part_name] = Part.new(class_string || "")
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def get_defaults_from_schema
|
|
77
|
-
defaults = {}
|
|
78
|
-
@schema.elements.each_value do |element|
|
|
79
|
-
element.dimensions.each do |dim_name, dim|
|
|
80
|
-
defaults[dim_name] = dim.default_option if dim.default_option
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
defaults
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
data/lib/tailmix/part.rb
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "set"
|
|
4
|
-
|
|
5
|
-
module Tailmix
|
|
6
|
-
class Part
|
|
7
|
-
def initialize(class_string)
|
|
8
|
-
@classes = Set.new(class_string.to_s.split)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def add(*new_classes)
|
|
12
|
-
@classes.merge(process_args(new_classes))
|
|
13
|
-
self
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def remove(*classes_to_remove)
|
|
17
|
-
@classes.subtract(process_args(classes_to_remove))
|
|
18
|
-
self
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def toggle(*classes_to_toggle)
|
|
22
|
-
process_args(classes_to_toggle).each do |cls|
|
|
23
|
-
@classes.delete?(cls) || @classes.add(cls)
|
|
24
|
-
end
|
|
25
|
-
self
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def to_s
|
|
29
|
-
@classes.to_a.join(" ")
|
|
30
|
-
end
|
|
31
|
-
alias to_str to_s
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
def process_args(args)
|
|
36
|
-
args.flat_map { |arg| arg.to_s.split }
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
data/lib/tailmix/resolver.rb
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "ostruct"
|
|
4
|
-
|
|
5
|
-
module Tailmix
|
|
6
|
-
module Resolver
|
|
7
|
-
def self.call(schema, active_variants = {})
|
|
8
|
-
resolved_parts = schema.elements.each_with_object({}) do |(element_name, element), result|
|
|
9
|
-
class_list = []
|
|
10
|
-
|
|
11
|
-
class_list << element.base_classes
|
|
12
|
-
|
|
13
|
-
element.dimensions.each do |dimension_name, dimension|
|
|
14
|
-
active_option = active_variants[dimension_name] || dimension.default_option
|
|
15
|
-
|
|
16
|
-
if active_option
|
|
17
|
-
variant_class = dimension.options[active_option]
|
|
18
|
-
class_list << variant_class
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
result[element_name] = class_list.compact.join(" ")
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
OpenStruct.new(resolved_parts)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
data/lib/tailmix/schema.rb
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "element"
|
|
4
|
-
|
|
5
|
-
module Tailmix
|
|
6
|
-
class Schema
|
|
7
|
-
attr_reader :elements, :actions
|
|
8
|
-
|
|
9
|
-
def initialize(&block)
|
|
10
|
-
@elements = {}
|
|
11
|
-
@actions = {}
|
|
12
|
-
instance_eval(&block) if block_given?
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def element(name, base_classes, &block)
|
|
16
|
-
@elements[name.to_sym] = Element.new(base_classes, &block)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def action(name, behavior: :toggle, &block)
|
|
20
|
-
builder = ActionBuilder.new
|
|
21
|
-
builder.instance_eval(&block)
|
|
22
|
-
|
|
23
|
-
@actions[name.to_sym] = {
|
|
24
|
-
behavior: behavior,
|
|
25
|
-
classes_by_part: builder.classes_by_part
|
|
26
|
-
}
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
class ActionBuilder
|
|
30
|
-
attr_reader :classes_by_part
|
|
31
|
-
|
|
32
|
-
def initialize
|
|
33
|
-
@classes_by_part = {}
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def element(name, classes)
|
|
37
|
-
@classes_by_part[name.to_sym] = classes
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
data/lib/tailmix/utils.rb
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Tailmix
|
|
4
|
-
module Utils
|
|
5
|
-
def self.deep_merge(original_hash, other_hash)
|
|
6
|
-
other_hash.each_with_object(original_hash.dup) do |(key, value), result|
|
|
7
|
-
if value.is_a?(Hash) && result[key].is_a?(Hash)
|
|
8
|
-
result[key] = deep_merge(result[key], value)
|
|
9
|
-
else
|
|
10
|
-
result[key] = value
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|