vident 1.0.0.beta2 → 1.0.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 +4 -4
- data/CHANGELOG.md +32 -1
- data/README.md +171 -17
- data/lib/generators/vident/install/install_generator.rb +53 -0
- data/lib/generators/vident/install/templates/vident.rb +20 -0
- data/lib/vident/caching.rb +3 -9
- data/lib/vident/child_element_helper.rb +22 -21
- data/lib/vident/component.rb +3 -10
- data/lib/vident/component_attribute_resolver.rb +21 -36
- data/lib/vident/component_class_lists.rb +4 -3
- data/lib/vident/stable_id.rb +48 -17
- data/lib/vident/stimulus/naming.rb +19 -0
- data/lib/vident/stimulus/primitive.rb +38 -0
- data/lib/vident/stimulus.rb +31 -0
- data/lib/vident/stimulus_action.rb +58 -23
- data/lib/vident/stimulus_attribute_base.rb +27 -23
- data/lib/vident/stimulus_attributes.rb +56 -185
- data/lib/vident/stimulus_builder.rb +66 -87
- data/lib/vident/stimulus_class.rb +3 -9
- data/lib/vident/stimulus_class_collection.rb +1 -5
- data/lib/vident/stimulus_collection_base.rb +4 -12
- data/lib/vident/stimulus_component.rb +8 -7
- data/lib/vident/stimulus_controller.rb +10 -13
- data/lib/vident/stimulus_data_attribute_builder.rb +15 -74
- data/lib/vident/stimulus_helper.rb +4 -12
- data/lib/vident/stimulus_null.rb +21 -0
- data/lib/vident/stimulus_outlet.rb +3 -9
- data/lib/vident/stimulus_outlet_collection.rb +1 -5
- data/lib/vident/stimulus_param.rb +42 -0
- data/lib/vident/stimulus_param_collection.rb +11 -0
- data/lib/vident/stimulus_target.rb +7 -17
- data/lib/vident/stimulus_target_collection.rb +2 -6
- data/lib/vident/stimulus_value.rb +14 -44
- data/lib/vident/stimulus_value_collection.rb +1 -5
- data/lib/vident/tailwind.rb +0 -2
- data/lib/vident/version.rb +1 -1
- data/lib/vident.rb +7 -12
- data/skills/vident/SKILL.md +628 -0
- metadata +10 -1
|
@@ -1,90 +1,31 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Vident
|
|
4
|
-
# Builds a hash of Stimulus data attributes from collections of stimulus objects
|
|
5
|
-
# Handles merging multiple actions, targets, outlets, values, and classes
|
|
6
|
-
# into the final data-* attributes needed for HTML elements
|
|
7
4
|
class StimulusDataAttributeBuilder
|
|
8
|
-
def initialize(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@
|
|
13
|
-
@values = Array(values)
|
|
14
|
-
@classes = Array(classes)
|
|
5
|
+
def initialize(**collections_by_name)
|
|
6
|
+
unknown = collections_by_name.keys - Stimulus.names
|
|
7
|
+
raise ArgumentError, "Unknown stimulus primitive(s) #{unknown.inspect}" if unknown.any?
|
|
8
|
+
|
|
9
|
+
@collections_by_name = collections_by_name.transform_values { |v| Array(v) }
|
|
15
10
|
end
|
|
16
11
|
|
|
17
|
-
# Build the final data attributes hash
|
|
18
12
|
def build
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
**merged_targets,
|
|
23
|
-
**merged_outlets,
|
|
24
|
-
**merged_values,
|
|
25
|
-
**merged_classes
|
|
26
|
-
}.transform_keys(&:to_s).compact
|
|
13
|
+
Stimulus::PRIMITIVES.each_with_object({}) do |primitive, attrs|
|
|
14
|
+
attrs.merge!(merge_collection(primitive.collection_class, @collections_by_name[primitive.name] || []))
|
|
15
|
+
end.transform_keys(&:to_s).compact
|
|
27
16
|
end
|
|
28
17
|
|
|
29
18
|
private
|
|
30
19
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if
|
|
35
|
-
StimulusControllerCollection.merge(*@controllers).to_h
|
|
36
|
-
else
|
|
37
|
-
StimulusControllerCollection.new(@controllers).to_h
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def merged_actions
|
|
42
|
-
return {} if @actions.empty?
|
|
43
|
-
|
|
44
|
-
if @actions.first.is_a?(StimulusActionCollection)
|
|
45
|
-
StimulusActionCollection.merge(*@actions).to_h
|
|
46
|
-
else
|
|
47
|
-
StimulusActionCollection.new(@actions).to_h
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def merged_targets
|
|
52
|
-
return {} if @targets.empty?
|
|
53
|
-
|
|
54
|
-
if @targets.first.is_a?(StimulusTargetCollection)
|
|
55
|
-
StimulusTargetCollection.merge(*@targets).to_h
|
|
56
|
-
else
|
|
57
|
-
StimulusTargetCollection.new(@targets).to_h
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def merged_outlets
|
|
62
|
-
return {} if @outlets.empty?
|
|
63
|
-
|
|
64
|
-
if @outlets.first.is_a?(StimulusOutletCollection)
|
|
65
|
-
StimulusOutletCollection.merge(*@outlets).to_h
|
|
66
|
-
else
|
|
67
|
-
StimulusOutletCollection.new(@outlets).to_h
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def merged_values
|
|
72
|
-
return {} if @values.empty?
|
|
73
|
-
|
|
74
|
-
if @values.first.is_a?(StimulusValueCollection)
|
|
75
|
-
StimulusValueCollection.merge(*@values).to_h
|
|
76
|
-
else
|
|
77
|
-
StimulusValueCollection.new(@values).to_h
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def merged_classes
|
|
82
|
-
return {} if @classes.empty?
|
|
20
|
+
# Items are either pre-built collections (DSL / resolver path) or raw value
|
|
21
|
+
# objects (child_element path). Merge-or-wrap accordingly.
|
|
22
|
+
def merge_collection(collection_class, items)
|
|
23
|
+
return {} if items.empty?
|
|
83
24
|
|
|
84
|
-
if
|
|
85
|
-
|
|
25
|
+
if items.first.is_a?(collection_class)
|
|
26
|
+
collection_class.merge(*items).to_h
|
|
86
27
|
else
|
|
87
|
-
|
|
28
|
+
collection_class.new(items).to_h
|
|
88
29
|
end
|
|
89
30
|
end
|
|
90
31
|
end
|
|
@@ -47,28 +47,20 @@ module Vident
|
|
|
47
47
|
|
|
48
48
|
protected
|
|
49
49
|
|
|
50
|
-
def stimulus_dsl_builder
|
|
51
|
-
@stimulus_builder
|
|
52
|
-
end
|
|
50
|
+
def stimulus_dsl_builder = @stimulus_builder
|
|
53
51
|
end
|
|
54
52
|
|
|
55
53
|
# Instance method to get DSL attributes for this component instance
|
|
56
|
-
def stimulus_dsl_attributes
|
|
57
|
-
self.class.stimulus_dsl_attributes(self)
|
|
58
|
-
end
|
|
54
|
+
def stimulus_dsl_attributes = self.class.stimulus_dsl_attributes(self)
|
|
59
55
|
|
|
60
56
|
# Instance method to resolve prop-mapped values at runtime
|
|
61
57
|
def resolve_values_from_props(prop_names)
|
|
62
58
|
return {} if prop_names.empty?
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
prop_names.each do |name|
|
|
60
|
+
prop_names.each_with_object({}) do |name, resolved|
|
|
66
61
|
# Map from instance variable if it exists
|
|
67
|
-
if instance_variable_defined?("@#{name}")
|
|
68
|
-
resolved[name] = instance_variable_get("@#{name}")
|
|
69
|
-
end
|
|
62
|
+
resolved[name] = instance_variable_get("@#{name}") if instance_variable_defined?("@#{name}")
|
|
70
63
|
end
|
|
71
|
-
resolved
|
|
72
64
|
end
|
|
73
65
|
end
|
|
74
66
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Vident
|
|
4
|
+
# Sentinel: emits the literal string "null" as the data attribute value.
|
|
5
|
+
# For Stimulus `Object` and `Array` value types this is JSON-parsed to JS `null`;
|
|
6
|
+
# other value types will read it as garbage ("null" string / NaN / truthy), so only
|
|
7
|
+
# use this with nullable Object/Array values.
|
|
8
|
+
#
|
|
9
|
+
# A bare `nil` (static or returned from a proc) omits the attribute entirely so
|
|
10
|
+
# Stimulus uses its per-type default. Reach for this sentinel only when you need
|
|
11
|
+
# an explicit JS `null`.
|
|
12
|
+
StimulusNull = Object.new
|
|
13
|
+
def StimulusNull.inspect
|
|
14
|
+
"Vident::StimulusNull"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def StimulusNull.to_s
|
|
18
|
+
"null"
|
|
19
|
+
end
|
|
20
|
+
StimulusNull.freeze
|
|
21
|
+
end
|
|
@@ -9,17 +9,11 @@ module Vident
|
|
|
9
9
|
super(*args, implied_controller: implied_controller)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def to_s
|
|
13
|
-
@selector
|
|
14
|
-
end
|
|
12
|
+
def to_s = @selector
|
|
15
13
|
|
|
16
|
-
def data_attribute_name
|
|
17
|
-
"#{@controller}-#{@outlet_name}-outlet"
|
|
18
|
-
end
|
|
14
|
+
def data_attribute_name = "#{@controller}-#{@outlet_name}-outlet"
|
|
19
15
|
|
|
20
|
-
def data_attribute_value
|
|
21
|
-
@selector
|
|
22
|
-
end
|
|
16
|
+
def data_attribute_value = @selector
|
|
23
17
|
|
|
24
18
|
private
|
|
25
19
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Vident
|
|
4
|
+
# `data-<controller>-<name>-param="..."` — readable on the JS side as
|
|
5
|
+
# `event.params.<camelName>`. Element-scoped: every action on the element
|
|
6
|
+
# sees the same params.
|
|
7
|
+
class StimulusParam < StimulusAttributeBase
|
|
8
|
+
attr_reader :controller, :param_name, :value
|
|
9
|
+
|
|
10
|
+
def to_s = @value.to_s
|
|
11
|
+
|
|
12
|
+
def data_attribute_name = "#{@controller}-#{@param_name}-param"
|
|
13
|
+
|
|
14
|
+
def data_attribute_value = @value
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def parse_arguments(*args)
|
|
19
|
+
case args.size
|
|
20
|
+
when 2 then parse_two_arguments(*args)
|
|
21
|
+
when 3 then parse_three_arguments(*args)
|
|
22
|
+
else raise ArgumentError, "Invalid number of arguments: #{args.size} (#{args.inspect}). Did you pass an array of hashes?"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def parse_two_arguments(param_name, value)
|
|
27
|
+
raise ArgumentError, "Invalid argument types: #{param_name.class}, #{value.class}" unless param_name.is_a?(Symbol)
|
|
28
|
+
@controller = implied_controller_name
|
|
29
|
+
@param_name = param_name.to_s.dasherize
|
|
30
|
+
@value = serialize_value(value)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def parse_three_arguments(controller, param_name, value)
|
|
34
|
+
unless controller.is_a?(String) && param_name.is_a?(Symbol)
|
|
35
|
+
raise ArgumentError, "Invalid argument types: #{controller.class}, #{param_name.class}, #{value.class}"
|
|
36
|
+
end
|
|
37
|
+
@controller = stimulize_path(controller)
|
|
38
|
+
@param_name = param_name.to_s.dasherize
|
|
39
|
+
@value = serialize_value(value)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -4,19 +4,13 @@ module Vident
|
|
|
4
4
|
class StimulusTarget < StimulusAttributeBase
|
|
5
5
|
attr_reader :controller, :name
|
|
6
6
|
|
|
7
|
-
def to_s
|
|
8
|
-
@name
|
|
9
|
-
end
|
|
7
|
+
def to_s = @name
|
|
10
8
|
|
|
11
9
|
# Returns the data attribute name for this target
|
|
12
|
-
def data_attribute_name
|
|
13
|
-
"#{@controller}-target"
|
|
14
|
-
end
|
|
10
|
+
def data_attribute_name = "#{@controller}-target"
|
|
15
11
|
|
|
16
12
|
# Returns the target name value for the data attribute
|
|
17
|
-
def data_attribute_value
|
|
18
|
-
@name
|
|
19
|
-
end
|
|
13
|
+
def data_attribute_value = @name
|
|
20
14
|
|
|
21
15
|
private
|
|
22
16
|
|
|
@@ -33,14 +27,10 @@ module Vident
|
|
|
33
27
|
|
|
34
28
|
def parse_single_argument(arg)
|
|
35
29
|
@controller = implied_controller_name
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# 1 string arg, assume it's a target name on implied controller
|
|
41
|
-
@name = arg
|
|
42
|
-
else
|
|
43
|
-
raise ArgumentError, "Invalid argument type: #{arg.class}"
|
|
30
|
+
@name = case arg
|
|
31
|
+
when Symbol then js_name(arg) # name of target on implied controller
|
|
32
|
+
when String then arg # target name on implied controller
|
|
33
|
+
else raise ArgumentError, "Invalid argument type: #{arg.class}"
|
|
44
34
|
end
|
|
45
35
|
end
|
|
46
36
|
|
|
@@ -8,12 +8,8 @@ module Vident
|
|
|
8
8
|
merged = {}
|
|
9
9
|
items.each do |target|
|
|
10
10
|
target.to_h.each do |key, value|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"#{merged[key]} #{value}"
|
|
14
|
-
else
|
|
15
|
-
value
|
|
16
|
-
end
|
|
11
|
+
# Merge space-separated values for same target attribute
|
|
12
|
+
merged[key] = merged.key?(key) ? "#{merged[key]} #{value}" : value
|
|
17
13
|
end
|
|
18
14
|
end
|
|
19
15
|
merged
|
|
@@ -1,69 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "json"
|
|
4
|
-
|
|
5
3
|
module Vident
|
|
6
4
|
class StimulusValue < StimulusAttributeBase
|
|
7
5
|
attr_reader :controller, :value_name, :value
|
|
8
6
|
|
|
9
|
-
def to_s
|
|
10
|
-
@value.to_s
|
|
11
|
-
end
|
|
7
|
+
def to_s = @value.to_s
|
|
12
8
|
|
|
13
|
-
def data_attribute_name
|
|
14
|
-
"#{@controller}-#{@value_name}-value"
|
|
15
|
-
end
|
|
9
|
+
def data_attribute_name = "#{@controller}-#{@value_name}-value"
|
|
16
10
|
|
|
17
|
-
def data_attribute_value
|
|
18
|
-
@value
|
|
19
|
-
end
|
|
11
|
+
def data_attribute_value = @value
|
|
20
12
|
|
|
21
13
|
private
|
|
22
14
|
|
|
23
15
|
def parse_arguments(*args)
|
|
24
16
|
case args.size
|
|
25
|
-
when 2
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
parse_three_arguments(args[0], args[1], args[2])
|
|
29
|
-
else
|
|
30
|
-
raise ArgumentError, "Invalid number of arguments: #{args.size} (#{args.inspect}). Did you pass an array of hashes?"
|
|
17
|
+
when 2 then parse_two_arguments(*args)
|
|
18
|
+
when 3 then parse_three_arguments(*args)
|
|
19
|
+
else raise ArgumentError, "Invalid number of arguments: #{args.size} (#{args.inspect}). Did you pass an array of hashes?"
|
|
31
20
|
end
|
|
32
21
|
end
|
|
33
22
|
|
|
34
23
|
def parse_two_arguments(value_name, value)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@value = serialize_value(value)
|
|
40
|
-
else
|
|
41
|
-
raise ArgumentError, "Invalid argument types: #{value_name.class}, #{value.class}"
|
|
42
|
-
end
|
|
24
|
+
raise ArgumentError, "Invalid argument types: #{value_name.class}, #{value.class}" unless value_name.is_a?(Symbol)
|
|
25
|
+
@controller = implied_controller_name
|
|
26
|
+
@value_name = value_name.to_s.dasherize
|
|
27
|
+
@value = serialize_value(value)
|
|
43
28
|
end
|
|
44
29
|
|
|
45
30
|
def parse_three_arguments(controller, value_name, value)
|
|
46
|
-
|
|
47
|
-
# controller + value name + value
|
|
48
|
-
@controller = stimulize_path(controller)
|
|
49
|
-
@value_name = value_name.to_s.dasherize
|
|
50
|
-
@value = serialize_value(value)
|
|
51
|
-
else
|
|
31
|
+
unless controller.is_a?(String) && value_name.is_a?(Symbol)
|
|
52
32
|
raise ArgumentError, "Invalid argument types: #{controller.class}, #{value_name.class}, #{value.class}"
|
|
53
33
|
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
case value
|
|
58
|
-
when Array, Hash
|
|
59
|
-
value.to_json
|
|
60
|
-
when TrueClass, FalseClass
|
|
61
|
-
value.to_s
|
|
62
|
-
when Numeric
|
|
63
|
-
value.to_s
|
|
64
|
-
else
|
|
65
|
-
value.to_s
|
|
66
|
-
end
|
|
34
|
+
@controller = stimulize_path(controller)
|
|
35
|
+
@value_name = value_name.to_s.dasherize
|
|
36
|
+
@value = serialize_value(value)
|
|
67
37
|
end
|
|
68
38
|
end
|
|
69
39
|
end
|
data/lib/vident/tailwind.rb
CHANGED
data/lib/vident/version.rb
CHANGED
data/lib/vident.rb
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
if ENV["COVERAGE"]
|
|
4
|
-
require "simplecov"
|
|
5
|
-
SimpleCov.command_name "Vident"
|
|
6
|
-
SimpleCov.root File.expand_path("..", __dir__)
|
|
7
|
-
SimpleCov.start do
|
|
8
|
-
add_filter "/test/"
|
|
9
|
-
add_filter "/tmp/"
|
|
10
|
-
add_filter "/bin/"
|
|
11
|
-
add_filter "/lib/vident/engine.rb"
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
3
|
require "active_support"
|
|
16
4
|
require "active_support/concern"
|
|
17
5
|
require "literal"
|
|
@@ -19,12 +7,14 @@ require "literal"
|
|
|
19
7
|
require "vident/version"
|
|
20
8
|
require "vident/tailwind"
|
|
21
9
|
|
|
10
|
+
require "vident/stimulus_null"
|
|
22
11
|
require "vident/stimulus_attribute_base"
|
|
23
12
|
require "vident/stimulus_controller"
|
|
24
13
|
require "vident/stimulus_action"
|
|
25
14
|
require "vident/stimulus_target"
|
|
26
15
|
require "vident/stimulus_outlet"
|
|
27
16
|
require "vident/stimulus_value"
|
|
17
|
+
require "vident/stimulus_param"
|
|
28
18
|
require "vident/stimulus_class"
|
|
29
19
|
|
|
30
20
|
require "vident/stimulus_collection_base"
|
|
@@ -33,8 +23,13 @@ require "vident/stimulus_action_collection"
|
|
|
33
23
|
require "vident/stimulus_target_collection"
|
|
34
24
|
require "vident/stimulus_outlet_collection"
|
|
35
25
|
require "vident/stimulus_value_collection"
|
|
26
|
+
require "vident/stimulus_param_collection"
|
|
36
27
|
require "vident/stimulus_class_collection"
|
|
37
28
|
|
|
29
|
+
require "vident/stimulus/primitive"
|
|
30
|
+
require "vident/stimulus/naming"
|
|
31
|
+
require "vident/stimulus"
|
|
32
|
+
|
|
38
33
|
require "vident/stimulus_attributes"
|
|
39
34
|
require "vident/stimulus_data_attribute_builder"
|
|
40
35
|
|