vident-typed-view_component 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +372 -0
- data/Rakefile +8 -0
- data/config/routes.rb +2 -0
- data/lib/tasks/vident/typed/view_component_tasks.rake +4 -0
- data/lib/vident/typed/view_component/base.rb +15 -0
- data/lib/vident/typed/view_component/engine.rb +19 -0
- data/lib/vident/typed/view_component/version.rb +7 -0
- data/lib/vident/typed/view_component.rb +10 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8b452999e699b9280843995877688131d0f5340ce7677a2daa255cc205528cde
|
4
|
+
data.tar.gz: d443df28c20a174dfbd8e49dc1e2bad9494ba5036628bfa9e649baf9f0fe1a24
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 02f8b2eb878cbdef3c01a55ef39e2b0c67d633d9f5bb0ac8fd80967b1561a6ee75ecb547f79ce9ec11c4d2795da93fe3c4fff08de3a5583edd08b5fe98a6c03c
|
7
|
+
data.tar.gz: 5806003e62d04293b81a76f3b790bda373dc8dc0bd4fd9669cfb409d2bf6835587703600fe416173ca17c782d1b75c96eabcbdef81add5803cc35aa80718734c
|
data/README.md
ADDED
@@ -0,0 +1,372 @@
|
|
1
|
+
# Vident::Typed::ViewComponent
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
|
5
|
+
# Examples
|
6
|
+
|
7
|
+
Before we dive into a specific example note that there are some components implemented in `test/dummy/app/components`.
|
8
|
+
|
9
|
+
Try them out by starting Rails:
|
10
|
+
|
11
|
+
```bash
|
12
|
+
cd test/dummy
|
13
|
+
bundle install
|
14
|
+
rails assets:precompile
|
15
|
+
rails s
|
16
|
+
```
|
17
|
+
|
18
|
+
and visiting http://localhost:3000
|
19
|
+
|
20
|
+
|
21
|
+
## A Vident component example (without Stimulus)
|
22
|
+
|
23
|
+
First is an example component that uses `Vident::Typed::ViewComponent::Base` but no Stimulus features.
|
24
|
+
|
25
|
+
It is an avatar component that can either be displayed as an image or as initials.
|
26
|
+
|
27
|
+
It supports numerous sizes and shapes and can optionally have a border. It also generates a cache key for use in fragment caching or etag generation.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class AvatarComponent < ::Vident::Typed::ViewComponent::Base
|
31
|
+
include ::Vident::Tailwind
|
32
|
+
include ::Vident::ViewComponent::Caching
|
33
|
+
|
34
|
+
no_stimulus_controller
|
35
|
+
with_cache_key :attributes
|
36
|
+
|
37
|
+
attribute :url, String, allow_nil: true, allow_blank: false
|
38
|
+
attribute :initials, String, allow_blank: false
|
39
|
+
|
40
|
+
attribute :shape, Symbol, in: %i[circle square], default: :circle
|
41
|
+
|
42
|
+
attribute :border, :boolean, default: false
|
43
|
+
|
44
|
+
attribute :size, Symbol, in: %i[tiny small normal medium large x_large xx_large], default: :normal
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def default_html_options
|
49
|
+
if image_avatar?
|
50
|
+
{ class: "inline-block object-contain", src: url, alt: t(".image") }
|
51
|
+
else
|
52
|
+
{ class: "inline-flex items-center justify-center bg-gray-500" }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def element_classes
|
57
|
+
[size_classes, shape_class, border? ? "border" : ""]
|
58
|
+
end
|
59
|
+
|
60
|
+
alias_method :image_avatar?, :url?
|
61
|
+
|
62
|
+
def shape_class
|
63
|
+
(shape == :circle) ? "rounded-full" : "rounded-md"
|
64
|
+
end
|
65
|
+
|
66
|
+
def size_classes
|
67
|
+
case size
|
68
|
+
when :tiny
|
69
|
+
"w-6 h-6"
|
70
|
+
when :small
|
71
|
+
"w-8 h-8"
|
72
|
+
when :medium
|
73
|
+
"w-12 h-12"
|
74
|
+
when :large
|
75
|
+
"w-14 h-14"
|
76
|
+
when :x_large
|
77
|
+
"sm:w-24 sm:h-24 w-16 h-16"
|
78
|
+
when :xx_large
|
79
|
+
"sm:w-32 sm:h-32 w-24 h-24"
|
80
|
+
else
|
81
|
+
"w-10 h-10"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def text_size_class
|
86
|
+
case size
|
87
|
+
when :tiny
|
88
|
+
"text-xs"
|
89
|
+
when :small
|
90
|
+
"text-xs"
|
91
|
+
when :medium
|
92
|
+
"text-lg"
|
93
|
+
when :large
|
94
|
+
"sm:text-xl text-lg"
|
95
|
+
when :extra_large
|
96
|
+
"sm:text-2xl text-xl"
|
97
|
+
else
|
98
|
+
"text-medium"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
```erb
|
105
|
+
<%= render root(
|
106
|
+
element_tag: image_avatar? ? :img : :div,
|
107
|
+
html_options: default_html_options
|
108
|
+
) do %>
|
109
|
+
<% unless image_avatar? %>
|
110
|
+
<span class="<%= text_size_class %> font-medium leading-none text-white"><%= initials %></span>
|
111
|
+
<% end %>
|
112
|
+
<% end %>
|
113
|
+
|
114
|
+
```
|
115
|
+
|
116
|
+
Example usages:
|
117
|
+
|
118
|
+
```erb
|
119
|
+
<!-- These will render -->
|
120
|
+
<%= render AvatarComponent.new(url: "https://someurl.com/avatar.jpg", initials: "AB" size: :large) %>
|
121
|
+
<%= render AvatarComponent.new(url: "https://someurl.com/avatar.jpg", html_options: {alt: "My alt text", class: "object-scale-down"}) %>
|
122
|
+
<%= render AvatarComponent.new(initials: "SG", size: :small) %>
|
123
|
+
<%= render AvatarComponent.new(initials: "SG", size: :large, html_options: {class: "border-2 border-red-600"}) %>
|
124
|
+
|
125
|
+
<!-- These will raise an error -->
|
126
|
+
<!-- missing initals -->
|
127
|
+
<%= render AvatarComponent.new(url: "https://someurl.com/avatar.jpg", size: :large) %>
|
128
|
+
<!-- initials blank -->
|
129
|
+
<%= render AvatarComponent.new(initials: "", size: :large) %>
|
130
|
+
<!-- invalid size -->
|
131
|
+
<%= render AvatarComponent.new(initials: "SG", size: :foo_bar) %>
|
132
|
+
```
|
133
|
+
|
134
|
+
|
135
|
+
The following is rendered when used `render AvatarComponent.new(initials: "SG", size: :small, border: true)`:
|
136
|
+
|
137
|
+
```html
|
138
|
+
<div class="avatar-component w-8 h-8 rounded-full border inline-flex items-center justify-center bg-gray-500" id="avatar-component-9790427-12">
|
139
|
+
<span class="text-xs font-medium leading-none text-white">SG</span>
|
140
|
+
</div>
|
141
|
+
```
|
142
|
+
|
143
|
+
The following is rendered when used `render AvatarComponent.new(url: "https://i.pravatar.cc/300", initials: "AB", html_options: {alt: "My alt text", class: "block"})`:
|
144
|
+
|
145
|
+
```html
|
146
|
+
<img src="https://i.pravatar.cc/300" alt="My alt text" class="avatar-component w-10 h-10 rounded-full object-contain block" id="avatar-component-7083941-11">
|
147
|
+
```
|
148
|
+
|
149
|
+
----
|
150
|
+
|
151
|
+
![Example](examples/avatar.png)
|
152
|
+
|
153
|
+
|
154
|
+
## Another ViewComponent + Vident example with Stimulus
|
155
|
+
|
156
|
+
Consider the following ERB that might be part of an application's views. The app uses `ViewComponent`, `Stimulus` and `Vident`.
|
157
|
+
|
158
|
+
The Greeter is a component that displays a text input and a button. When the button is clicked, the text input's value is
|
159
|
+
used to greet the user. At the same time the button changes to be a 'reset' button, which resets the greeting when clicked again.
|
160
|
+
|
161
|
+
![ex1.gif](examples%2Fex1.gif)
|
162
|
+
|
163
|
+
```erb
|
164
|
+
<%# app/views/home/index.html.erb %>
|
165
|
+
|
166
|
+
<!-- ... -->
|
167
|
+
|
168
|
+
<!-- render the Greeter ViewComponent (that uses Vident) -->
|
169
|
+
<%= render ::GreeterComponent.new(cta: "Hey!", html_options: {class: "my-4"}) do |greeter| %>
|
170
|
+
<%# this component has a slot called `trigger` that renders a `ButtonComponent` (which also uses Vident) %>
|
171
|
+
<% greeter.trigger(
|
172
|
+
|
173
|
+
# The button component has attributes that are typed
|
174
|
+
before_clicked: "Greet",
|
175
|
+
after_clicked: "Greeted! Reset?",
|
176
|
+
|
177
|
+
# A stimulus action is added to the button that triggers the `greet` action on the greeter stimulus controller.
|
178
|
+
# This action will be added to any defined on the button component itself
|
179
|
+
actions: [
|
180
|
+
greeter.action(:click, :greet),
|
181
|
+
],
|
182
|
+
|
183
|
+
# We can also override the default button classes of our component, or set other HTML attributes
|
184
|
+
html_options: {
|
185
|
+
class: "bg-red-500 hover:bg-red-700"
|
186
|
+
}
|
187
|
+
) %>
|
188
|
+
<% end %>
|
189
|
+
|
190
|
+
<!-- ... -->
|
191
|
+
```
|
192
|
+
|
193
|
+
The output HTML of the above, using Vident, is:
|
194
|
+
|
195
|
+
```html
|
196
|
+
<div class="greeter-component py-2 my-4"
|
197
|
+
data-controller="greeter-component"
|
198
|
+
data-greeter-component-pre-click-class="text-md text-gray-500"
|
199
|
+
data-greeter-component-post-click-class="text-xl text-blue-700"
|
200
|
+
id="greeter-component-1599855-6">
|
201
|
+
<input type="text"
|
202
|
+
data-greeter-component-target="name"
|
203
|
+
class="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline">
|
204
|
+
<button class="button-component ml-4 whitespace-no-wrap bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded bg-red-500 hover:bg-red-700"
|
205
|
+
data-controller="button-component"
|
206
|
+
data-action="click->greeter-component#greet button-component#changeMessage"
|
207
|
+
data-button-component-after-clicked-message="Greeted! Reset?"
|
208
|
+
data-button-component-before-clicked-message="Greet"
|
209
|
+
id="button-component-7799479-7">Hey!</button>
|
210
|
+
<!-- you can also use the `target_tag` helper to render targets -->
|
211
|
+
<span class="ml-4 text-md text-gray-500"
|
212
|
+
data-greeter-component-target="output">
|
213
|
+
...
|
214
|
+
</span>
|
215
|
+
</div>
|
216
|
+
```
|
217
|
+
|
218
|
+
Let's look at the components in more detail.
|
219
|
+
|
220
|
+
The main component is the `GreeterComponent`:
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
# app/components/greeter_component.rb
|
224
|
+
|
225
|
+
class GreeterComponent < ::Vident::ViewComponent::Base
|
226
|
+
renders_one :trigger, ButtonComponent
|
227
|
+
end
|
228
|
+
```
|
229
|
+
|
230
|
+
```erb
|
231
|
+
<%# app/components/greeter_component.html.erb %>
|
232
|
+
|
233
|
+
<%# Rendering the `root` element creates a tag which has stimulus `data-*`s, a unique id & other attributes set. %>
|
234
|
+
<%# The stimulus controller name (identifier) is derived from the component name, and then used to generate the relavent data attribute names. %>
|
235
|
+
|
236
|
+
<%= render root named_classes: {
|
237
|
+
pre_click: "text-md text-gray-500", # named classes are exposed to Stimulus as `data-<controller>-<name>-class` attributes
|
238
|
+
post_click: "text-xl text-blue-700",
|
239
|
+
html_options: {class: "py-2"}
|
240
|
+
} do |greeter| %>
|
241
|
+
|
242
|
+
<%# `greeter` is the root element and exposes methods to generate stimulus targets and actions %>
|
243
|
+
<input type="text"
|
244
|
+
<%= greeter.as_target(:name) %>
|
245
|
+
class="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline">
|
246
|
+
|
247
|
+
<%# Render the slot %>
|
248
|
+
<%= trigger %>
|
249
|
+
|
250
|
+
<%# you can also use the `target_tag` helper to render targets %>
|
251
|
+
<%= greeter.target_tag(
|
252
|
+
:span,
|
253
|
+
:output,
|
254
|
+
# Stimulus named classes can be referenced to set class attributes at render time
|
255
|
+
class: "ml-4 #{greeter.named_classes(:pre_click)}"
|
256
|
+
) do %>
|
257
|
+
...
|
258
|
+
<% end %>
|
259
|
+
<% end %>
|
260
|
+
|
261
|
+
```
|
262
|
+
|
263
|
+
```js
|
264
|
+
// app/components/greeter_component_controller.js
|
265
|
+
|
266
|
+
import { Controller } from "@hotwired/stimulus"
|
267
|
+
|
268
|
+
// This is a Stimulus controller that is automatically registered for the `GreeterComponent`
|
269
|
+
// and is 'sidecar' to the component. You can see that while in the ERB we use Ruby naming conventions
|
270
|
+
// with snake_case Symbols, here they are converted to camelCase names. We can also just use camelCase
|
271
|
+
// in the ERB if we want.
|
272
|
+
export default class extends Controller {
|
273
|
+
static targets = [ "name", "output" ]
|
274
|
+
static classes = [ "preClick", "postClick" ]
|
275
|
+
|
276
|
+
greet() {
|
277
|
+
this.clicked = !this.clicked;
|
278
|
+
this.outputTarget.classList.toggle(this.preClickClasses, !this.clicked);
|
279
|
+
this.outputTarget.classList.toggle(this.postClickClasses, this.clicked);
|
280
|
+
|
281
|
+
if (this.clicked)
|
282
|
+
this.outputTarget.textContent = `Hello, ${this.nameTarget.value}!`
|
283
|
+
else
|
284
|
+
this.clear();
|
285
|
+
}
|
286
|
+
|
287
|
+
clear() {
|
288
|
+
this.outputTarget.textContent = '...';
|
289
|
+
this.nameTarget.value = '';
|
290
|
+
}
|
291
|
+
}
|
292
|
+
```
|
293
|
+
|
294
|
+
The slot renders a `ButtonComponent` component:
|
295
|
+
|
296
|
+
```ruby
|
297
|
+
# app/components/button_component.rb
|
298
|
+
|
299
|
+
class ButtonComponent < ::Vident::Typed::ViewComponent::Base
|
300
|
+
# The attributes can specify an expected type, a default value and if nil is allowed.
|
301
|
+
attribute :after_clicked, String, default: "Greeted!"
|
302
|
+
attribute :before_clicked, String, allow_nil: false
|
303
|
+
|
304
|
+
# This example is a templateless ViewComponent.
|
305
|
+
def call
|
306
|
+
# The button is rendered as a <button> tag with an click action on its own controller.
|
307
|
+
render root(
|
308
|
+
element_tag: :button,
|
309
|
+
|
310
|
+
# We can define actions as arrays of Symbols, or pass manually manually crafted strings.
|
311
|
+
# Here we specify the action name only, implying an action on the current components controller
|
312
|
+
# and the default event type of `click`.
|
313
|
+
actions: [:change_message],
|
314
|
+
# Alternatively: [:click, :change_message] or ["click", "changeMessage"] or even "click->button-component#changeMessage"
|
315
|
+
|
316
|
+
# A couple of data values are also set which will be available to the controller
|
317
|
+
data_maps: [{after_clicked_message: after_clicked, before_clicked_message: before_clicked}],
|
318
|
+
|
319
|
+
# The <button> tag has a default styling set directly on it. Note that
|
320
|
+
# if not using utility classes, you can style the component using its
|
321
|
+
# canonical class name (which is equal to the component's stimulus identifier),
|
322
|
+
# in this case `button-component`.
|
323
|
+
html_options: {class: "ml-4 whitespace-no-wrap bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"}
|
324
|
+
) do
|
325
|
+
@before_clicked
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
```
|
330
|
+
|
331
|
+
```js
|
332
|
+
// app/components/button_component_controller.js
|
333
|
+
|
334
|
+
import { Controller } from "@hotwired/stimulus"
|
335
|
+
|
336
|
+
export default class extends Controller {
|
337
|
+
// The action is in camelCase.
|
338
|
+
changeMessage() {
|
339
|
+
this.clicked = !this.clicked;
|
340
|
+
// The data attributes have their naming convention converted to camelCase.
|
341
|
+
this.element.textContent = this.clicked ? this.data.get("afterClickedMessage") : this.data.get("beforeClickedMessage");
|
342
|
+
}
|
343
|
+
}
|
344
|
+
|
345
|
+
```
|
346
|
+
|
347
|
+
|
348
|
+
## Usage
|
349
|
+
How to use my plugin.
|
350
|
+
|
351
|
+
## Installation
|
352
|
+
Add this line to your application's Gemfile:
|
353
|
+
|
354
|
+
```ruby
|
355
|
+
gem "vident-typed-view_component"
|
356
|
+
```
|
357
|
+
|
358
|
+
And then execute:
|
359
|
+
```bash
|
360
|
+
$ bundle
|
361
|
+
```
|
362
|
+
|
363
|
+
Or install it yourself as:
|
364
|
+
```bash
|
365
|
+
$ gem install vident-typed-view_component
|
366
|
+
```
|
367
|
+
|
368
|
+
## Contributing
|
369
|
+
Contribution directions go here.
|
370
|
+
|
371
|
+
## License
|
372
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/config/routes.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Vident
|
2
|
+
module Typed
|
3
|
+
module ViewComponent
|
4
|
+
class Base < ::ViewComponent::Base
|
5
|
+
include ::Vident::Typed::Component
|
6
|
+
|
7
|
+
# Helper to create the main element
|
8
|
+
def parent_element(**options)
|
9
|
+
@parent_element ||= ::Vident::ViewComponent::RootComponent.new(**parent_element_attributes(options))
|
10
|
+
end
|
11
|
+
alias_method :root, :parent_element
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Vident
|
2
|
+
module Typed
|
3
|
+
module ViewComponent
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
lib_path = File.expand_path("../../../../../lib/", __FILE__)
|
6
|
+
config.autoload_paths << lib_path
|
7
|
+
config.eager_load_paths << lib_path
|
8
|
+
|
9
|
+
config.before_initialize do
|
10
|
+
Rails.autoloaders.each do |autoloader|
|
11
|
+
autoloader.inflector.inflect(
|
12
|
+
"version" => "VERSION"
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vident-typed-view_component
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Ierodiaconou
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '8'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '7'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '8'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: vident-typed
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.1.0
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 0.1.0
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '1'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: vident-view_component
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 0.1.0
|
60
|
+
- - "<"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.1.0
|
70
|
+
- - "<"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '1'
|
73
|
+
description: Vident with ViewComponent & typed attributes
|
74
|
+
email:
|
75
|
+
- stevegeek@gmail.com
|
76
|
+
executables: []
|
77
|
+
extensions: []
|
78
|
+
extra_rdoc_files: []
|
79
|
+
files:
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- config/routes.rb
|
83
|
+
- lib/tasks/vident/typed/view_component_tasks.rake
|
84
|
+
- lib/vident/typed/view_component.rb
|
85
|
+
- lib/vident/typed/view_component/base.rb
|
86
|
+
- lib/vident/typed/view_component/engine.rb
|
87
|
+
- lib/vident/typed/view_component/version.rb
|
88
|
+
homepage: https://github.com/stevegeek/vident-typed-view_component
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata:
|
92
|
+
homepage_uri: https://github.com/stevegeek/vident-typed-view_component
|
93
|
+
source_code_uri: https://github.com/stevegeek/vident-typed-view_component
|
94
|
+
changelog_uri: https://github.com/stevegeek/vident-typed-view_component/blob/main/CHANGELOG.md
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubygems_version: 3.4.6
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Vident with ViewComponent & typed attributes
|
114
|
+
test_files: []
|