vident-phlex 1.0.0.beta2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -1
  3. data/README.md +171 -17
  4. data/lib/vident/phlex/html.rb +3 -7
  5. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4466b6e94b193580be755d18af0d75b075b31bc1a5cfb96911aa04302ca7604
4
- data.tar.gz: '038b7d3c7fd7633372cde14d268a671067edf2299a13805269e4a934d89a5202'
3
+ metadata.gz: 1a941674bbc07885fbd2a26849332fc6e6957a22feb5162b9cee454746d8205c
4
+ data.tar.gz: '0912a7ad696343c5437056344b51822e4e9af4b2dbca92ea78c805b2e3039567'
5
5
  SHA512:
6
- metadata.gz: b92de4dca48fff939f1fe933d913ccc7f84f734593fa81072251d904e4171f70901ae1a4e13c41c7cd4635305715e9b879dbac31329390b422a0ea166fc16d12
7
- data.tar.gz: ceea7b4cabf7aa0e2711ce9048b3f531ba71513ad2e0591c4135ee26e25037a9755a9712e66b43707125cab56b0f85ab78a16055a8802f1774862766165ae620
6
+ metadata.gz: 3331181090bf6dc0edf13b515f71881e570b453c7655c991414a3ae1c49965cbaacb40597e5484fe1316ab298e8af4aa6051efd4a4f63c38f6d880200ed8273b
7
+ data.tar.gz: 85c1212c4e9ee24e021cf9192bbe78134723243da8a5e45d2163eba243abc180f10169a41133dc2a51078f9f289223442d3b1d2c4c6fc89b6471e16fce0aefee
data/CHANGELOG.md CHANGED
@@ -6,11 +6,42 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
8
 
9
+ ## [1.0.0] - 2026-04-19
10
+
11
+ ### Breaking
12
+
13
+ - `nil` stimulus values (static or returned from a proc) are now filtered out of the rendered data attributes instead of being serialized to an empty string. The previous behaviour silently turned Boolean-typed Stimulus values on, because Stimulus parses empty strings as `true`. To explicitly emit the JS `null` literal (for Object/Array values), return the new `Vident::StimulusNull` sentinel (#24).
14
+ - `Vident::StableId` now requires an explicit strategy and an explicit per-request seed (#14). Run `bin/rails generate vident:install` to create an initializer that picks `STRICT` outside tests and wires a `before_action` in `ApplicationController` seeding the generator from `request.fullpath`. `set_current_sequence_generator` now requires `seed:` (nil raises `ArgumentError`); calling `next_id_in_sequence` with no strategy configured raises `Vident::StableId::StrategyNotConfiguredError`; in `STRICT` mode, missing the per-request seeding raises `Vident::StableId::GeneratorNotSetError`. The previous hard-coded seed of `42` (which produced identical IDs across unrelated requests and caused DOM collisions when Ajax fragments were grafted into server-rendered pages) is gone, and the `new_current_sequence_generator` alias has been removed.
15
+
16
+ ### Added
17
+
18
+ - `Vident::StimulusNull` sentinel. Assign or return it from a value proc to emit `data-...-value="null"`, which Stimulus's Object/Array parser reads as JSON `null`.
19
+ - `Vident::StableId.with_sequence_generator(seed:) { ... }` block helper for scoping a generator to a render outside the normal request flow (mailers, jobs, previews) (#14).
20
+ - `bin/rails generate vident:install` installer that writes `config/initializers/vident.rb` and patches `ApplicationController` with the per-request seed hook (#14).
21
+ - Claude Code skill at `skills/vident/SKILL.md` shipped with the gem. The install generator drops it into `.claude/skills/vident/SKILL.md` in the host app so Claude Code picks up the gem's conventions automatically.
22
+ - Action descriptor support. The `stimulus_actions:` prop, `stimulus do ... actions(...)` DSL, and `child_element(stimulus_action(s): ...)` now accept a `Hash` (`{event:, method:, controller:, options:, keyboard:, window:}`) or a typed `Vident::StimulusAction::Descriptor` instance, allowing the `:once`/`:prevent`/`:stop`/`:passive`/`:"!passive"`/`:capture`/`:self` event-option modifiers, `.ctrl+a`-style keyboard filters, and `@window` in a structured Ruby form rather than a hand-typed descriptor string.
23
+ - Stimulus action parameters. New `Vident::StimulusParam` / `StimulusParamCollection`, a `stimulus_params:` prop, a `params` DSL entry (mirrors `values`), a `stimulus_params:`/`stimulus_param:` kwarg on `child_element`, and inline `as_stimulus_param(s)` helpers. Emits `data-<controller>-<name>-param` attributes readable via `event.params.<name>` in the JS controller; element-scoped to match Stimulus's own semantics.
24
+
25
+ ### Changed
26
+
27
+ - Internal refactor: introduced a `Vident::Stimulus::PRIMITIVES` registry (`lib/vident/stimulus.rb`) as the single source of truth for the seven Stimulus primitive kinds (controllers, actions, targets, outlets, values, params, classes). `StimulusDataAttributeBuilder`, the seven `stimulus_<kind>s(...)` plural parsers, and the seven `add_stimulus_<kind>s(...)` mutators are now generated from that registry, so adding a future primitive is a one-line registry addition plus a Value/Collection class pair — no per-kind edits in the resolver, builder, child-element helper, or data-attribute builder. No user-visible API change.
28
+ - `serialize_value` lives on `StimulusAttributeBase` and is shared across `StimulusValue` / `StimulusParam` (was duplicated).
29
+ - `StimulusAttributeBase.stimulize_path` is the canonical path → identifier helper (`stimulus_identifier_from_path` on `StimulusComponent` now delegates); both accept Symbol input consistently.
30
+ - `StimulusBuilder`'s two nil-filter methods collapsed into one `resolve_hash_filtering_nil`.
31
+ - Uniform shape matrix across all seven plural parsers: every kind now consistently accepts pre-built `<Kind>` instances, pre-built `<Kind>Collection`s, Arrays, and (where meaningful) Hashes in its variadic input.
32
+
33
+ ### Fixed
34
+
35
+ - `stimulus_controllers:` prop and the `stimulus_controllers(...)` helper now accept Symbol paths (e.g. `:my_controller`, `:"admin/users"`) instead of raising `NoMethodError: undefined method 'split' for an instance of Symbol` (#15).
36
+ - `Vident::StimulusController`'s `implied_controller_path` / `implied_controller_name` overrides now raise the same `ArgumentError` as the base when `implied_controller` is nil, instead of a confusing `NoMethodError`.
37
+ - `stimulus_values:` and `stimulus_classes:` props now accept cross-controller entries. The type unions include `Array` (matching `stimulus_actions:`/`stimulus_targets:`), and the collection parsers pass through pre-built `StimulusValue`/`StimulusValueCollection` (and class equivalents) instead of re-wrapping them into the single-value constructor and raising `ArgumentError: Invalid number of arguments` (#23).
38
+ - `Vident::ComponentClassLists#class_list_builder` no longer memoises the `ClassListBuilder` instance. The first caller's `root_element_html_class:` was previously latched into the cached builder, which silently dropped the `class:` argument passed to a later `root_element(class: …)` whenever `class_list_for_stimulus_classes(:name)` ran first. The underlying `TailwindMerge::Merger` is still thread-cached, so the re-construction cost is negligible.
39
+
9
40
  ## [1.0.0.beta2] - 2026-04-16
10
41
 
11
42
  ### Breaking
12
43
 
13
- - Renamed the `tag(...)` helper to `child_element(...)` (and the internal `Vident::TagHelper` module to `Vident::ChildElementHelper`). The old name shadowed Rails' own `tag(name, options)` positional API, which breaks Rails helpers like `hidden_field_tag` and `image_tag` when called inside vident components. Rename any `component.tag(...)` calls to `component.child_element(...)`.
44
+ - Renamed the `tag(...)` helper to `child_element(...)` (and the internal `Vident::TagHelper` module to `Vident::ChildElementHelper`). The old name shadowed Rails' own `tag(name, options)` positional API, which breaks Rails helpers like `hidden_field_tag` and `image_tag` when called inside vident components (#22). Rename any `component.tag(...)` calls to `component.child_element(...)`.
14
45
 
15
46
  ### Fixed
16
47
 
data/README.md CHANGED
@@ -59,8 +59,11 @@ Then run:
59
59
 
60
60
  ```bash
61
61
  bundle install
62
+ bin/rails generate vident:install
62
63
  ```
63
64
 
65
+ The `vident:install` generator writes `config/initializers/vident.rb`, wires per-request ID seeding into `ApplicationController`, and (if you use Claude Code) drops a Vident skill into `.claude/skills/vident/SKILL.md` so the model has first-party guidance on the gem's conventions. See [Element IDs and request-scoped seeding](#element-ids-and-request-scoped-seeding) for the initializer rationale, and [Claude Code skill](#claude-code-skill) for the skill.
66
+
64
67
  ## Quick Start
65
68
 
66
69
  Here's a simple example of a Vident component using ViewComponent:
@@ -352,10 +355,25 @@ class ToggleComponent < Vident::ViewComponent::Base
352
355
  classes expanded: "block",
353
356
  collapsed: "hidden",
354
357
  transitioning: "opacity-50"
358
+
359
+ # Action parameters (element-scoped; readable as event.params.* in JS)
360
+ params item_id: -> { @item.id }, kind: "inline"
355
361
  end
356
362
  end
357
363
  ```
358
364
 
365
+ **Action modifiers** — the Array form `[:click, :method]` handles the common case. For Stimulus's modifier syntax (`:once`/`:prevent`/`:stop`/`:passive`/`:"!passive"`/`:capture`/`:self`, keyboard filters, `@window`), pass a Hash or a `Vident::StimulusAction::Descriptor`:
366
+
367
+ ```ruby
368
+ actions({event: :click, method: :submit, options: [:once, :prevent]})
369
+ actions({event: :keydown, method: :on_key, keyboard: "ctrl+a"})
370
+ actions({event: :resize, method: :on_resize, window: true})
371
+ # or, if you want a typed, passable object:
372
+ actions Vident::StimulusAction::Descriptor.new(event: :click, method: :save, options: [:prevent])
373
+ ```
374
+
375
+ Unknown option symbols raise `ArgumentError` at attribute construction, not at render.
376
+
359
377
  ### Dynamic Values and Classes with Procs
360
378
 
361
379
  The Stimulus DSL supports dynamic values and classes using procs or lambdas that are evaluated in the component instance context:
@@ -415,6 +433,43 @@ stimulus do
415
433
  end
416
434
  ```
417
435
 
436
+ **Nil values.** Returning `nil` from a value proc (or setting a static `nil`) omits the data attribute entirely, so Stimulus uses its per-type default. Don't rely on `nil` becoming empty-string — that silently reads as `true` for Boolean values. If you genuinely need to emit a JS `null` (only meaningful for Object/Array-typed Stimulus values), return the `Vident::StimulusNull` sentinel, which serializes to the literal string `"null"` for JSON.parse.
437
+
438
+ ```ruby
439
+ values current_user_id: -> { @user&.id }, # nil → attribute omitted
440
+ config: -> { @user ? @config : Vident::StimulusNull } # nil object → JSON null
441
+ ```
442
+
443
+ ### Action Parameters
444
+
445
+ Stimulus action parameters — `data-<controller>-<name>-param="value"` — are read inside an action handler as `event.params.<name>` (auto-typecast to Number / String / Object / Boolean). Params are **element-scoped**: every action attached to the same element sees the same params.
446
+
447
+ Vident mirrors the `values` entry points:
448
+
449
+ ```ruby
450
+ # In the DSL (component root element)
451
+ stimulus do
452
+ actions [:click, :promote]
453
+ params release_id: -> { @release_id }, kind: "promote"
454
+ end
455
+
456
+ # As a prop at render time
457
+ render MyComponent.new(stimulus_params: { release_id: 42 })
458
+
459
+ # Cross-controller (Array form) — both as a prop and in the DSL
460
+ stimulus_params: [
461
+ [:release_id, 42], # implied-release-id-param="42"
462
+ ["other/ctrl", :scope, "full"], # other--ctrl-scope-param="full"
463
+ ]
464
+
465
+ # On a child element (co-located with the action it informs)
466
+ card.child_element(:button,
467
+ stimulus_action: [:click, :promote],
468
+ stimulus_params: { release_id: @release_id })
469
+ ```
470
+
471
+ Inline helpers: `as_stimulus_param(:name, value)` / `as_stimulus_params({name: value, ...})`.
472
+
418
473
  ### Scoped Custom Events
419
474
 
420
475
  Vident provides helper methods to generate scoped event names for dispatching custom events that are unique to your component:
@@ -474,6 +529,8 @@ class CustomComponent < Vident::ViewComponent::Base
474
529
  end
475
530
  ```
476
531
 
532
+ All stimulus props accept Symbol paths as well as Strings (e.g. `stimulus_controllers: [:custom, :"admin/users"]`). `stimulus_values:` and `stimulus_classes:` additionally accept Array entries (for cross-controller: `[["admin/users", :name, "value"]]`) and pre-built `StimulusValue`/`StimulusValueCollection` / `StimulusClass`/`StimulusClassCollection` instances, so you can compose attribute sets outside the component and pass them in.
533
+
477
534
  or you can use tag helpers to generate HTML with Stimulus attributes:
478
535
 
479
536
  ```erb
@@ -521,36 +578,71 @@ or directly in the ViewComponent template (eg with ERB) using the `as_stimulus_*
521
578
 
522
579
  ### Stimulus Helpers in Templates
523
580
 
524
- Vident provides helper methods for generating Stimulus attributes:
581
+ Inline helpers emit pre-built `data-*` fragments you can drop into any tag. Both singular and plural forms exist; pass one or many arguments accordingly.
525
582
 
526
583
  ```erb
527
584
  <%= render root do |component| %>
528
- <!-- Create a target -->
529
- <div <%= component.as_target(:content) %>>
585
+ <div <%= component.as_stimulus_target(:content) %>>
530
586
  Content here
531
587
  </div>
532
-
533
- <!-- Create an action -->
534
- <button <%= component.as_action(:click, :toggle) %>>
535
- Toggle
536
- </button>
537
-
538
- <!-- Use the tag helper -->
539
- <%= component.tag :div, stimulus_target: :output, class: "mt-4" do %>
588
+
589
+ <button <%= component.as_stimulus_action(:click, :toggle) %>>Toggle</button>
590
+
591
+ <input <%= component.as_stimulus_targets(:input, :field) %>
592
+ <%= component.as_stimulus_actions([:input, :validate], [:change, :save]) %>>
593
+
594
+ <%# Or build a whole element with the child_element helper: %>
595
+ <%= component.child_element(:div, stimulus_target: :output, class: "mt-4") do %>
540
596
  Output here
541
597
  <% end %>
542
-
543
- <!-- Multiple targets/actions -->
544
- <input <%= component.as_targets(:input, :field) %>
545
- <%= component.as_actions([:input, :validate], [:change, :save]) %>>
546
598
  <% end %>
547
599
  ```
548
600
 
601
+ Parallel helpers exist for every attribute kind: `as_stimulus_controller(s)`, `as_stimulus_value(s)`, `as_stimulus_class(es)`, `as_stimulus_outlet(s)`.
602
+
549
603
  ### Stimulus Outlets
550
604
 
551
- Connect components via Stimulus outlets:
605
+ [Stimulus outlets](https://stimulus.hotwired.dev/reference/outlets) let one controller hold references to other controllers matched by a CSS selector. Vident has a few forms for declaring them.
552
606
 
607
+ **On the component's root element** — via the DSL:
553
608
 
609
+ ```ruby
610
+ class DashboardComponent < Vident::ViewComponent::Base
611
+ stimulus do
612
+ # kwarg form: outlet name is the implied controller's identifier
613
+ outlets modal: ".modal", user_status: ".online-user"
614
+
615
+ # positional-hash form: required when the outlet identifier contains "--"
616
+ # (e.g. cross-namespace controllers) because Ruby kwarg keys can't have dashes
617
+ outlets({"admin--users" => ".admin-users"})
618
+ end
619
+ end
620
+ ```
621
+
622
+ Or via the `stimulus_outlets:` prop / `root_element_attributes`:
623
+
624
+ ```ruby
625
+ stimulus_outlets: [
626
+ [:modal, ".modal"], # [name, selector] on implied controller
627
+ ["admin/users", :row, ".user-row"], # [controller_path, name, selector] for cross-controller
628
+ :user_status, # single symbol → auto-selector (see below)
629
+ other_component # component instance → reuses its stimulus_identifier + id
630
+ ]
631
+ ```
632
+
633
+ **Auto-generated selectors.** Pass just a name (symbol or string) and the selector becomes `[data-controller~=<name>]`. Pass a component instance and the selector additionally scopes to the component's id (`#<id> [data-controller~=...]`), which is what lets you target a specific instance rather than every matching controller on the page.
634
+
635
+ **Self-registration via `stimulus_outlet_host`.** A built-in prop on every Vident component. When set to another component, the child registers itself as an outlet on that host at initialization — the host doesn't need to know about the child in its DSL:
636
+
637
+ ```ruby
638
+ render DashboardComponent.new do |dashboard|
639
+ render ModalComponent.new(stimulus_outlet_host: dashboard)
640
+ end
641
+ ```
642
+
643
+ The modal now appears on the dashboard's root element as `data-dashboard-component-modal-component-outlet="#<modal-id>"` without the dashboard declaring it upfront.
644
+
645
+ **On child elements** — `child_element` accepts `stimulus_outlet:` (singular) and `stimulus_outlets:` (plural / Enumerable) exactly like the target/action kwargs, so a nested `<div>` can carry its own outlet declarations.
554
646
 
555
647
 
556
648
  ### Stimulus Controller Naming
@@ -586,7 +678,7 @@ end
586
678
  <% end %>
587
679
  ```
588
680
 
589
- This creates a nested component that once clicked triggers the parent components `handleTrigger` action.
681
+ This creates a nested component that once clicked triggers the parent components `handleTrigger` action. The same pattern works for cross-controller `stimulus_values:`, `stimulus_classes:`, and `stimulus_outlets:` — build the entries with the parent's helpers (`parent.stimulus_value(...)`, etc.) and pass them down.
590
682
 
591
683
  ## Other Features
592
684
 
@@ -692,6 +784,68 @@ end
692
784
  <% end %>
693
785
  ```
694
786
 
787
+ ### Element IDs and request-scoped seeding
788
+
789
+ Every Vident component generates an element `id` at construction time (e.g. `button-component-abc123-0`). The IDs are produced by a deterministic sequence so the same render produces the same markup — which is what lets HTTP `ETag` caching return `304 Not Modified` for unchanged pages.
790
+
791
+ Because the IDs are deterministic, **the sequence has to be keyed on something that identifies the logical content of the request**. If two unrelated renders share the same seed, the same sequence indices produce the same IDs, and Ajax-inserted fragments can collide with IDs already on the page.
792
+
793
+ The `vident:install` generator wires this up for you. It writes `config/initializers/vident.rb`:
794
+
795
+ ```ruby
796
+ # config/initializers/vident.rb
797
+ Vident::StableId.strategy = if Rails.env.test?
798
+ Vident::StableId::RANDOM_FALLBACK
799
+ else
800
+ Vident::StableId::STRICT
801
+ end
802
+ ```
803
+
804
+ and patches `ApplicationController`:
805
+
806
+ ```ruby
807
+ class ApplicationController < ActionController::Base
808
+ before_action do
809
+ Vident::StableId.set_current_sequence_generator(seed: request.fullpath)
810
+ end
811
+ after_action do
812
+ Vident::StableId.clear_current_sequence_generator
813
+ end
814
+ end
815
+ ```
816
+
817
+ **Why `request.fullpath`?** It includes the query string, so `/items/1?page=2` and `/items/1?page=3` get different seeds and different IDs — which is what you want, because they are different pages from a caching perspective. Requests to the same fullpath get identical IDs, so `ETag` matches work unchanged.
818
+
819
+ #### Strategies
820
+
821
+ - `Vident::StableId::STRICT` (production/development default). Raises `Vident::StableId::GeneratorNotSetError` if a component renders on a thread that has no generator set. Use this in any environment where missing the `before_action` is a bug — the loud failure tells you immediately.
822
+ - `Vident::StableId::RANDOM_FALLBACK` (test default). Emits a random hex id when no generator is set. Tests, ViewComponent previews, and ad-hoc renders work without any extra wiring. You can still call `set_current_sequence_generator(seed:)` when you want to assert on deterministic IDs.
823
+
824
+ You can point `strategy` at any callable of your own, e.g. to log every generation or route through a different generator entirely.
825
+
826
+ #### Rendering outside a request
827
+
828
+ Mailers, jobs, previews, and scripts run outside the controller callback cycle, so there's no `before_action` to seed the generator. Under `STRICT` they will raise. Two options:
829
+
830
+ 1. **Wrap the render in a scoped generator:**
831
+ ```ruby
832
+ Vident::StableId.with_sequence_generator(seed: "daily-digest-#{Date.today}") do
833
+ render_component(DigestComponent.new(...))
834
+ end
835
+ ```
836
+ The block sets the generator, yields, and restores whatever was on the thread before (including `nil`) in an `ensure`.
837
+ 2. **Run in a context where `RANDOM_FALLBACK` is fine.** If you don't care about id stability for that particular render (no caching, no snapshot comparison), either swap the strategy for that block or just accept random IDs.
838
+
839
+ #### The collision bug in earlier versions
840
+
841
+ Before 1.0.0 `set_current_sequence_generator` hard-coded the seed to `42`, so every request that called it got the same deterministic sequence. When two independent renders shipped in one browser session — e.g. a server-rendered page and an Ajax fragment loaded into it — both started from index 0 and produced colliding `id` attributes. This surfaced as duplicate IDs in the DOM, broken `label[for=...]` associations, and Stimulus controllers attaching to the wrong element. Upgrading and running `bin/rails generate vident:install` seeds from `request.fullpath` instead, so each render gets its own sequence space.
842
+
843
+ ### Claude Code skill
844
+
845
+ Vident ships a [Claude Code](https://docs.claude.com/claude-code) skill at `skills/vident/SKILL.md` that teaches the model the gem's conventions: the `stimulus do` DSL, `child_element`, outlets (including `stimulus_outlet_host` self-registration), the `nil` / `Vident::StimulusNull` value rules, the per-request StableId setup, and the Ruby↔JS dispatch handshake. It covers the foot-guns ahead of time so the model doesn't repeat them.
846
+
847
+ `bin/rails generate vident:install` copies the file into `.claude/skills/vident/SKILL.md` of the host app (skipped if already present). Claude Code picks it up automatically via skill discovery; no further wiring needed. If you want to update the skill later, delete the file and re-run the generator.
848
+
695
849
 
696
850
  ## Testing
697
851
 
@@ -3,7 +3,7 @@
3
3
  module Vident
4
4
  module Phlex
5
5
  class HTML < ::Phlex::HTML
6
- include ::Vident::Component
6
+ include Vident::Component
7
7
 
8
8
  STANDARD_ELEMENTS = [:a, :abbr, :address, :article, :aside, :b, :bdi, :bdo, :blockquote, :body, :button, :caption, :cite, :code, :colgroup, :data, :datalist, :dd, :del, :details, :dfn, :dialog, :div, :dl, :dt, :em, :fieldset, :figcaption, :figure, :footer, :form, :g, :h1, :h2, :h3, :h4, :h5, :h6, :head, :header, :hgroup, :html, :i, :iframe, :ins, :kbd, :label, :legend, :li, :main, :map, :mark, :menuitem, :meter, :nav, :noscript, :object, :ol, :optgroup, :option, :output, :p, :path, :picture, :pre, :progress, :q, :rp, :rt, :ruby, :s, :samp, :script, :section, :select, :slot, :small, :span, :strong, :style, :sub, :summary, :sup, :svg, :table, :tbody, :td, :template_tag, :textarea, :tfoot, :th, :thead, :time, :title, :tr, :u, :ul, :video, :wbr].freeze
9
9
  VOID_ELEMENTS = [:area, :br, :embed, :hr, :img, :input, :link, :meta, :param, :source, :track, :col].freeze
@@ -29,15 +29,11 @@ module Vident
29
29
  def root_element(**overrides, &block)
30
30
  tag_type = root_element_tag_type
31
31
  check_valid_html_tag!(tag_type)
32
- # Evaluate before generating the outer tag options to ensure DSL methods are executed
32
+ # Evaluate block first so DSL methods run before outer tag options are computed.
33
33
  if block_given?
34
34
  content = capture(self, &block).html_safe
35
35
  options = resolve_root_element_attributes_before_render(overrides)
36
- if content
37
- send(tag_type, **options) { content }
38
- else
39
- send(tag_type, **options)
40
- end
36
+ send(tag_type, **options) { content }
41
37
  else
42
38
  send(tag_type, **resolve_root_element_attributes_before_render(overrides))
43
39
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vident-phlex
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Ierodiaconou
@@ -55,14 +55,14 @@ dependencies:
55
55
  requirements:
56
56
  - - "~>"
57
57
  - !ruby/object:Gem::Version
58
- version: 1.0.0.beta2
58
+ version: 1.0.0
59
59
  type: :runtime
60
60
  prerelease: false
61
61
  version_requirements: !ruby/object:Gem::Requirement
62
62
  requirements:
63
63
  - - "~>"
64
64
  - !ruby/object:Gem::Version
65
- version: 1.0.0.beta2
65
+ version: 1.0.0
66
66
  - !ruby/object:Gem::Dependency
67
67
  name: phlex
68
68
  requirement: !ruby/object:Gem::Requirement
@@ -131,7 +131,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
131
  requirements:
132
132
  - - ">="
133
133
  - !ruby/object:Gem::Version
134
- version: 3.1.0
134
+ version: 3.2.0
135
135
  required_rubygems_version: !ruby/object:Gem::Requirement
136
136
  requirements:
137
137
  - - ">="