vident 0.1.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 +7 -0
- data/.standard.yml +3 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +29 -0
- data/LICENSE.txt +21 -0
- data/README.md +349 -0
- data/Rakefile +14 -0
- data/examples/ex1.gif +0 -0
- data/lib/tasks/vident.rake +37 -0
- data/lib/vident/attributes/not_typed.rb +78 -0
- data/lib/vident/attributes/typed.rb +180 -0
- data/lib/vident/attributes/typed_niling_struct.rb +27 -0
- data/lib/vident/attributes/types.rb +16 -0
- data/lib/vident/base.rb +286 -0
- data/lib/vident/component.rb +32 -0
- data/lib/vident/railtie.rb +10 -0
- data/lib/vident/root_component/base.rb +239 -0
- data/lib/vident/root_component/using_phlex_html.rb +44 -0
- data/lib/vident/root_component/using_view_component.rb +44 -0
- data/lib/vident/stable_id.rb +24 -0
- data/lib/vident/typed_component.rb +48 -0
- data/lib/vident/version.rb +5 -0
- data/lib/vident.rb +33 -0
- data/sig/vident.rbs +4 -0
- metadata +85 -0
@@ -0,0 +1,239 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Vident
|
4
|
+
module RootComponent
|
5
|
+
module Base
|
6
|
+
def initialize(
|
7
|
+
controllers: nil,
|
8
|
+
actions: nil,
|
9
|
+
targets: nil,
|
10
|
+
named_classes: nil, # https://stimulus.hotwired.dev/reference/css-classes
|
11
|
+
data_maps: nil,
|
12
|
+
element_tag: nil,
|
13
|
+
id: nil,
|
14
|
+
html_options: nil
|
15
|
+
)
|
16
|
+
@element_tag = element_tag
|
17
|
+
@html_options = html_options
|
18
|
+
@id = id
|
19
|
+
@controllers = Array.wrap(controllers)
|
20
|
+
@actions = actions
|
21
|
+
@targets = targets
|
22
|
+
@named_classes = named_classes
|
23
|
+
@data_map_kvs = {}
|
24
|
+
@data_maps = data_maps
|
25
|
+
end
|
26
|
+
|
27
|
+
# The view component's helpers for setting stimulus data-* attributes on this component.
|
28
|
+
|
29
|
+
# TODO: rename
|
30
|
+
# Create a Stimulus action string, and returns it
|
31
|
+
# examples:
|
32
|
+
# action(:my_thing) => "current_controller#myThing"
|
33
|
+
# action(:click, :my_thing) => "click->current_controller#myThing"
|
34
|
+
# action("click->current_controller#myThing") => "click->current_controller#myThing"
|
35
|
+
# action("path/to/current", :my_thing) => "path--to--current_controller#myThing"
|
36
|
+
# action(:click, "path/to/current", :my_thing) => "click->path--to--current_controller#myThing"
|
37
|
+
def action(*args)
|
38
|
+
part1, part2, part3 = args
|
39
|
+
(args.size == 1) ? parse_action_arg(part1) : parse_multiple_action_args(part1, part2, part3)
|
40
|
+
end
|
41
|
+
|
42
|
+
def action_data_attribute(*actions)
|
43
|
+
{action: parse_actions(actions).join(" ")}
|
44
|
+
end
|
45
|
+
|
46
|
+
# TODO: rename & make stimulus Target class instance and returns it, which can convert to String
|
47
|
+
# Create a Stimulus Target and returns it
|
48
|
+
# examples:
|
49
|
+
# target(:my_target) => {controller: 'current_controller' name: 'myTarget'}
|
50
|
+
# target("path/to/current", :my_target) => {controller: 'path--to--current_controller', name: 'myTarget'}
|
51
|
+
def target(name, part2 = nil)
|
52
|
+
if part2.nil?
|
53
|
+
{controller: implied_controller_name, name: js_name(name)}
|
54
|
+
else
|
55
|
+
{controller: stimulize_path(name), name: js_name(part2)}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def target_data_attribute(name)
|
60
|
+
build_target_data_attributes([target(name)])
|
61
|
+
end
|
62
|
+
|
63
|
+
# Getter for a named classes list so can be used in view to set initial state on SSR
|
64
|
+
# Returns a String of classes that can be used in a `class` attribute.
|
65
|
+
def named_classes(*names)
|
66
|
+
names.map { |name| convert_classes_list_to_string(@named_classes[name]) }.join(" ")
|
67
|
+
end
|
68
|
+
|
69
|
+
# Helpers for generating the Stimulus data-* attributes directly
|
70
|
+
|
71
|
+
# Return the HTML `data-controller` attribute
|
72
|
+
def with_controllers
|
73
|
+
"data-controller='#{controller_list}'".html_safe
|
74
|
+
end
|
75
|
+
|
76
|
+
# Return the HTML `data-target` attribute
|
77
|
+
def as_targets(*targets)
|
78
|
+
build_target_data_attributes(parse_targets(targets))
|
79
|
+
.map { |dt, n| "data-#{dt}=\"#{n}\"" }
|
80
|
+
.join(" ")
|
81
|
+
.html_safe
|
82
|
+
end
|
83
|
+
alias_method :as_target, :as_targets
|
84
|
+
|
85
|
+
# Return the HTML `data-action` attribute to add these actions
|
86
|
+
def with_actions(*actions)
|
87
|
+
"data-action='#{parse_actions(actions).join(" ")}'".html_safe
|
88
|
+
end
|
89
|
+
alias_method :with_action, :with_actions
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# An implicit Stimulus controller name is built from the implicit controller path
|
94
|
+
def implied_controller_name
|
95
|
+
stimulize_path(implied_controller_path)
|
96
|
+
end
|
97
|
+
|
98
|
+
# When using the DSL if you dont specify, the first controller is implied
|
99
|
+
def implied_controller_path
|
100
|
+
@controllers&.first || raise(StandardError, "No controllers have been specified")
|
101
|
+
end
|
102
|
+
|
103
|
+
# A complete list of Stimulus controllers for this component
|
104
|
+
def controller_list
|
105
|
+
@controllers&.map { |c| stimulize_path(c) }&.join(" ")
|
106
|
+
end
|
107
|
+
|
108
|
+
# Complete list of actions ready to be use in the data-action attribute
|
109
|
+
def action_list
|
110
|
+
return nil unless @actions&.size&.positive?
|
111
|
+
parse_actions(@actions).join(" ")
|
112
|
+
end
|
113
|
+
|
114
|
+
# Complete list of targets ready to be use in the data attributes
|
115
|
+
def target_list
|
116
|
+
return {} unless @targets&.size&.positive?
|
117
|
+
build_target_data_attributes(parse_targets(@targets))
|
118
|
+
end
|
119
|
+
|
120
|
+
def named_classes_list
|
121
|
+
return {} unless @named_classes&.size&.positive?
|
122
|
+
build_named_classes_data_attributes(@named_classes)
|
123
|
+
end
|
124
|
+
|
125
|
+
# stimulus "data-*" attributes map for this component
|
126
|
+
def tag_data_attributes
|
127
|
+
{controller: controller_list, action: action_list}
|
128
|
+
.merge!(target_list)
|
129
|
+
.merge!(named_classes_list)
|
130
|
+
.merge!(data_map_attributes)
|
131
|
+
.compact_blank!
|
132
|
+
end
|
133
|
+
|
134
|
+
# Actions can be specified as a symbol, in which case they imply an action on the primary
|
135
|
+
# controller, or as a string in which case it implies an action that is already fully qualified
|
136
|
+
# stimulus action.
|
137
|
+
# 1 Symbol: :my_action => "my_controller#myAction"
|
138
|
+
# 1 String: "my_controller#myAction"
|
139
|
+
# 2 Symbols: [:click, :my_action] => "click->my_controller#myAction"
|
140
|
+
# 1 String, 1 Symbol: ["path/to/controller", :my_action] => "path--to--controller#myAction"
|
141
|
+
# 1 Symbol, 1 String, 1 Symbol: [:hover, "path/to/controller", :my_action] => "hover->path--to--controller#myAction"
|
142
|
+
|
143
|
+
def parse_action_arg(part1)
|
144
|
+
if part1.is_a?(Symbol)
|
145
|
+
# 1 symbol arg, name of method on this controller
|
146
|
+
"#{implied_controller_name}##{js_name(part1)}"
|
147
|
+
elsif part1.is_a?(String)
|
148
|
+
# 1 string arg, fully qualified action
|
149
|
+
part1
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def parse_multiple_action_args(part1, part2, part3)
|
154
|
+
if part3.nil? && part1.is_a?(Symbol)
|
155
|
+
# 2 symbol args = event + action
|
156
|
+
"#{part1}->#{implied_controller_name}##{js_name(part2)}"
|
157
|
+
elsif part3.nil?
|
158
|
+
# 1 string arg, 1 symbol = controller + action
|
159
|
+
"#{stimulize_path(part1)}##{js_name(part2)}"
|
160
|
+
else
|
161
|
+
# 1 symbol, 1 string, 1 symbol = as above but with event
|
162
|
+
"#{part1}->#{stimulize_path(part2)}##{js_name(part3)}"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Parse actions, targets and attributes that are passed in as symbols or strings
|
167
|
+
|
168
|
+
def parse_targets(targets)
|
169
|
+
targets.map { |n| parse_target(n) }
|
170
|
+
end
|
171
|
+
|
172
|
+
def parse_target(raw_target)
|
173
|
+
return raw_target if raw_target.is_a?(String)
|
174
|
+
return raw_target if raw_target.is_a?(Hash)
|
175
|
+
target(raw_target)
|
176
|
+
end
|
177
|
+
|
178
|
+
def build_target_data_attributes(targets)
|
179
|
+
targets.map { |t| ["#{t[:controller]}-target".to_sym, t[:name]] }.to_h
|
180
|
+
end
|
181
|
+
|
182
|
+
def parse_actions(actions)
|
183
|
+
actions.map! { |a| a.is_a?(String) ? a : action(*a) }
|
184
|
+
end
|
185
|
+
|
186
|
+
def parse_attributes(attrs, controller = nil)
|
187
|
+
attrs.transform_keys { |k| "#{controller || implied_controller_name}-#{k}" }
|
188
|
+
end
|
189
|
+
|
190
|
+
def data_map_attributes
|
191
|
+
return {} unless @data_maps
|
192
|
+
@data_maps.each_with_object({}) do |m, obj|
|
193
|
+
if m.is_a?(Hash)
|
194
|
+
obj.merge!(parse_attributes(m))
|
195
|
+
elsif m.is_a?(Array)
|
196
|
+
controller_path = m.first
|
197
|
+
data = m.last
|
198
|
+
obj.merge!(parse_attributes(data, stimulize_path(controller_path)))
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def parse_named_classes_hash(named_classes)
|
204
|
+
named_classes.map do |name, classes|
|
205
|
+
logical_name = name.to_s.dasherize
|
206
|
+
classes_str = convert_classes_list_to_string(classes)
|
207
|
+
if classes.is_a?(Hash)
|
208
|
+
{controller: stimulize_path(classes[:controller_path]), name: logical_name, classes: classes_str}
|
209
|
+
else
|
210
|
+
{controller: implied_controller_name, name: logical_name, classes: classes_str}
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def build_named_classes_data_attributes(named_classes)
|
216
|
+
parse_named_classes_hash(named_classes)
|
217
|
+
.map { |c| ["#{c[:controller]}-#{c[:name]}-class", c[:classes]] }
|
218
|
+
.to_h
|
219
|
+
end
|
220
|
+
|
221
|
+
def convert_classes_list_to_string(classes)
|
222
|
+
return "" if classes.nil?
|
223
|
+
return classes if classes.is_a?(String)
|
224
|
+
return classes.join(" ") if classes.is_a?(Array)
|
225
|
+
classes[:classes].is_a?(Array) ? classes[:classes].join(" ") : classes[:classes]
|
226
|
+
end
|
227
|
+
|
228
|
+
# Convert a file path to a stimulus controller name
|
229
|
+
def stimulize_path(path)
|
230
|
+
path.split("/").map { |p| p.to_s.dasherize }.join("--")
|
231
|
+
end
|
232
|
+
|
233
|
+
# Convert a Ruby 'snake case' string to a JavaScript camel case strings
|
234
|
+
def js_name(name)
|
235
|
+
name.to_s.camelize(:lower)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if Gem.loaded_specs.has_key? "phlex"
|
4
|
+
require "phlex"
|
5
|
+
|
6
|
+
module Vident
|
7
|
+
module RootComponent
|
8
|
+
class UsingPhlexHTML < Phlex::HTML
|
9
|
+
include Base
|
10
|
+
|
11
|
+
VALID_TAGS = Set[*(Phlex::HTML::VOID_ELEMENTS.keys + Phlex::HTML::STANDARD_ELEMENTS.keys)].freeze
|
12
|
+
|
13
|
+
# Create a tag for a target with a block containing content
|
14
|
+
def target_tag(tag_name, targets, **options, &block)
|
15
|
+
parsed = parse_targets(Array.wrap(targets))
|
16
|
+
options[:data] ||= {}
|
17
|
+
options[:data].merge!(build_target_data_attributes(parsed))
|
18
|
+
generate_tag(tag_name, **options, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Build a tag with the attributes determined by this components properties and stimulus
|
22
|
+
# data attributes.
|
23
|
+
def template(&block)
|
24
|
+
# Generate tag options and render
|
25
|
+
tag_type = @element_tag.presence&.to_sym || :div
|
26
|
+
raise ArgumentError, "Unsupported HTML tag name #{tag_type}" unless VALID_TAGS.include?(tag_type)
|
27
|
+
options = @html_options&.dup || {}
|
28
|
+
data_attrs = tag_data_attributes
|
29
|
+
data_attrs = options[:data].present? ? data_attrs.merge(options[:data]) : data_attrs
|
30
|
+
options = options.merge(id: @id) if @id
|
31
|
+
options.except!(:data)
|
32
|
+
options.merge!(data_attrs.transform_keys { |k| "data-#{k}" })
|
33
|
+
generate_tag(tag_type, **options, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def generate_tag(tag_type, **options, &block)
|
39
|
+
send((tag_type == :template) ? :template_tag : tag_type, **options, &block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if Gem.loaded_specs.has_key? "view_component"
|
4
|
+
require "view_component"
|
5
|
+
|
6
|
+
module Vident
|
7
|
+
module RootComponent
|
8
|
+
class UsingViewComponent < ::ViewComponent::Base
|
9
|
+
include Base
|
10
|
+
|
11
|
+
SELF_CLOSING_TAGS = Set[:area, :base, :br, :col, :embed, :hr, :img, :input, :link, :meta, :param, :source, :track, :wbr].freeze
|
12
|
+
|
13
|
+
def target_tag(tag_name, targets, **options, &block)
|
14
|
+
parsed = parse_targets(Array.wrap(targets))
|
15
|
+
options[:data] ||= {}
|
16
|
+
options[:data].merge!(build_target_data_attributes(parsed))
|
17
|
+
content = view_context.capture(&block) if block
|
18
|
+
view_context.content_tag(tag_name, content, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
# Capture inner block content
|
23
|
+
# It's important that we capture the block content before generating the tag options.
|
24
|
+
# This is because the content could contain calls to `s.data_map`.
|
25
|
+
# These calls add key-value pairs to the internal data_map, which can then be translated into
|
26
|
+
# the correct `data-*` attrs by the tag options.
|
27
|
+
generated = content
|
28
|
+
|
29
|
+
# Generate outer tag options and render
|
30
|
+
tag_type = @element_tag.presence || :div
|
31
|
+
options = @html_options&.dup || {}
|
32
|
+
data_attrs = tag_data_attributes
|
33
|
+
options[:data] = options[:data].present? ? data_attrs.merge(options[:data]) : data_attrs
|
34
|
+
options = options.merge(id: @id) if @id
|
35
|
+
if SELF_CLOSING_TAGS.include?(tag_type)
|
36
|
+
view_context.tag(tag_type, options)
|
37
|
+
else
|
38
|
+
view_context.content_tag(tag_type, generated, options)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Vident
|
4
|
+
class StableId
|
5
|
+
class << self
|
6
|
+
def set_current_sequence_generator
|
7
|
+
::Thread.current[:vident_number_sequence_generator] = id_sequence_generator
|
8
|
+
end
|
9
|
+
|
10
|
+
def next_id_in_sequence
|
11
|
+
generator = ::Thread.current[:vident_number_sequence_generator]
|
12
|
+
return "?" unless generator
|
13
|
+
generator.next.join("-")
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def id_sequence_generator
|
19
|
+
number_generator = Random.new(296_865_628_524)
|
20
|
+
Enumerator.produce { number_generator.rand(10_000_000) }.with_index
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if Gem.loaded_specs.has_key? "dry-struct"
|
4
|
+
require_relative "./attributes/typed"
|
5
|
+
|
6
|
+
module Vident
|
7
|
+
module TypedComponent
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
include Vident::Base
|
12
|
+
include Vident::Attributes::Typed
|
13
|
+
|
14
|
+
attribute :id, String, delegates: false
|
15
|
+
attribute :html_options, Hash, delegates: false
|
16
|
+
attribute :element_tag, Symbol, delegates: false
|
17
|
+
|
18
|
+
# StimulusJS support
|
19
|
+
attribute :controllers, Array, default: [], delegates: false
|
20
|
+
attribute :actions, Array, default: [], delegates: false
|
21
|
+
attribute :targets, Array, default: [], delegates: false
|
22
|
+
attribute :data_maps, Array, default: [], delegates: false
|
23
|
+
|
24
|
+
# TODO normalise the syntax of defining actions, controllers, etc
|
25
|
+
attribute :named_classes, Hash, delegates: false
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(attrs = {})
|
29
|
+
before_initialise(attrs)
|
30
|
+
prepare_attributes(attrs)
|
31
|
+
# The attributes need to also be set as ivars
|
32
|
+
attributes.each do |attr_name, attr_value|
|
33
|
+
instance_variable_set(self.class.attribute_ivar_names[attr_name], attr_value)
|
34
|
+
end
|
35
|
+
after_initialise
|
36
|
+
super()
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
module Vident
|
42
|
+
module TypedComponent
|
43
|
+
def self.included(base)
|
44
|
+
raise "Vident::TypedComponent requires dry-struct to be installed"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/vident.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "vident/version"
|
4
|
+
require_relative "vident/railtie"
|
5
|
+
|
6
|
+
module Vident
|
7
|
+
class << self
|
8
|
+
def configuration
|
9
|
+
@configuration ||= Configuration.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure
|
13
|
+
yield(configuration) if block_given?
|
14
|
+
configuration
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Configuration
|
19
|
+
attr_accessor :include_i18n_helpers
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@include_i18n_helpers = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require_relative "vident/stable_id"
|
28
|
+
require_relative "vident/root_component/base"
|
29
|
+
require_relative "vident/root_component/using_phlex_html"
|
30
|
+
require_relative "vident/root_component/using_view_component"
|
31
|
+
require_relative "vident/base"
|
32
|
+
require_relative "vident/component"
|
33
|
+
require_relative "vident/typed_component"
|
data/sig/vident.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vident
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Ierodiaconou
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-12-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.0'
|
27
|
+
description: Vident makes using Stimulus with your `ViewComponent` or `Phlex` view
|
28
|
+
components as easy as writing Ruby. It also provides a base class for your components
|
29
|
+
to inherit from.
|
30
|
+
email:
|
31
|
+
- stevegeek@gmail.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- ".standard.yml"
|
37
|
+
- CODE_OF_CONDUCT.md
|
38
|
+
- Gemfile
|
39
|
+
- LICENSE.txt
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- examples/ex1.gif
|
43
|
+
- lib/tasks/vident.rake
|
44
|
+
- lib/vident.rb
|
45
|
+
- lib/vident/attributes/not_typed.rb
|
46
|
+
- lib/vident/attributes/typed.rb
|
47
|
+
- lib/vident/attributes/typed_niling_struct.rb
|
48
|
+
- lib/vident/attributes/types.rb
|
49
|
+
- lib/vident/base.rb
|
50
|
+
- lib/vident/component.rb
|
51
|
+
- lib/vident/railtie.rb
|
52
|
+
- lib/vident/root_component/base.rb
|
53
|
+
- lib/vident/root_component/using_phlex_html.rb
|
54
|
+
- lib/vident/root_component/using_view_component.rb
|
55
|
+
- lib/vident/stable_id.rb
|
56
|
+
- lib/vident/typed_component.rb
|
57
|
+
- lib/vident/version.rb
|
58
|
+
- sig/vident.rbs
|
59
|
+
homepage: https://github.com/stevegeek/vident
|
60
|
+
licenses:
|
61
|
+
- MIT
|
62
|
+
metadata:
|
63
|
+
homepage_uri: https://github.com/stevegeek/vident
|
64
|
+
source_code_uri: https://github.com/stevegeek/vident
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 3.0.0
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubygems_version: 3.3.7
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: Vident is a view component base class for your design system implementation,
|
84
|
+
which provides helpers for working with Stimulus. For ViewComponent and Phlex.
|
85
|
+
test_files: []
|