tailmix 0.1.0 → 0.4.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/README.md +147 -85
  4. data/app/javascript/tailmix/finder.js +12 -0
  5. data/app/javascript/tailmix/index.js +7 -0
  6. data/app/javascript/tailmix/mutator.js +28 -0
  7. data/app/javascript/tailmix/runner.js +7 -0
  8. data/app/javascript/tailmix/stimulus_adapter.js +37 -0
  9. data/examples/_modal_component.arb +36 -0
  10. data/examples/modal_component.rb +180 -0
  11. data/lib/generators/tailmix/install_generator.rb +19 -0
  12. data/lib/tailmix/definition/context_builder.rb +39 -0
  13. data/lib/tailmix/definition/contexts/action_builder.rb +31 -0
  14. data/lib/tailmix/definition/contexts/actions/element_builder.rb +30 -0
  15. data/lib/tailmix/definition/contexts/attribute_builder.rb +21 -0
  16. data/lib/tailmix/definition/contexts/dimension_builder.rb +16 -0
  17. data/lib/tailmix/definition/contexts/element_builder.rb +41 -0
  18. data/lib/tailmix/definition/contexts/stimulus_builder.rb +101 -0
  19. data/lib/tailmix/definition/merger.rb +93 -0
  20. data/lib/tailmix/definition/result.rb +31 -0
  21. data/lib/tailmix/definition.rb +11 -0
  22. data/lib/tailmix/dev/docs.rb +82 -0
  23. data/lib/tailmix/dev/stimulus_generator.rb +124 -0
  24. data/lib/tailmix/dev/tools.rb +26 -0
  25. data/lib/tailmix/engine.rb +17 -0
  26. data/lib/tailmix/html/attributes.rb +71 -0
  27. data/lib/tailmix/html/class_list.rb +79 -0
  28. data/lib/tailmix/html/data_map.rb +95 -0
  29. data/lib/tailmix/html/stimulus_builder.rb +65 -0
  30. data/lib/tailmix/runtime/action.rb +51 -0
  31. data/lib/tailmix/runtime/context.rb +66 -0
  32. data/lib/tailmix/runtime/facade_builder.rb +23 -0
  33. data/lib/tailmix/runtime/stimulus/compiler.rb +59 -0
  34. data/lib/tailmix/runtime.rb +14 -0
  35. data/lib/tailmix/version.rb +1 -1
  36. data/lib/tailmix.rb +48 -18
  37. metadata +33 -10
  38. data/examples/status_badge_component.rb +0 -44
  39. data/lib/tailmix/dimension.rb +0 -18
  40. data/lib/tailmix/element.rb +0 -24
  41. data/lib/tailmix/manager.rb +0 -58
  42. data/lib/tailmix/part.rb +0 -39
  43. data/lib/tailmix/resolver.rb +0 -28
  44. data/lib/tailmix/schema.rb +0 -18
  45. data/lib/tailmix/utils.rb +0 -15
@@ -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>
@@ -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
@@ -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
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "resolver"
4
- require_relative "part"
5
- require_relative "utils"
6
-
7
- module Tailmix
8
- class Manager
9
- def initialize(schema, initial_variants = {})
10
- @schema = schema
11
- @current_variants = {}
12
- @part_objects = {}
13
-
14
- defaults = get_defaults_from_schema
15
- combine(Utils.deep_merge(defaults, initial_variants))
16
- end
17
-
18
- def combine(variants_to_apply = {})
19
- @current_variants = Utils.deep_merge(@current_variants, variants_to_apply)
20
- rebuild_parts!
21
- self
22
- end
23
-
24
- def method_missing(method_name, *args, &block)
25
- part_name = method_name.to_sym
26
- if @part_objects.key?(part_name)
27
- @part_objects[part_name]
28
- else
29
- super
30
- end
31
- end
32
-
33
- def respond_to_missing?(method_name, include_private = false)
34
- @part_objects.key?(method_name.to_sym) || super
35
- end
36
-
37
- private
38
-
39
- def rebuild_parts!
40
- resolved_struct = Resolver.call(@schema, @current_variants)
41
- @part_objects = {}
42
-
43
- resolved_struct.to_h.each do |part_name, class_string|
44
- @part_objects[part_name] = Part.new(class_string || "")
45
- end
46
- end
47
-
48
- def get_defaults_from_schema
49
- defaults = {}
50
- @schema.elements.each_value do |element|
51
- element.dimensions.each do |dim_name, dim|
52
- defaults[dim_name] = dim.default_option if dim.default_option
53
- end
54
- end
55
- defaults
56
- end
57
- end
58
- 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
@@ -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
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "element"
4
-
5
- module Tailmix
6
- class Schema
7
- attr_reader :elements
8
-
9
- def initialize(&block)
10
- @elements = {}
11
- instance_eval(&block) if block_given?
12
- end
13
-
14
- def element(name, base_classes, &block)
15
- @elements[name.to_sym] = Element.new(base_classes, &block)
16
- end
17
- end
18
- 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