vident-phlex 0.5.1 → 0.13.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '087edd0f039c8c672607ffda1774e42757c34606d78ddf98eb24e0ce62f5bb57'
4
- data.tar.gz: 469963787ee34b5c59b19e8b35c74d17de2db6dbd92548e29787ef672a0320a8
3
+ metadata.gz: 4dc779e8e9af309227688c4b2d575c316105d1aa20f1b42fdf2eb2ee475fda53
4
+ data.tar.gz: 1efba9e7cb073dd4524e4af42e18a59017fd9b798287ce23d8e7f6a0c17906fb
5
5
  SHA512:
6
- metadata.gz: 22a9c3b5d6cb1e33a8d47c48b30c2a9f72ac6cb5753e325ca2a9048d535b329a08d308dd71727aab5cf751a842673502070bada67e19f2db4dd0e73d1d7c60b1
7
- data.tar.gz: 88c39254ace9d5045f6ec9f57b873c7b1f8a5fa7cd53b934d68febf3dbb91e00e99a31e6e775fb673e7a14a500b73ca5714c0a5c290997872cb1f6d6de543b33
6
+ metadata.gz: c168c00d8b8e82e74bfabdae026641059a11bc7e92b3726388cca6bcf0356f24a5426e1f095e5d71941e89f1a794a81732e91aa321bf0298593a73a9bbd0dedf
7
+ data.tar.gz: d8adcea13c91ba2d185515df917ce10a2833a1fb1ab32237e073eb01aabc52732ad496ae31015637ff0fb2a18fc6bdf1a7fb4d4330572fe906b1ca4d7bb4fd33
data/CHANGELOG.md ADDED
@@ -0,0 +1,221 @@
1
+
2
+ # Change Log
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/).
7
+
8
+
9
+ ## [0.13.0] - 2024-04-07
10
+
11
+ ### Breaking
12
+
13
+ - `data_maps` has been renamed to `values` and support has been added for the Stimulus 2+ Values API.
14
+ - `root`/`parent_element` no longer takes options, to define attributes for it, you can use `root_element_attributes` or the view component helper `root_component_attributes`. This change means
15
+ that root elements can be instantiated outside of `render` which is useful if you refer to the instance in the components body block
16
+
17
+ ### Added
18
+
19
+ - New monorepo structure for the Vident project, retaining the separate gems however.
20
+ - All gems now have the same version and are released together.
21
+
22
+ ### Changed
23
+
24
+ ### Fixed
25
+
26
+ ## [0.12.1] - 2024-06-12
27
+
28
+ ### Fixed
29
+
30
+ - parsing of targets where the controller is also specified
31
+
32
+ ## [0.12.0] - 2024-02-25
33
+
34
+ ### Added
35
+
36
+ - `outlet` DSL methods updated so that the selector is scoped to the component's root element by default. This
37
+ is probably the most common use case, and it's now the default.
38
+ - `with_outlets` DSL method added to generate the data-* attributes for the outlets and return as a fragment
39
+ of HTML
40
+
41
+
42
+ ## [0.11.0] - 2024-02-21
43
+
44
+ ### Added
45
+
46
+ - `outlet_host` DSL method to support components hooking themselves into a host component's outlets
47
+
48
+
49
+
50
+ ## [0.10.1] - 2024-02-21
51
+
52
+ ### Added
53
+
54
+ - `outlets` option now accepts either a string stimulus controller identifier, a component instance, or a tuple of
55
+ identifier and CSS selector for the outlet.
56
+
57
+
58
+ ## [0.10.0] - 2024-02-21
59
+
60
+ ### Added
61
+
62
+ - `outlets` option for components, used to specify Stimulus outlets
63
+
64
+ ## [0.9.0] - 2023-08-11
65
+
66
+ ### Added
67
+
68
+ - `#cache_key` support is now part of the core gem, and can be added to components using `Vident::Caching` module
69
+
70
+ ## [0.8.0] - 2023-03-31
71
+
72
+ ### Added
73
+
74
+ - new gems for Vident related functionality, eg `vident-typed` and `vident-tailwind`
75
+ - `vident` is now the core gem which can be used with any component system. Gems for Phlex and ViewComponent are available, `vident-phlex` and `vident-view_component`, and `vident-typed-phlex` and `vident-typed-view_component` are available with typed attributes support.
76
+
77
+ ### Changed
78
+
79
+ - removed functionality for `better_html`, `dry-types`, `view_component`, and `phlex` from the core gem
80
+ - gem is now a Rails Engine and supports eager and autoloading
81
+
82
+ ### Fixed
83
+
84
+ - Fix untyped attributes inheritance
85
+
86
+ ## [0.7.0] - 2023-03-08
87
+
88
+ ### Added
89
+
90
+ - new `Vident::Tailwind` module which uses [tailwind_merge](https://github.com/gjtorikian/tailwind_merge) to merge TailwindCSS classes
91
+
92
+ ### Changed
93
+
94
+ - Removed a dependency on intenal constants from `phlex`
95
+
96
+ ## [0.6.3] - 2023-03-03
97
+
98
+ ### Fixed
99
+
100
+ - Fix for changes to HTML tag collection in Phlex
101
+
102
+
103
+ ## [0.6.2] - 2023-02-23
104
+
105
+ ### Fixed
106
+
107
+ - Element tag options are not set when no ID is provided
108
+
109
+
110
+ ## [0.6.1] - 2023-02-20
111
+
112
+ ### Fixed
113
+
114
+ - `better_html` support fix for aliased dsl methods
115
+
116
+
117
+ ## [0.6.0] - 2023-02-20
118
+
119
+ ### Added
120
+
121
+ - Experimental support for `better_html` in the root components (the stimulus attributes are generated with `html_attributes`)
122
+
123
+
124
+
125
+ ## [0.5.1] - 2023-02-17
126
+
127
+ ### Added
128
+
129
+ - N/A
130
+
131
+ ### Changed
132
+
133
+ - N/A
134
+
135
+ ### Fixed
136
+
137
+ - Typed attributes was not always using custom coercion methods if they were defined
138
+
139
+ ### Removed
140
+
141
+ - N/A
142
+
143
+ ### Deprecated
144
+
145
+ - N/A
146
+
147
+ ### Security
148
+
149
+ - N/A
150
+
151
+ ---
152
+
153
+ # Package Changelogs
154
+
155
+ ## vident-better_html
156
+
157
+ ### [0.6.0] - 2023-02-20
158
+
159
+ #### Added
160
+
161
+ - Experimental support for `better_html` in the root components (the stimulus attributes are generated with `html_attributes`)
162
+
163
+ ### [0.6.1] - 2023-02-20
164
+
165
+ #### Fixed
166
+
167
+ - `better_html` support fix for aliased dsl methods
168
+
169
+ ## vident-tailwind
170
+
171
+ ### [0.1.1] - 2023-04-02
172
+
173
+ #### Fixed
174
+
175
+ - `tailwind_merge` should only take a non-nil value, and since it uses the class string as a cache key, it should not be blank.
176
+
177
+ ## vident-typed-view_component
178
+
179
+ ### [0.3.0] - 2023-08-12
180
+
181
+ - Update to depend on `vident-view_component` v0.3.0
182
+ - Adds support for new `Vident::Caching` module
183
+ - Update examples to support view_component v3
184
+
185
+ ### [0.1.0] - 2023-04-01
186
+
187
+ - Initial release, extracted from `vident`
188
+
189
+ ## vident-view_component
190
+
191
+ ### [0.3.0] - 2023-08-12
192
+
193
+ - Update to depend on `vident` v0.9.0
194
+ - Adds support for new `Vident::Caching` module
195
+ - Update examples to support view_component v3
196
+
197
+ ### [0.1.0] - 2023-04-01
198
+
199
+ - Initial release, extracted from `vident`
200
+
201
+ ## vident-phlex
202
+
203
+ ### [0.3.0] - 2023-08-12
204
+
205
+ - Update to depend on `vident` v0.9.0
206
+ - Adds support for new `Vident::Caching` module
207
+
208
+ ### [0.1.0] - 2023-04-01
209
+
210
+ - Initial release, extracted from `vident`
211
+
212
+ ## vident-typed-phlex
213
+
214
+ ### [0.3.0] - 2023-08-12
215
+
216
+ - Update to depend on `vident-typed` v0.3.0
217
+ - Adds support for new `Vident::Caching` module
218
+
219
+ ### [0.1.0] - 2023-04-01
220
+
221
+ - Initial release, extracted from `vident`
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022-2025 Stephen Ierodiaconou
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,3 +1,705 @@
1
+ # Vident
2
+
3
+ Vident is a collection of gems that provide a set of tools for building web applications with Ruby on Rails.
4
+
5
+ ## Included Gems
6
+
7
+ The core gems:
8
+
9
+ - `vident`: The core Vident library
10
+ - `vident-phlex`: Phlex integration for Vident
11
+ - `vident-view_component`: ViewComponent integration for Vident
12
+
13
+ Note that you can use both `Phlex` and `ViewComponent` in the same application if desired.
14
+
15
+ And then optional extra features:
16
+
17
+ - `vident-tailwind`: Tailwind CSS integration for Vident
18
+ - `vident-typed`: Type system for Vident components
19
+ - `vident-typed-minitest`: Minitest integration for typed Vident components
20
+ - `vident-typed-phlex`: Phlex integration for typed Vident components
21
+ - `vident-typed-view_component`: ViewComponent integration for typed Vident
22
+ - `vident-better_html`: Better HTML integration for Vident
23
+
24
+ ## Directory Structure
25
+
26
+ The repository is structured like this:
27
+
28
+ ```
29
+ vident/
30
+ ├── lib/ # All gem code
31
+ │ ├── vident.rb # Core entry point
32
+ │ ├── vident-phlex.rb # Gem entry points
33
+ │ ├── vident-better_html.rb
34
+ │ ├── vident/ # Shared code
35
+ │ ├── base.rb
36
+ │ ├── phlex/ # Phlex integration
37
+ │ ├── better_html/ # Better HTML integration
38
+ │ └── ...
39
+ ├── test/ # All tests
40
+ │ ├── vident/ # Core tests
41
+ │ ├── vident-phlex/ # Tests for each gem
42
+ │ └── ...
43
+ ├── docs/ # Documentation
44
+ ├── examples/ # Examples
45
+ ├── vident.gemspec # Gemspec for core gem
46
+ ├── vident-phlex.gemspec # Gemspecs for each gem
47
+ └── ...
48
+ ```
49
+
50
+ ## Development
51
+
52
+ ### Setting Up Development Environment
53
+
54
+ ```bash
55
+ # Clone the repository
56
+ git clone https://github.com/stevegeek/vident.git
57
+ cd vident
58
+
59
+ # Install dependencies
60
+ bundle install
61
+ ```
62
+
63
+ ### Running Tests
64
+
65
+ To run tests for all gems:
66
+
67
+ ```bash
68
+ rake test
69
+ ```
70
+
71
+ To run tests for a specific gem:
72
+
73
+ ```bash
74
+ rake test:vident-phlex
75
+ ```
76
+
77
+ ### Building and Installing Gems
78
+
79
+ To build all gems:
80
+
81
+ ```bash
82
+ rake build
83
+ ```
84
+
85
+ To install all gems locally:
86
+
87
+ ```bash
88
+ rake install
89
+ ```
90
+
91
+ ## Contributing
92
+
93
+ 1. Fork the repository
94
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
95
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
96
+ 4. Push to the branch (`git push origin my-new-feature`)
97
+ 5. Create a new Pull Request
98
+
99
+ ## License
100
+
101
+ The gems are available as open source under the terms of the [MIT License](LICENSE.txt).
102
+
103
+ ---
104
+
105
+ # Component Documentation
106
+
107
+ ---
108
+
109
+ ## gem: vident-typed-view_component
110
+
111
+ # Vident::Typed::ViewComponent
112
+
113
+ Adds typed attributes to Vident ViewComponent components.
114
+
115
+ ```ruby
116
+ class ApplicationComponent < ::Vident::Typed::ViewComponent::Base
117
+ end
118
+ ```
119
+
120
+ For more details see [vident](https://github.com/stevegeek/vident).
121
+
122
+ ### Examples
123
+
124
+ Before we dive into a specific example note that there are some components implemented in `test/dummy/app/components`.
125
+
126
+ Try them out by starting Rails:
127
+
128
+ ```bash
129
+ cd test/dummy
130
+ bundle install
131
+ rails assets:precompile
132
+ rails s
133
+ ```
134
+
135
+ and visiting http://localhost:3000
136
+
137
+
138
+ ### A Vident component example (without Stimulus)
139
+
140
+ First is an example component that uses `Vident::Typed::ViewComponent::Base` but no Stimulus features.
141
+
142
+ It is an avatar component that can either be displayed as an image or as initials.
143
+
144
+ 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.
145
+
146
+ ```ruby
147
+ class AvatarComponent < ::Vident::Typed::ViewComponent::Base
148
+ include ::Vident::Tailwind
149
+ include ::Vident::Caching
150
+
151
+ no_stimulus_controller
152
+ with_cache_key :attributes
153
+
154
+ attribute :url, String, allow_nil: true, allow_blank: false
155
+ attribute :initials, String, allow_blank: false
156
+
157
+ attribute :shape, Symbol, in: %i[circle square], default: :circle
158
+
159
+ attribute :border, :boolean, default: false
160
+
161
+ attribute :size, Symbol, in: %i[tiny small normal medium large x_large xx_large], default: :normal
162
+
163
+ private
164
+
165
+ def default_html_options
166
+ if image_avatar?
167
+ { class: "inline-block object-contain", src: url, alt: t(".image") }
168
+ else
169
+ { class: "inline-flex items-center justify-center bg-gray-500" }
170
+ end
171
+ end
172
+
173
+ def element_classes
174
+ [size_classes, shape_class, border? ? "border" : ""]
175
+ end
176
+
177
+ alias_method :image_avatar?, :url?
178
+
179
+ def shape_class
180
+ (shape == :circle) ? "rounded-full" : "rounded-md"
181
+ end
182
+
183
+ def size_classes
184
+ case size
185
+ when :tiny
186
+ "w-6 h-6"
187
+ when :small
188
+ "w-8 h-8"
189
+ when :medium
190
+ "w-12 h-12"
191
+ when :large
192
+ "w-14 h-14"
193
+ when :x_large
194
+ "sm:w-24 sm:h-24 w-16 h-16"
195
+ when :xx_large
196
+ "sm:w-32 sm:h-32 w-24 h-24"
197
+ else
198
+ "w-10 h-10"
199
+ end
200
+ end
201
+
202
+ def text_size_class
203
+ case size
204
+ when :tiny
205
+ "text-xs"
206
+ when :small
207
+ "text-xs"
208
+ when :medium
209
+ "text-lg"
210
+ when :large
211
+ "sm:text-xl text-lg"
212
+ when :extra_large
213
+ "sm:text-2xl text-xl"
214
+ else
215
+ "text-medium"
216
+ end
217
+ end
218
+ end
219
+ ```
220
+
221
+ ```erb
222
+ <%= render root(
223
+ element_tag: image_avatar? ? :img : :div,
224
+ html_options: default_html_options
225
+ ) do %>
226
+ <% unless image_avatar? %>
227
+ <span class="<%= text_size_class %> font-medium leading-none text-white"><%= initials %></span>
228
+ <% end %>
229
+ <% end %>
230
+
231
+ ```
232
+
233
+ Example usages:
234
+
235
+ ```erb
236
+ <!-- These will render -->
237
+ <%= render AvatarComponent.new(url: "https://someurl.com/avatar.jpg", initials: "AB" size: :large) %>
238
+ <%= render AvatarComponent.new(url: "https://someurl.com/avatar.jpg", html_options: {alt: "My alt text", class: "object-scale-down"}) %>
239
+ <%= render AvatarComponent.new(initials: "SG", size: :small) %>
240
+ <%= render AvatarComponent.new(initials: "SG", size: :large, html_options: {class: "border-2 border-red-600"}) %>
241
+
242
+ <!-- These will raise an error -->
243
+ <!-- missing initals -->
244
+ <%= render AvatarComponent.new(url: "https://someurl.com/avatar.jpg", size: :large) %>
245
+ <!-- initials blank -->
246
+ <%= render AvatarComponent.new(initials: "", size: :large) %>
247
+ <!-- invalid size -->
248
+ <%= render AvatarComponent.new(initials: "SG", size: :foo_bar) %>
249
+ ```
250
+
251
+
252
+ The following is rendered when used `render AvatarComponent.new(initials: "SG", size: :small, border: true)`:
253
+
254
+ ```html
255
+ <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">
256
+ <span class="text-xs font-medium leading-none text-white">SG</span>
257
+ </div>
258
+ ```
259
+
260
+ 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"})`:
261
+
262
+ ```html
263
+ <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">
264
+ ```
265
+
266
+ ----
267
+
268
+ ![Example](examples/avatar.png)
269
+
270
+
271
+ ### Another ViewComponent + Vident example with Stimulus
272
+
273
+ Consider the following ERB that might be part of an application's views. The app uses `ViewComponent`, `Stimulus` and `Vident`.
274
+
275
+ The Greeter is a component that displays a text input and a button. When the button is clicked, the text input's value is
276
+ used to greet the user. At the same time the button changes to be a 'reset' button, which resets the greeting when clicked again.
277
+
278
+ ![ex1.gif](examples/ex1.gif)
279
+
280
+ ```erb
281
+ <%# app/views/home/index.html.erb %>
282
+
283
+ <!-- ... -->
284
+
285
+ <!-- render the Greeter ViewComponent (that uses Vident) -->
286
+ <%= render ::GreeterComponent.new(cta: "Hey!", html_options: {class: "my-4"}) do |greeter| %>
287
+ <%# this component has a slot called `trigger` that renders a `ButtonComponent` (which also uses Vident) %>
288
+ <% greeter.with_trigger(
289
+
290
+ # The button component has attributes that are typed
291
+ before_clicked: "Greet",
292
+ after_clicked: "Greeted! Reset?",
293
+
294
+ # A stimulus action is added to the button that triggers the `greet` action on the greeter stimulus controller.
295
+ # This action will be added to any defined on the button component itself
296
+ actions: [
297
+ greeter.action(:click, :greet),
298
+ ],
299
+
300
+ # We can also override the default button classes of our component, or set other HTML attributes
301
+ html_options: {
302
+ class: "bg-red-500 hover:bg-red-700"
303
+ }
304
+ ) %>
305
+ <% end %>
306
+
307
+ <!-- ... -->
308
+ ```
309
+
310
+ The output HTML of the above, using Vident, is:
311
+
312
+ ```html
313
+ <div class="greeter-component py-2 my-4"
314
+ data-controller="greeter-component"
315
+ data-greeter-component-pre-click-class="text-md text-gray-500"
316
+ data-greeter-component-post-click-class="text-xl text-blue-700"
317
+ id="greeter-component-1599855-6">
318
+ <input type="text"
319
+ data-greeter-component-target="name"
320
+ class="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline">
321
+ <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"
322
+ data-controller="button-component"
323
+ data-action="click->greeter-component#greet button-component#changeMessage"
324
+ data-button-component-after-clicked-message="Greeted! Reset?"
325
+ data-button-component-before-clicked-message="Greet"
326
+ id="button-component-7799479-7">Hey!</button>
327
+ <!-- you can also use the `target_tag` helper to render targets -->
328
+ <span class="ml-4 text-md text-gray-500"
329
+ data-greeter-component-target="output">
330
+ ...
331
+ </span>
332
+ </div>
333
+ ```
334
+
335
+ Let's look at the components in more detail.
336
+
337
+ The main component is the `GreeterComponent`:
338
+
339
+ ```ruby
340
+ # app/components/greeter_component.rb
341
+
342
+ class GreeterComponent < ::Vident::ViewComponent::Base
343
+ renders_one :trigger, ButtonComponent
344
+ end
345
+ ```
346
+
347
+ ```erb
348
+ <%# app/components/greeter_component.html.erb %>
349
+
350
+ <%# Rendering the `root` element creates a tag which has stimulus `data-*`s, a unique id & other attributes set. %>
351
+ <%# The stimulus controller name (identifier) is derived from the component name, and then used to generate the relavent data attribute names. %>
352
+
353
+ <%= render root named_classes: {
354
+ pre_click: "text-md text-gray-500", # named classes are exposed to Stimulus as `data-<controller>-<n>-class` attributes
355
+ post_click: "text-xl text-blue-700",
356
+ html_options: {class: "py-2"}
357
+ } do |greeter| %>
358
+
359
+ <%# `greeter` is the root element and exposes methods to generate stimulus targets and actions %>
360
+ <input type="text"
361
+ <%= greeter.as_target(:name) %>
362
+ class="shadow appearance-none border rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline">
363
+
364
+ <%# Render the slot %>
365
+ <%= trigger %>
366
+
367
+ <%# you can also use the `target_tag` helper to render targets %>
368
+ <%= greeter.target_tag(
369
+ :span,
370
+ :output,
371
+ # Stimulus named classes can be referenced to set class attributes at render time
372
+ class: "ml-4 #{greeter.named_classes(:pre_click)}"
373
+ ) do %>
374
+ ...
375
+ <% end %>
376
+ <% end %>
377
+
378
+ ```
379
+
380
+ ```js
381
+ // app/components/greeter_component_controller.js
382
+
383
+ import { Controller } from "@hotwired/stimulus"
384
+
385
+ // This is a Stimulus controller that is automatically registered for the `GreeterComponent`
386
+ // and is 'sidecar' to the component. You can see that while in the ERB we use Ruby naming conventions
387
+ // with snake_case Symbols, here they are converted to camelCase names. We can also just use camelCase
388
+ // in the ERB if we want.
389
+ export default class extends Controller {
390
+ static targets = [ "name", "output" ]
391
+ static classes = [ "preClick", "postClick" ]
392
+
393
+ greet() {
394
+ this.clicked = !this.clicked;
395
+ this.outputTarget.classList.toggle(this.preClickClasses, !this.clicked);
396
+ this.outputTarget.classList.toggle(this.postClickClasses, this.clicked);
397
+
398
+ if (this.clicked)
399
+ this.outputTarget.textContent = `Hello, ${this.nameTarget.value}!`
400
+ else
401
+ this.clear();
402
+ }
403
+
404
+ clear() {
405
+ this.outputTarget.textContent = '...';
406
+ this.nameTarget.value = '';
407
+ }
408
+ }
409
+ ```
410
+
411
+ The slot renders a `ButtonComponent` component:
412
+
413
+ ```ruby
414
+ # app/components/button_component.rb
415
+
416
+ class ButtonComponent < ::Vident::Typed::ViewComponent::Base
417
+ # The attributes can specify an expected type, a default value and if nil is allowed.
418
+ attribute :after_clicked, String, default: "Greeted!"
419
+ attribute :before_clicked, String, allow_nil: false
420
+
421
+ # This example is a templateless ViewComponent.
422
+ def call
423
+ # The button is rendered as a <button> tag with an click action on its own controller.
424
+ render root(
425
+ element_tag: :button,
426
+
427
+ # We can define actions as arrays of Symbols, or pass manually manually crafted strings.
428
+ # Here we specify the action name only, implying an action on the current components controller
429
+ # and the default event type of `click`.
430
+ actions: [:change_message],
431
+ # Alternatively: [:click, :change_message] or ["click", "changeMessage"] or even "click->button-component#changeMessage"
432
+
433
+ # A couple of data values are also set which will be available to the controller
434
+ data_maps: [{after_clicked_message: after_clicked, before_clicked_message: before_clicked}],
435
+
436
+ # The <button> tag has a default styling set directly on it. Note that
437
+ # if not using utility classes, you can style the component using its
438
+ # canonical class name (which is equal to the component's stimulus identifier),
439
+ # in this case `button-component`.
440
+ html_options: {class: "ml-4 whitespace-no-wrap bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"}
441
+ ) do
442
+ @before_clicked
443
+ end
444
+ end
445
+ end
446
+ ```
447
+
448
+ ```js
449
+ // app/components/button_component_controller.js
450
+
451
+ import { Controller } from "@hotwired/stimulus"
452
+
453
+ export default class extends Controller {
454
+ // The action is in camelCase.
455
+ changeMessage() {
456
+ this.clicked = !this.clicked;
457
+ // The data attributes have their naming convention converted to camelCase.
458
+ this.element.textContent = this.clicked ? this.data.get("afterClickedMessage") : this.data.get("beforeClickedMessage");
459
+ }
460
+ }
461
+
462
+ ```
463
+
464
+ ### Usage
465
+ How to use my plugin.
466
+
467
+ ### Installation
468
+ Add this line to your application's Gemfile:
469
+
470
+ ```ruby
471
+ gem "vident-typed-view_component"
472
+ ```
473
+
474
+ And then execute:
475
+ ```bash
476
+ $ bundle
477
+ ```
478
+
479
+ Or install it yourself as:
480
+ ```bash
481
+ $ gem install vident-typed-view_component
482
+ ```
483
+
484
+ ---
485
+
486
+
487
+ ## gem: vident-view_component
488
+
489
+ # Vident::ViewComponent
490
+
491
+ [ViewComponent](https://viewcomponent.org/) powered [Vident](https://github.com/stevegeek/vident) components.
492
+
493
+ ```ruby
494
+ class ApplicationComponent < ::Vident::ViewComponent::Base
495
+ end
496
+ ```
497
+
498
+ For more details see [vident](https://github.com/stevegeek/vident).
499
+
500
+ ### Examples
501
+
502
+ Before we dive into a specific example note that there are some components implemented in the `test/dummy/app/components`.
503
+
504
+ Try them out by starting Rails:
505
+
506
+ ```bash
507
+ cd test/dummy
508
+ bundle install
509
+ rails assets:precompile
510
+ rails s
511
+ ```
512
+
513
+ and visiting http://localhost:3000
514
+
515
+
516
+ ### A Vident component example (without Stimulus)
517
+
518
+ First is an example component that uses `Vident::ViewComponent::Base` but no Stimulus features.
519
+
520
+ It is an avatar component that can either be displayed as an image or as initials. 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.
521
+
522
+ ```ruby
523
+ class AvatarComponent < ::Vident::ViewComponent::Base
524
+ include ::Vident::Tailwind
525
+ include ::Vident::Caching
526
+
527
+ no_stimulus_controller
528
+ with_cache_key :attributes
529
+
530
+ attribute :url, allow_nil: true
531
+ attribute :initials, allow_nil: false
532
+
533
+ attribute :shape, default: :circle
534
+
535
+ attribute :border, default: false
536
+
537
+ attribute :size, default: :normal
538
+
539
+ private
540
+
541
+ def default_html_options
542
+ if image_avatar?
543
+ { class: "inline-block object-contain", src: url, alt: t(".image") }
544
+ else
545
+ { class: "inline-flex items-center justify-center bg-gray-500" }
546
+ end
547
+ end
548
+
549
+ def element_classes
550
+ [size_classes, shape_class, border? ? "border" : ""]
551
+ end
552
+
553
+ alias_method :image_avatar?, :url?
554
+
555
+ def shape_class
556
+ (shape == :circle) ? "rounded-full" : "rounded-md"
557
+ end
558
+
559
+ def size_classes
560
+ case size
561
+ when :tiny
562
+ "w-6 h-6"
563
+ when :small
564
+ "w-8 h-8"
565
+ when :medium
566
+ "w-12 h-12"
567
+ when :large
568
+ "w-14 h-14"
569
+ when :x_large
570
+ "sm:w-24 sm:h-24 w-16 h-16"
571
+ when :xx_large
572
+ "sm:w-32 sm:h-32 w-24 h-24"
573
+ else
574
+ "w-10 h-10"
575
+ end
576
+ end
577
+
578
+ def text_size_class
579
+ case size
580
+ when :tiny
581
+ "text-xs"
582
+ when :small
583
+ "text-xs"
584
+ when :medium
585
+ "text-lg"
586
+ when :large
587
+ "sm:text-xl text-lg"
588
+ when :extra_large
589
+ "sm:text-2xl text-xl"
590
+ else
591
+ "text-medium"
592
+ end
593
+ end
594
+ end
595
+ ```
596
+
597
+ ```erb
598
+ <%= render root(
599
+ element_tag: image_avatar? ? :img : :div,
600
+ html_options: default_html_options
601
+ ) do %>
602
+ <% unless image_avatar? %>
603
+ <span class="<%= text_size_class %> font-medium leading-none text-white"><%= initials %></span>
604
+ <% end %>
605
+ <% end %>
606
+ ```
607
+
608
+ Example usages:
609
+
610
+ ```erb
611
+ <%= render AvatarComponent.new(url: "https://someurl.com/avatar.jpg", initials: "AB" size: :large) %>
612
+ <%= render AvatarComponent.new(url: "https://someurl.com/avatar.jpg", html_options: {alt: "My alt text", class: "object-scale-down"}) %>
613
+ <%= render AvatarComponent.new(initials: "SG", size: :small) %>
614
+ <%= render AvatarComponent.new(initials: "SG", size: :large, html_options: {class: "border-2 border-red-600"}) %>
615
+ ```
616
+
617
+ The following is rendered when used `render AvatarComponent.new(initials: "SG", size: :small, border: true)`:
618
+
619
+ ```html
620
+ <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">
621
+ <span class="text-xs font-medium leading-none text-white">SG</span>
622
+ </div>
623
+ ```
624
+
625
+ 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"})`:
626
+
627
+ ```html
628
+ <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">
629
+ ```
630
+
631
+ ----
632
+
633
+ ![Example](examples/avatar.png)
634
+
635
+ ### Usage
636
+ How to use my plugin.
637
+
638
+ ### Installation
639
+ Add this line to your application's Gemfile:
640
+
641
+ ```ruby
642
+ gem "vident-view_component"
643
+ ```
644
+
645
+ And then execute:
646
+ ```bash
647
+ $ bundle
648
+ ```
649
+
650
+ Or install it yourself as:
651
+ ```bash
652
+ $ gem install vident-view_component
653
+ ```
654
+
655
+ ---
656
+
657
+ ## gem: vident-better_html
658
+
659
+ # Vident::BetterHtml
660
+ Short description and motivation.
661
+
662
+ ### Usage
663
+ How to use my plugin.
664
+
665
+ ```ruby
666
+ BetterHtml.config = BetterHtml::Config.new(YAML.load(File.read(".better-html.yml")))
667
+
668
+ BetterHtml.configure do |config|
669
+ config.template_exclusion_filter = proc { |filename| !filename.start_with?(Rails.root.to_s) }
670
+ end
671
+ # ViewComponent needs to do this hack to work in certain cases
672
+ # see https://github.com/Shopify/better-html/pull/98
673
+ class BetterHtml::HtmlAttributes
674
+ alias_method :to_s_without_html_safe, :to_s
675
+
676
+ def to_s
677
+ to_s_without_html_safe.html_safe
678
+ end
679
+ end
680
+ ```
681
+
682
+ ### Installation
683
+ Add this line to your application's Gemfile:
684
+
685
+ ```ruby
686
+ gem "vident-better_html"
687
+ ```
688
+
689
+ And then execute:
690
+ ```bash
691
+ $ bundle
692
+ ```
693
+
694
+ Or install it yourself as:
695
+ ```bash
696
+ $ gem install vident-better_html
697
+ ```
698
+
699
+ ---
700
+
701
+ ## gem: vident-phlex
702
+
1
703
  # Vident::Phlex
2
704
 
3
705
  [Phlex](https://phlex.fun/) powered [Vident](https://github.com/stevegeek/vident) components.
@@ -9,10 +711,10 @@ end
9
711
 
10
712
  For more details see [vident](https://github.com/stevegeek/vident).
11
713
 
12
- ## Usage
714
+ ### Usage
13
715
  How to use my plugin.
14
716
 
15
- ## Installation
717
+ ### Installation
16
718
  Add this line to your application's Gemfile:
17
719
 
18
720
  ```ruby
@@ -29,8 +731,121 @@ Or install it yourself as:
29
731
  $ gem install vident-phlex
30
732
  ```
31
733
 
32
- ## Contributing
33
- Contribution directions go here.
734
+ ---
34
735
 
35
- ## License
36
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
736
+ ## gem: vident-tailwind
737
+
738
+ # Vident::Tailwind
739
+ Short description and motivation.
740
+
741
+ ### Usage
742
+ How to use my plugin.
743
+
744
+ ### Installation
745
+ Add this line to your application's Gemfile:
746
+
747
+ ```ruby
748
+ gem "vident-tailwind"
749
+ ```
750
+
751
+ And then execute:
752
+ ```bash
753
+ $ bundle
754
+ ```
755
+
756
+ Or install it yourself as:
757
+ ```bash
758
+ $ gem install vident-tailwind
759
+ ```
760
+
761
+ ---
762
+
763
+ ## gem: vident-typed-minitest
764
+
765
+ # Vident::Typed::Minitest
766
+ Short description and motivation.
767
+
768
+ ### Usage
769
+ How to use my plugin.
770
+
771
+ ### Installation
772
+ Add this line to your application's Gemfile:
773
+
774
+ ```ruby
775
+ gem "vident-typed-minitest"
776
+ ```
777
+
778
+ And then execute:
779
+ ```bash
780
+ $ bundle
781
+ ```
782
+
783
+ Or install it yourself as:
784
+ ```bash
785
+ $ gem install vident-typed-minitest
786
+ ```
787
+
788
+ ---
789
+
790
+ ## gem: vident-typed-phlex
791
+
792
+ # Vident::Typed::Phlex
793
+
794
+ Adds typed attributes to Vident Phlex based components.
795
+
796
+ ```ruby
797
+ class ApplicationComponent < ::Vident::Typed::Phlex::HTML
798
+ end
799
+ ```
800
+
801
+ For more details see [vident](https://github.com/stevegeek/vident).
802
+
803
+ ### Usage
804
+ How to use my plugin.
805
+
806
+ ### Installation
807
+ Add this line to your application's Gemfile:
808
+
809
+ ```ruby
810
+ gem "vident-typed-phlex"
811
+ ```
812
+
813
+ And then execute:
814
+ ```bash
815
+ $ bundle
816
+ ```
817
+
818
+ Or install it yourself as:
819
+ ```bash
820
+ $ gem install vident-typed-phlex
821
+ ```
822
+
823
+ ---
824
+
825
+
826
+ ## gem: vident-typed
827
+
828
+ # Vident::Typed
829
+ Short description and motivation.
830
+
831
+ ### Usage
832
+ How to use my plugin.
833
+
834
+ ### Installation
835
+ Add this line to your application's Gemfile:
836
+
837
+ ```ruby
838
+ gem "vident-typed"
839
+ ```
840
+
841
+ And then execute:
842
+ ```bash
843
+ $ bundle
844
+ ```
845
+
846
+ Or install it yourself as:
847
+ ```bash
848
+ $ gem install vident-typed
849
+ ```
850
+
851
+ ---
@@ -20,8 +20,8 @@ module Vident
20
20
  end
21
21
 
22
22
  # Helper to create the main element
23
- def parent_element(**options)
24
- @parent_element ||= ::Vident::Phlex::RootComponent.new(**parent_element_attributes(options))
23
+ def parent_element
24
+ @parent_element ||= ::Vident::Phlex::RootComponent.new(**stimulus_options_for_root_component)
25
25
  end
26
26
  alias_method :root, :parent_element
27
27
  end
@@ -47,7 +47,7 @@ module Vident
47
47
  def generate_tag(tag_type, content, **options, &block)
48
48
  # FIXME: Content was generated by the block, we assume its safe but that might not be true!
49
49
  method_name = (tag_type == :template) ? :template_tag : tag_type
50
- block = proc { unsafe_raw content } if !block && content
50
+ block = proc { raw content.html_safe } if !block && content
51
51
  send(method_name, **options, &block)
52
52
  end
53
53
  end
@@ -1,5 +1,5 @@
1
1
  module Vident
2
2
  module Phlex
3
- VERSION = "0.5.1"
3
+ VERSION = Vident::VERSION
4
4
  end
5
5
  end
data/lib/vident/phlex.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  require "vident/phlex/version"
2
- require "vident/phlex/engine"
2
+ require "vident/phlex/core"
3
+ require "vident/phlex/html"
4
+ require "vident/phlex/root_component"
5
+ require "vident/phlex/engine" if defined?(Rails)
3
6
 
4
7
  module Vident
5
8
  module Phlex
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vident-phlex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Ierodiaconou
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-10-18 00:00:00.000000000 Z
10
+ date: 2025-06-26 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: railties
@@ -16,60 +15,54 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '7'
18
+ version: '7.2'
20
19
  - - "<"
21
20
  - !ruby/object:Gem::Version
22
- version: '8.0'
21
+ version: '9'
23
22
  type: :runtime
24
23
  prerelease: false
25
24
  version_requirements: !ruby/object:Gem::Requirement
26
25
  requirements:
27
26
  - - ">="
28
27
  - !ruby/object:Gem::Version
29
- version: '7'
28
+ version: '7.2'
30
29
  - - "<"
31
30
  - !ruby/object:Gem::Version
32
- version: '8.0'
31
+ version: '9'
33
32
  - !ruby/object:Gem::Dependency
34
33
  name: activesupport
35
34
  requirement: !ruby/object:Gem::Requirement
36
35
  requirements:
37
36
  - - ">="
38
37
  - !ruby/object:Gem::Version
39
- version: '7'
38
+ version: '7.2'
40
39
  - - "<"
41
40
  - !ruby/object:Gem::Version
42
- version: '8.0'
41
+ version: '9'
43
42
  type: :runtime
44
43
  prerelease: false
45
44
  version_requirements: !ruby/object:Gem::Requirement
46
45
  requirements:
47
46
  - - ">="
48
47
  - !ruby/object:Gem::Version
49
- version: '7'
48
+ version: '7.2'
50
49
  - - "<"
51
50
  - !ruby/object:Gem::Version
52
- version: '8.0'
51
+ version: '9'
53
52
  - !ruby/object:Gem::Dependency
54
53
  name: vident
55
54
  requirement: !ruby/object:Gem::Requirement
56
55
  requirements:
57
- - - ">="
58
- - !ruby/object:Gem::Version
59
- version: 0.9.0
60
- - - "<"
56
+ - - "~>"
61
57
  - !ruby/object:Gem::Version
62
- version: '1'
58
+ version: 0.13.1
63
59
  type: :runtime
64
60
  prerelease: false
65
61
  version_requirements: !ruby/object:Gem::Requirement
66
62
  requirements:
67
- - - ">="
63
+ - - "~>"
68
64
  - !ruby/object:Gem::Version
69
- version: 0.9.0
70
- - - "<"
71
- - !ruby/object:Gem::Version
72
- version: '1'
65
+ version: 0.13.1
73
66
  - !ruby/object:Gem::Dependency
74
67
  name: phlex
75
68
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +72,7 @@ dependencies:
79
72
  version: 1.5.0
80
73
  - - "<"
81
74
  - !ruby/object:Gem::Version
82
- version: '2'
75
+ version: '3'
83
76
  type: :runtime
84
77
  prerelease: false
85
78
  version_requirements: !ruby/object:Gem::Requirement
@@ -89,7 +82,7 @@ dependencies:
89
82
  version: 1.5.0
90
83
  - - "<"
91
84
  - !ruby/object:Gem::Version
92
- version: '2'
85
+ version: '3'
93
86
  - !ruby/object:Gem::Dependency
94
87
  name: phlex-rails
95
88
  requirement: !ruby/object:Gem::Requirement
@@ -99,7 +92,7 @@ dependencies:
99
92
  version: 0.8.1
100
93
  - - "<"
101
94
  - !ruby/object:Gem::Version
102
- version: '2'
95
+ version: '3'
103
96
  type: :runtime
104
97
  prerelease: false
105
98
  version_requirements: !ruby/object:Gem::Requirement
@@ -109,7 +102,7 @@ dependencies:
109
102
  version: 0.8.1
110
103
  - - "<"
111
104
  - !ruby/object:Gem::Version
112
- version: '2'
105
+ version: '3'
113
106
  description: Vident with Phlex
114
107
  email:
115
108
  - stevegeek@gmail.com
@@ -117,23 +110,22 @@ executables: []
117
110
  extensions: []
118
111
  extra_rdoc_files: []
119
112
  files:
113
+ - CHANGELOG.md
114
+ - LICENSE.txt
120
115
  - README.md
121
- - Rakefile
122
- - lib/tasks/vident/phlex_tasks.rake
123
116
  - lib/vident/phlex.rb
124
117
  - lib/vident/phlex/core.rb
125
118
  - lib/vident/phlex/engine.rb
126
119
  - lib/vident/phlex/html.rb
127
120
  - lib/vident/phlex/root_component.rb
128
121
  - lib/vident/phlex/version.rb
129
- homepage: https://github.com/stevegeek/vident-phlex
122
+ homepage: https://github.com/stevegeek/vident
130
123
  licenses:
131
124
  - MIT
132
125
  metadata:
133
- homepage_uri: https://github.com/stevegeek/vident-phlex
134
- source_code_uri: https://github.com/stevegeek/vident-phlex
135
- changelog_uri: https://github.com/stevegeek/vident-phlex/blob/main/CHANGELOG.md
136
- post_install_message:
126
+ homepage_uri: https://github.com/stevegeek/vident
127
+ source_code_uri: https://github.com/stevegeek/vident
128
+ changelog_uri: https://github.com/stevegeek/vident/blob/main/CHANGELOG.md
137
129
  rdoc_options: []
138
130
  require_paths:
139
131
  - lib
@@ -141,15 +133,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
133
  requirements:
142
134
  - - ">="
143
135
  - !ruby/object:Gem::Version
144
- version: '0'
136
+ version: 3.1.0
145
137
  required_rubygems_version: !ruby/object:Gem::Requirement
146
138
  requirements:
147
139
  - - ">="
148
140
  - !ruby/object:Gem::Version
149
141
  version: '0'
150
142
  requirements: []
151
- rubygems_version: 3.5.11
152
- signing_key:
143
+ rubygems_version: 3.6.2
153
144
  specification_version: 4
154
145
  summary: Vident with Phlex
155
146
  test_files: []
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- require "bundler/setup"
2
-
3
- APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
- load "rails/tasks/engine.rake"
5
-
6
- load "rails/tasks/statistics.rake"
7
-
8
- require "bundler/gem_tasks"
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :vident_phlex do
3
- # # Task goes here
4
- # end