vident 1.0.2 → 2.0.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 +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +45 -17
- data/lib/vident/caching.rb +4 -110
- data/lib/vident/capabilities/caching.rb +98 -0
- data/lib/vident/capabilities/child_element_rendering.rb +92 -0
- data/lib/vident/capabilities/class_list_building.rb +23 -0
- data/lib/vident/capabilities/declarable.rb +39 -0
- data/lib/vident/capabilities/identifiable.rb +54 -0
- data/lib/vident/capabilities/inspectable.rb +17 -0
- data/lib/vident/capabilities/root_element_rendering.rb +31 -0
- data/lib/vident/capabilities/stimulus_data_emitting.rb +98 -0
- data/lib/vident/capabilities/stimulus_declaring.rb +79 -0
- data/lib/vident/capabilities/stimulus_draft.rb +51 -0
- data/lib/vident/capabilities/stimulus_mutation.rb +60 -0
- data/lib/vident/capabilities/stimulus_parsing.rb +144 -0
- data/lib/vident/capabilities/tailwind.rb +18 -0
- data/lib/vident/component.rb +14 -76
- data/lib/vident/engine.rb +6 -5
- data/lib/vident/error.rb +16 -0
- data/lib/{vident2 → vident}/internals/action_builder.rb +18 -22
- data/lib/vident/internals/attribute_writer.rb +17 -0
- data/lib/{vident2 → vident}/internals/class_list_builder.rb +5 -22
- data/lib/vident/internals/declaration.rb +13 -0
- data/lib/{vident2 → vident}/internals/declarations.rb +6 -18
- data/lib/{vident2 → vident}/internals/draft.rb +3 -16
- data/lib/{vident2 → vident}/internals/dsl.rb +6 -32
- data/lib/vident/internals/plan.rb +9 -0
- data/lib/vident/internals/registry.rb +37 -0
- data/lib/{vident2 → vident}/internals/resolver.rb +101 -91
- data/lib/{vident2 → vident}/internals/target_builder.rb +1 -7
- data/lib/vident/stable_id.rb +3 -3
- data/lib/{vident2 → vident}/stimulus/action.rb +11 -24
- data/lib/vident/stimulus/base.rb +26 -0
- data/lib/{vident2 → vident}/stimulus/class_map.rb +6 -18
- data/lib/{vident2 → vident}/stimulus/collection.rb +6 -8
- data/lib/vident/stimulus/combinable.rb +30 -0
- data/lib/vident/stimulus/controller.rb +45 -0
- data/lib/vident/stimulus/naming.rb +9 -9
- data/lib/vident/stimulus/null.rb +7 -0
- data/lib/{vident2 → vident}/stimulus/outlet.rb +12 -32
- data/lib/{vident2 → vident}/stimulus/param.rb +5 -11
- data/lib/{vident2 → vident}/stimulus/target.rb +5 -14
- data/lib/vident/stimulus/value.rb +57 -0
- data/lib/vident/stimulus_null.rb +4 -8
- data/lib/vident/tailwind.rb +4 -17
- data/lib/vident/types.rb +28 -0
- data/lib/vident/version.rb +1 -6
- data/lib/vident.rb +46 -36
- data/skills/vident/SKILL.md +122 -19
- data/skills/vident/api-reference.md +259 -115
- data/skills/vident/examples.md +23 -10
- metadata +38 -60
- data/lib/vident/child_element_helper.rb +0 -64
- data/lib/vident/class_list_builder.rb +0 -112
- data/lib/vident/component_attribute_resolver.rb +0 -106
- data/lib/vident/component_class_lists.rb +0 -37
- data/lib/vident/stimulus/primitive.rb +0 -38
- data/lib/vident/stimulus.rb +0 -31
- data/lib/vident/stimulus_action.rb +0 -133
- data/lib/vident/stimulus_action_collection.rb +0 -11
- data/lib/vident/stimulus_attribute_base.rb +0 -67
- data/lib/vident/stimulus_attributes.rb +0 -129
- data/lib/vident/stimulus_builder.rb +0 -136
- data/lib/vident/stimulus_class.rb +0 -59
- data/lib/vident/stimulus_class_collection.rb +0 -11
- data/lib/vident/stimulus_collection_base.rb +0 -51
- data/lib/vident/stimulus_component.rb +0 -75
- data/lib/vident/stimulus_controller.rb +0 -41
- data/lib/vident/stimulus_controller_collection.rb +0 -14
- data/lib/vident/stimulus_data_attribute_builder.rb +0 -32
- data/lib/vident/stimulus_helper.rb +0 -66
- data/lib/vident/stimulus_outlet.rb +0 -90
- data/lib/vident/stimulus_outlet_collection.rb +0 -11
- data/lib/vident/stimulus_param.rb +0 -42
- data/lib/vident/stimulus_param_collection.rb +0 -11
- data/lib/vident/stimulus_target.rb +0 -47
- data/lib/vident/stimulus_target_collection.rb +0 -18
- data/lib/vident/stimulus_value.rb +0 -39
- data/lib/vident/stimulus_value_collection.rb +0 -11
- data/lib/vident2/caching.rb +0 -93
- data/lib/vident2/component.rb +0 -538
- data/lib/vident2/engine.rb +0 -18
- data/lib/vident2/error.rb +0 -30
- data/lib/vident2/internals/attribute_writer.rb +0 -22
- data/lib/vident2/internals/declaration.rb +0 -17
- data/lib/vident2/internals/plan.rb +0 -12
- data/lib/vident2/internals/registry.rb +0 -41
- data/lib/vident2/phlex/html.rb +0 -84
- data/lib/vident2/phlex.rb +0 -9
- data/lib/vident2/stimulus/controller.rb +0 -59
- data/lib/vident2/stimulus/naming.rb +0 -26
- data/lib/vident2/stimulus/null.rb +0 -16
- data/lib/vident2/stimulus/value.rb +0 -77
- data/lib/vident2/tailwind.rb +0 -19
- data/lib/vident2/version.rb +0 -5
- data/lib/vident2/view_component/base.rb +0 -124
- data/lib/vident2/view_component.rb +0 -9
- data/lib/vident2.rb +0 -50
data/skills/vident/SKILL.md
CHANGED
|
@@ -54,13 +54,64 @@ class Foo::BarComponent < Vident::ViewComponent::Base
|
|
|
54
54
|
end
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
**Subclass re-enables the controller.** `no_stimulus_controller` is inherited by subclasses. A subclass that has its own paired JS controller calls `has_stimulus_controller` to flip the flag back on:
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
class ApplicationComponent < Vident::Phlex::HTML
|
|
61
|
+
no_stimulus_controller # shell — no paired JS
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class DropdownComponent < ApplicationComponent
|
|
65
|
+
has_stimulus_controller # emits data-controller="dropdown-component"
|
|
66
|
+
stimulus { actions :toggle }
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
57
70
|
Cross-controller references elsewhere (actions/targets/values/classes/outlets) use the `"path/to/controller"` **string** form — Vident stimulizes it for you.
|
|
58
71
|
|
|
59
72
|
### 1.2 Actions
|
|
60
73
|
|
|
61
74
|
Stimulus descriptor: `event->controller#method`, with optional modifiers (`:once`, `:prevent`, `keydown.ctrl+a`, `@window`, etc.). Stimulus encodes them as space-separated tokens in `data-action="..."`.
|
|
62
75
|
|
|
63
|
-
|
|
76
|
+
**Primary form — the fluent `action(...)` builder.** Singular `action` returns a builder that reads left-to-right:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
stimulus do
|
|
80
|
+
action :click # implied#click
|
|
81
|
+
action(:submit).on(:click) # click->implied#submit
|
|
82
|
+
action(:save).on(:click).modifier(:prevent, :stop) # click:prevent:stop->implied#save
|
|
83
|
+
action(:escape).on(:keydown).keyboard("esc").window # keydown.esc@window->implied#escape
|
|
84
|
+
action(:delete).when { admin? } # conditional — `.when` takes a predicate proc
|
|
85
|
+
end
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Chain methods: `.on(event)`, `.call_method(name)` (override), `.modifier(*opts)`, `.keyboard(str)`, `.window`, `.on_controller(alias_sym)`, `.when { predicate }`. Each returns `self`.
|
|
89
|
+
|
|
90
|
+
**Kwargs shorthand.** Equivalent to the fluent chain — pick whichever reads better:
|
|
91
|
+
|
|
92
|
+
```ruby
|
|
93
|
+
action :save, on: :click, modifier: [:prevent, :stop]
|
|
94
|
+
action :escape, on: :keydown, keyboard: "esc", window: true
|
|
95
|
+
action :delete, when: -> { admin? }
|
|
96
|
+
action :save, on: :click, call_method: :handle_save
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Recognised keys: `on:`, `call_method:`, `modifier:` (Symbol or Array), `keyboard:`, `window:`, `on_controller:`, `when:`. Anything else raises `ArgumentError`.
|
|
100
|
+
|
|
101
|
+
**Controller aliases.** Declare a short name for a cross-controller path with `controller "path", as: :alias`, then reference it from action entries:
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
stimulus do
|
|
105
|
+
controller "admin/users", as: :admin
|
|
106
|
+
|
|
107
|
+
action(:save).on(:click).on_controller(:admin) # click->admin--users#save
|
|
108
|
+
action :save, on: :click, on_controller: :admin # same, kwargs form
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The alias resolves at render time — unknown aliases raise `Vident::DeclarationError`. Also works for runtime inputs: `stimulus_actions: [{method: :save, controller: :admin}]` resolves against the same declared map.
|
|
113
|
+
|
|
114
|
+
**Legacy plural form.** Still accepted for compat — `actions(*entries)` accepts:
|
|
64
115
|
|
|
65
116
|
| Ruby | Emits |
|
|
66
117
|
| ------------------------------------------- | -------------------------------------------------- |
|
|
@@ -69,10 +120,9 @@ Vident `actions` DSL entries (all of these work inside `stimulus do ... end`):
|
|
|
69
120
|
| `[:click, "other/ctrl", :my_thing]` | `click->other--ctrl#myThing` |
|
|
70
121
|
| `"click->other--ctrl#myThing"` | pass-through, parsed into its parts |
|
|
71
122
|
| `{event: :click, method: :submit, options: [:once, :prevent]}` | `click:once:prevent->implied#submit` |
|
|
72
|
-
| `Vident::StimulusAction::Descriptor.new(event: :click, method: :submit, options: [:once])` | same — typed data object, Hash is sugar |
|
|
73
123
|
| `-> { [:click, :my_thing] if @editable }` | proc, evaluated in component instance; `nil`/`false` returns drop the entry |
|
|
74
124
|
|
|
75
|
-
**Modifiers via the Hash
|
|
125
|
+
**Modifiers via the Hash form.** Accepted keys:
|
|
76
126
|
|
|
77
127
|
| Key | Type | Emits |
|
|
78
128
|
| ------------ | ----------------- | ---------------------------------------- |
|
|
@@ -83,7 +133,7 @@ Vident `actions` DSL entries (all of these work inside `stimulus do ... end`):
|
|
|
83
133
|
| `keyboard:` | String like `"ctrl+a"` | `.ctrl+a` suffix on event filter |
|
|
84
134
|
| `window:` | Boolean | `@window` suffix on event |
|
|
85
135
|
|
|
86
|
-
Unknown option symbols raise `ArgumentError`.
|
|
136
|
+
Unknown option symbols raise `ArgumentError`. The Hash descriptor is parsed directly into `Vident::Stimulus::Action` — there is no separate `Descriptor` class in V2.
|
|
87
137
|
|
|
88
138
|
```ruby
|
|
89
139
|
actions({event: :keydown, method: :on_escape, keyboard: "esc", options: [:prevent]})
|
|
@@ -247,7 +297,7 @@ stimulus_outlets: [
|
|
|
247
297
|
]
|
|
248
298
|
```
|
|
249
299
|
|
|
250
|
-
**(c) Child self-registers on a host via `stimulus_outlet_host:`.** Every Vident component inherits a `stimulus_outlet_host` prop. Passing a parent component at render time calls `host.add_stimulus_outlets(self)` in `
|
|
300
|
+
**(c) Child self-registers on a host via `stimulus_outlet_host:`.** Every Vident component inherits a `stimulus_outlet_host` prop. Passing a parent component at render time calls `host.add_stimulus_outlets(self)` in `after_initialize` (via `Vident::Capabilities::StimulusDraft`), so the host's root gets the outlet attribute without enumerating children in its DSL:
|
|
251
301
|
|
|
252
302
|
```ruby
|
|
253
303
|
render PageComponent.new do |page|
|
|
@@ -329,7 +379,7 @@ prop :count, Integer, default: 0 # with default
|
|
|
329
379
|
prop :url, _Nilable(String) # optional / nilable
|
|
330
380
|
prop :variant, _Union(:primary, :secondary), default: :primary
|
|
331
381
|
prop :items, _Array(Hash), default: -> { [] } # callable defaults must be lambdas
|
|
332
|
-
prop :open, _Boolean, default: false #
|
|
382
|
+
prop :open, _Boolean, default: false # pass `predicate: :public` to also get an `open?` method
|
|
333
383
|
```
|
|
334
384
|
|
|
335
385
|
Props become `@ivar`s at init time. To also expose a reader method, declare the prop with `reader: :public`.
|
|
@@ -343,9 +393,9 @@ From `Vident::Component`:
|
|
|
343
393
|
- `classes` — `String | Array(String)`. Appended to the root element's `class=`.
|
|
344
394
|
- `html_options` — `Hash`. Merged onto the root element; highest precedence.
|
|
345
395
|
|
|
346
|
-
From `Vident::
|
|
396
|
+
From `Vident::Component`:
|
|
347
397
|
|
|
348
|
-
- `stimulus_controllers` — `Array(String | Symbol |
|
|
398
|
+
- `stimulus_controllers` — `Array(String | Symbol | Vident::Stimulus::Controller)`. Defaults to `[default_controller_path]` unless `no_stimulus_controller` is declared.
|
|
349
399
|
- `stimulus_actions`, `stimulus_targets`, `stimulus_values`, `stimulus_classes`, `stimulus_outlets` — Array / Hash props matching the shapes described in section 1.
|
|
350
400
|
- `stimulus_outlet_host` — optional `Vident::Component`; activates child→host outlet self-registration.
|
|
351
401
|
|
|
@@ -413,13 +463,45 @@ When handwriting HTML inside ERB instead of using `child_element`, emit just the
|
|
|
413
463
|
<div <%= component.as_stimulus_values(%i[count label]) %>></div>
|
|
414
464
|
```
|
|
415
465
|
|
|
416
|
-
Plural (`as_stimulus_targets`, `as_stimulus_actions`, `as_stimulus_values`, `as_stimulus_classes`, `as_stimulus_outlets`, `as_stimulus_controllers`) and singular variants exist for every attribute kind. These helpers are defined on `Vident::ViewComponent::Base`; for Phlex, use `child_element` or compose directly.
|
|
466
|
+
Plural (`as_stimulus_targets`, `as_stimulus_actions`, `as_stimulus_values`, `as_stimulus_params`, `as_stimulus_classes`, `as_stimulus_outlets`, `as_stimulus_controllers`) and singular variants (`as_stimulus_target`, `as_stimulus_action`, `as_stimulus_value`, `as_stimulus_param`, `as_stimulus_class`, `as_stimulus_outlet`, `as_stimulus_controller`) exist for every attribute kind. These helpers are defined on `Vident::ViewComponent::Base`; for Phlex, use `child_element` or compose directly.
|
|
467
|
+
|
|
468
|
+
### Class-level Stimulus builders (no instance needed)
|
|
469
|
+
|
|
470
|
+
When you need a Stimulus value without a component instance (Turbo-Stream partials, JSON endpoints, test selectors), call the builders on the class:
|
|
471
|
+
|
|
472
|
+
```ruby
|
|
473
|
+
ButtonComponent.stimulus_target(:submit) # Vident::Stimulus::Target
|
|
474
|
+
ButtonComponent.stimulus_action(:click, :handle) # click->implied#handle
|
|
475
|
+
ButtonComponent.stimulus_value(:count, 0)
|
|
476
|
+
ButtonComponent.stimulus_param(:item_id, 42)
|
|
477
|
+
ButtonComponent.stimulus_class(:loading, "opacity-50")
|
|
478
|
+
ButtonComponent.stimulus_outlet(:modal, ".js-modal") # selector required
|
|
479
|
+
ButtonComponent.stimulus_controller # the implied controller
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
Returns a `Vident::Stimulus::*` value object with the same `#to_h` / `#to_data_pair` as the instance equivalents — splat `.to_h` into a tag's HTML options. Two restrictions at class level: **outlets require an explicit selector** (no `component_id` to auto-scope), and **cross-controller forms are rejected** (call `Vident::Stimulus::Target.parse(...)` directly for those).
|
|
483
|
+
|
|
484
|
+
### Rendering outside `root_element(...)`
|
|
485
|
+
|
|
486
|
+
For components that build their root tag via a third-party helper (e.g. `inline_svg_tag`), two instance methods return what `root_element(...)` would emit:
|
|
487
|
+
|
|
488
|
+
- `root_element_class_list(extra_classes = nil)` → `String` with the full class cascade (`component_name`, `root_element_classes`, `@classes` prop, `html_options[:class]`, extras) plus Tailwind-merging.
|
|
489
|
+
- `root_element_data_attributes` → `Hash` (Symbol keys) with the full `data-*` set (controller, action, target, value, param, class, outlet) from the sealed Plan.
|
|
490
|
+
|
|
491
|
+
```ruby
|
|
492
|
+
def view_template
|
|
493
|
+
svg("data-src" => helpers.image_path(file_name),
|
|
494
|
+
id: @id,
|
|
495
|
+
class: root_element_class_list,
|
|
496
|
+
data: root_element_data_attributes) {}
|
|
497
|
+
end
|
|
498
|
+
```
|
|
417
499
|
|
|
418
500
|
---
|
|
419
501
|
|
|
420
502
|
## 3. `stimulus do ... end` block
|
|
421
503
|
|
|
422
|
-
Opens a `Vident::
|
|
504
|
+
Opens a `Vident::Internals::DSL` instance scoped to the class. It supports `actions`, `targets`, `values`, `values_from_props`, `classes`, `outlets`. Multiple `stimulus do` blocks on the same class are merged; a subclass's block is merged with its superclass's (subclass entries appended, values/classes/outlets merged by key, subclass wins on conflicts).
|
|
423
505
|
|
|
424
506
|
Procs passed anywhere in the DSL are evaluated via `instance_exec` on the **component instance** at render time (Phlex `before_template` / ViewComponent `before_render`), so they see `@ivars`, public/private instance methods, and the view context.
|
|
425
507
|
|
|
@@ -495,8 +577,30 @@ Vident::StableId.with_sequence_generator(seed: "some-unique-key") { render ... }
|
|
|
495
577
|
|
|
496
578
|
- **`after_component_initialize`** — override in your component; runs after props are assigned and Vident has prepared its stimulus collections. Don't override `after_initialize` unless you `super` — Literal calls it to wire everything up.
|
|
497
579
|
- **`component_name` / `stimulus_identifier`** — class method and instance method; the kebab-case/`--`-separated identifier. Used for outlet auto-selectors, scoped event names, and the default class on the root.
|
|
498
|
-
- **Caching** (`include Vident::Caching` + `with_cache_key :attr1, :attr2`) — declares attributes that feed `cache_key`. Combined with a template mtime so edits bust the cache. `depends_on(OtherComponent, …)` chains subcomponent mtimes into the key.
|
|
499
|
-
-
|
|
580
|
+
- **Caching** (`include Vident::Caching` + `with_cache_key :attr1, :attr2`) — declares attributes that feed `cache_key`. Combined with a template mtime so edits bust the cache. `depends_on(OtherComponent, …)` chains subcomponent mtimes into the key. Two separable concerns:
|
|
581
|
+
- **Computing the key** — `component.cache_key` is always available once `with_cache_key` is declared. Use it for etags, conditional rendering, explicit `Rails.cache.fetch(key) { ... }` at the call site, or any other place you need a content-addressed identifier.
|
|
582
|
+
- **Fragment-caching the render** — `cache_component(*extra_keys, &block)` wraps the block with Rails.cache using the Vident-computed key. Works on both adapters. For Phlex, call it inside `view_template` (delegates to Phlex's `cache(...)`); for ViewComponent, call inside `call` (uses `Rails.cache.fetch` + `capture`). Sidecar ERB templates can just write `<% cache cache_key do %> ... <% end %>` directly.
|
|
583
|
+
|
|
584
|
+
```ruby
|
|
585
|
+
# Phlex
|
|
586
|
+
def view_template
|
|
587
|
+
cache_component do
|
|
588
|
+
root_element { ... }
|
|
589
|
+
end
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
# ViewComponent (def call form)
|
|
593
|
+
def call
|
|
594
|
+
cache_component { root_element { ... } }
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
# ViewComponent (sidecar ERB) — use the Rails helper with component.cache_key
|
|
598
|
+
# <% cache cache_key do %>
|
|
599
|
+
# <%= root_element do %>...<% end %>
|
|
600
|
+
# <% end %>
|
|
601
|
+
```
|
|
602
|
+
Calling `cache_component` on a non-cacheable component (no `with_cache_key`) raises `Vident::ConfigurationError`.
|
|
603
|
+
- **`with(overrides = {})`** — returns a new instance with merged props. (`clone` is a backward-compat alias.)
|
|
500
604
|
- **Phlex tag safety** — `Vident::Phlex::HTML` validates every `child_element` tag name against a whitelist; passing an unknown tag raises.
|
|
501
605
|
|
|
502
606
|
---
|
|
@@ -625,13 +729,12 @@ end
|
|
|
625
729
|
|
|
626
730
|
For the exhaustive public-API listing (every method signature, argument shape, and raise-condition, verified against current code), see [`api-reference.md`](api-reference.md). The files below are useful when you need to read the implementation itself.
|
|
627
731
|
|
|
628
|
-
- `lib/vident/
|
|
629
|
-
- `lib/vident/stimulus_attributes.rb` — parser for every `stimulus_*` input shape + `as_stimulus_*` helpers' backing.
|
|
630
|
-
- `lib/vident/stimulus_{action,target,value,outlet,class,controller}.rb` — value objects; read `parse_arguments` to learn the argument shapes.
|
|
631
|
-
- `lib/vident/child_element_helper.rb` — `child_element` kwargs and validation.
|
|
632
|
-
- `lib/vident/component_attribute_resolver.rb` — how DSL, props, and `root_element_attributes` compose at render time.
|
|
633
|
-
- `lib/vident/component_class_lists.rb` — `class_list_for_stimulus_classes` / `render_classes`.
|
|
732
|
+
- `lib/vident/component.rb` — composition root; includes all capabilities in dependency order.
|
|
634
733
|
- `lib/vident/stable_id.rb` — the StableId strategy system.
|
|
635
734
|
- `lib/vident/stimulus_null.rb` — the StimulusNull sentinel.
|
|
636
|
-
- `lib/vident/
|
|
735
|
+
- `lib/vident/stimulus/` — value classes: `Action`, `Target`, `Controller`, `Outlet`, `Value`, `Param`, `ClassMap`, `Collection`, `Null`, `Naming`.
|
|
736
|
+
- `lib/vident/capabilities/` — focused capability mixins: `Tailwind`, `Caching`, `Declarable`, `Identifiable`, `StimulusDeclaring`, `StimulusParsing`, `StimulusMutation`, `StimulusDraft`, `StimulusDataEmitting`, `ClassListBuilding`, `RootElementRendering`, `ChildElementRendering`, `Inspectable`.
|
|
737
|
+
- `lib/vident/internals/` — internal DSL/resolver plumbing: `Registry`, `Declaration`, `Declarations`, `DSL`, `Draft`, `Plan`, `Resolver`, `AttributeWriter`, `ClassListBuilder`, `ActionBuilder`, `TargetBuilder`.
|
|
738
|
+
- `lib/vident/phlex/html.rb` — Phlex adapter (`root_element`, `child_element`, tag whitelist).
|
|
739
|
+
- `lib/vident/view_component/base.rb` — ViewComponent adapter (`root_element`, `child_element`, `as_stimulus_*` helpers).
|
|
637
740
|
- `test/dummy/app/components/dashboard/` — canonical multi-component example (outlets, scoped events, `StimulusNull`, dynamic classes, `values_from_props`, `class_list_for_stimulus_classes`, full JS side).
|