kiso 0.4.1.pre → 0.4.3.pre

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: 2746806e86680de2110a413ce1e6f29b0cc31a080bd1a41de7b5ac07902833cd
4
- data.tar.gz: e4bd2a60cf877c765c15b57de4d2743ca4de925a65bd7646ef7783b39d32fbb9
3
+ metadata.gz: 0e16c80be5816e217b497d96bbaca01d358ed7d9d9a76c885e0f3c0f4e482470
4
+ data.tar.gz: 5017356a702d692ec3a08f86de357392a7bd93e4bee6b1fef4096c6433249fcc
5
5
  SHA512:
6
- metadata.gz: 28c754958c46ffee194a411b0fe995c99fb8e9fe7bce78a30113063311d690d591f4ac6d2ef3855384fbc71e46562477de4981173eb938cc5318c5339c72253e
7
- data.tar.gz: fab0ce827f49744c698ff9522aa68dcca1d64c73ae1ba9a453297d2fbb3ca5f65fa9d06a15830cc6e5f4c1e1b301b8ecdb0aead95ed368423f7f728aa3058cf2
6
+ metadata.gz: a8ac36cb673b6f59b5fbd899e5c4117e525504d2d50a5b44bd08904c710b7bec469fa2f3f2c9b1fa4d349f2a0e965c98b394668fd7985b5a38210f93894aeb1b
7
+ data.tar.gz: 9d1b05dda12c29966829fde3eb6f7a42f1f36b29973d5674a637350ffe90e73a345c34c648833cbea21665fe42260ddd224f7272e231299f2993a6ef20eb5250
data/CHANGELOG.md CHANGED
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.3.pre] - 2026-03-08
11
+
12
+ ### Fixed
13
+
14
+ - `scope:` values now merge into the parent partial's kwargs — previously, scope was pushed onto the stack for sub-parts but not merged into the parent's own strict locals, causing `ActionView::StrictLocalsError`
15
+ - `kui_tag` / `appui_tag` now render correctly without a block — self-closing elements (e.g., status dots, icons) were rendering the options hash as text content instead of HTML attributes
16
+
17
+ ## [0.4.2.pre] - 2026-03-08
18
+
19
+ ### Added
20
+
21
+ - `scope:` prop for sharing domain locals from parent components to sub-parts — `appui(:room_card, scope: { room: room })` makes `room:` available to all sub-parts automatically without repeating it on every call. Explicit kwargs on sub-part calls override scope values. One level deep only (parent to its own sub-parts).
22
+
10
23
  ## [0.4.1.pre] - 2026-03-08
11
24
 
12
25
  ### Added
@@ -112,7 +125,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
112
125
  - Lookbook component previews
113
126
  - Bridgetown documentation site
114
127
 
115
- [Unreleased]: https://github.com/steveclarke/kiso/compare/v0.4.1.pre...HEAD
128
+ [Unreleased]: https://github.com/steveclarke/kiso/compare/v0.4.3.pre...HEAD
129
+ [0.4.3.pre]: https://github.com/steveclarke/kiso/releases/tag/v0.4.3.pre
130
+ [0.4.2.pre]: https://github.com/steveclarke/kiso/releases/tag/v0.4.2.pre
116
131
  [0.4.1.pre]: https://github.com/steveclarke/kiso/releases/tag/v0.4.1.pre
117
132
  [0.4.0.pre]: https://github.com/steveclarke/kiso/releases/tag/v0.4.0.pre
118
133
  [0.3.0.pre]: https://github.com/steveclarke/kiso/releases/tag/v0.3.0.pre
@@ -22,6 +22,9 @@ module Kiso
22
22
  # inherit overrides automatically. For self-rendering components, the hash is
23
23
  # also passed as a local so the partial can apply overrides to internally
24
24
  # rendered elements.
25
+ # @param scope [Hash, nil] domain locals shared from parent to sub-parts via context stack.
26
+ # Sub-parts receive scope values as kwargs automatically. Explicit kwargs on sub-part
27
+ # calls override scope values. One level deep only — no ancestor resolution.
25
28
  # @param kwargs [Hash] locals passed to the partial (e.g. +css_classes:+)
26
29
  # @yield optional block for component content
27
30
  # @return [ActiveSupport::SafeBuffer] rendered HTML
@@ -39,13 +42,19 @@ module Kiso
39
42
  # appui(:pricing_card, :header) { "Header" }
40
43
  # end
41
44
  #
45
+ # @example Share domain locals with sub-parts
46
+ # appui(:room_card, scope: { room: room }) do
47
+ # appui(:room_card, :status)
48
+ # appui(:room_card, :meta)
49
+ # end
50
+ #
42
51
  # @example Render a collection
43
52
  # appui(:pricing_card, collection: @plans)
44
- def appui(component, part = nil, collection: nil, ui: nil, **kwargs, &block)
53
+ def appui(component, part = nil, collection: nil, ui: nil, scope: nil, **kwargs, &block)
45
54
  kiso_render_component(
46
55
  component, part,
47
56
  path_prefix: "components",
48
- collection: collection, ui: ui, merge_global_ui: false,
57
+ collection: collection, ui: ui, scope: scope, merge_global_ui: false,
49
58
  **kwargs, &block
50
59
  )
51
60
  end
@@ -16,6 +16,9 @@ module Kiso
16
16
  # inherit overrides automatically. For self-rendering components, the hash is
17
17
  # also passed as a local so the partial can apply overrides to internally
18
18
  # rendered elements.
19
+ # @param scope [Hash, nil] domain locals shared from parent to sub-parts via context stack.
20
+ # Sub-parts receive scope values as kwargs automatically. Explicit kwargs on sub-part
21
+ # calls override scope values. One level deep only — no ancestor resolution.
19
22
  # @param kwargs [Hash] locals passed to the partial (e.g. +color:+, +variant:+, +css_classes:+)
20
23
  # @yield optional block for component content
21
24
  # @return [ActiveSupport::SafeBuffer] rendered HTML
@@ -33,13 +36,18 @@ module Kiso
33
36
  # @example Render an alert with inner element overrides
34
37
  # kui(:alert, icon: "info", ui: { close: "opacity-50" })
35
38
  #
39
+ # @example Share domain locals with sub-parts
40
+ # kui(:card, scope: { project: @project }) do
41
+ # kui(:card, :header) # sub-part receives project: automatically
42
+ # end
43
+ #
36
44
  # @example Render a collection
37
45
  # kui(:badge, collection: @tags)
38
- def kui(component, part = nil, collection: nil, ui: nil, **kwargs, &block)
46
+ def kui(component, part = nil, collection: nil, ui: nil, scope: nil, **kwargs, &block)
39
47
  kiso_render_component(
40
48
  component, part,
41
49
  path_prefix: "kiso/components",
42
- collection: collection, ui: ui, merge_global_ui: true,
50
+ collection: collection, ui: ui, scope: scope, merge_global_ui: true,
43
51
  **kwargs, &block
44
52
  )
45
53
  end
@@ -94,10 +102,17 @@ module Kiso
94
102
  # yield
95
103
  # end
96
104
  def kui_tag(tag, theme:, slot:, css_classes: "", variants: {}, **component_options, &block)
97
- content_tag(tag,
105
+ html_options = {
98
106
  class: theme.render(**variants, class: css_classes),
99
107
  data: kiso_prepare_options(component_options, slot: slot),
100
- **component_options, &block)
108
+ **component_options
109
+ }
110
+
111
+ if block
112
+ content_tag(tag, html_options, &block)
113
+ else
114
+ content_tag(tag, nil, html_options)
115
+ end
101
116
  end
102
117
 
103
118
  private
@@ -109,11 +124,12 @@ module Kiso
109
124
  # @param path_prefix [String] partial path prefix (e.g. "kiso/components" or "components")
110
125
  # @param collection [Array, nil] renders the partial once per item when present
111
126
  # @param ui [Hash, nil] per-slot class overrides
127
+ # @param scope [Hash, nil] domain locals shared from parent to sub-parts
112
128
  # @param merge_global_ui [Boolean] whether to merge global config ui layer
113
129
  # @param kwargs [Hash] locals passed to the partial
114
130
  # @param block [Proc] optional block for component content
115
131
  # @return [ActiveSupport::SafeBuffer] rendered HTML
116
- def kiso_render_component(component, part, path_prefix:, collection:, ui:, merge_global_ui: true, **kwargs, &block)
132
+ def kiso_render_component(component, part, path_prefix:, collection:, ui:, scope:, merge_global_ui: true, **kwargs, &block)
117
133
  path = if part
118
134
  "#{path_prefix}/#{component}/#{part}"
119
135
  else
@@ -131,6 +147,10 @@ module Kiso
131
147
  block ||= proc {}
132
148
 
133
149
  if part
150
+ # Sub-part: merge scope from parent context (scope values first, explicit kwargs win)
151
+ parent_scope = kiso_current_scope(component)
152
+ kwargs = parent_scope.merge(kwargs) if parent_scope.present?
153
+
134
154
  # Sub-part: merge slot override from parent's ui context
135
155
  parent_ui = kiso_current_ui(component)
136
156
  if (slot_classes = parent_ui[part].presence)
@@ -154,9 +174,15 @@ module Kiso
154
174
  ui || {}
155
175
  end
156
176
  has_ui = merged_ui.present?
177
+ has_scope = scope.present?
157
178
 
158
179
  # Push context for composed sub-parts to read (skip when empty)
159
180
  kiso_push_ui_context(component, merged_ui) if has_ui
181
+ kiso_push_scope(component, scope) if has_scope
182
+
183
+ # Merge scope into parent kwargs so the parent partial receives
184
+ # scope values as strict locals (scope as defaults, explicit kwargs win)
185
+ kwargs = scope.merge(kwargs) if has_scope
160
186
  begin
161
187
  locals = has_ui ? kwargs.merge(ui: merged_ui) : kwargs
162
188
 
@@ -167,6 +193,7 @@ module Kiso
167
193
  end
168
194
  ensure
169
195
  kiso_pop_ui_context(component) if has_ui
196
+ kiso_pop_scope(component) if has_scope
170
197
  end
171
198
  end
172
199
  end
@@ -1,17 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kiso
4
- # Manages a request-scoped context stack for per-slot +ui:+ overrides.
4
+ # Manages request-scoped context stacks for component communication.
5
5
  #
6
- # This is ERB's equivalent of Vue's provide/inject pattern. When a parent
7
- # component is rendered with +ui:+, the hash is pushed onto a stack.
8
- # Sub-parts rendered inside the parent's block read their slot override
9
- # from the stack automatically.
6
+ # This is ERB's equivalent of Vue's provide/inject pattern. Two stacks:
7
+ #
8
+ # - **ui:** per-slot CSS class overrides. When a parent component is
9
+ # rendered with +ui:+, the hash is pushed onto a stack. Sub-parts read
10
+ # their slot override automatically.
11
+ # - **scope:** — domain locals shared from parent to sub-parts. When a
12
+ # parent is rendered with +scope:+, the hash is pushed onto a stack.
13
+ # Sub-parts receive scope values as kwargs, with explicit kwargs
14
+ # taking priority. One level deep only — no ancestor resolution.
10
15
  #
11
16
  # Thread-safe because Rails creates a fresh view context (and therefore
12
17
  # fresh instance variables) per request.
13
18
  #
14
- # @example How the stack flows
19
+ # @example ui: stack flow
15
20
  # # Parent pushes:
16
21
  # kiso_push_ui_context(:card, { header: "p-8", title: "text-xl" })
17
22
  #
@@ -21,6 +26,16 @@ module Kiso
21
26
  # # After parent renders:
22
27
  # kiso_pop_ui_context(:card)
23
28
  #
29
+ # @example scope: stack flow
30
+ # # Parent pushes:
31
+ # kiso_push_scope(:room_card, { room: room })
32
+ #
33
+ # # Sub-part reads (merged into kwargs before render):
34
+ # kiso_current_scope(:room_card) #=> { room: room }
35
+ #
36
+ # # After parent renders:
37
+ # kiso_pop_scope(:room_card)
38
+ #
24
39
  # @see ComponentHelper#kui
25
40
  module UiContextHelper
26
41
  # Push a ui hash onto the context stack for a component.
@@ -49,11 +64,45 @@ module Kiso
49
64
  kiso_ui_stack.dig(component, -1) || {}
50
65
  end
51
66
 
67
+ # Push a scope hash onto the context stack for a component.
68
+ #
69
+ # Scope shares domain locals from a parent component with its sub-parts
70
+ # so callers don't have to repeat the same locals on every sub-part call.
71
+ #
72
+ # @param component [Symbol] the component name (e.g. +:room_card+)
73
+ # @param scope [Hash] domain locals to share with sub-parts
74
+ # @return [void]
75
+ def kiso_push_scope(component, scope)
76
+ kiso_scope_stack[component] ||= []
77
+ kiso_scope_stack[component].push(scope || {})
78
+ end
79
+
80
+ # Pop the most recent scope hash for a component.
81
+ #
82
+ # @param component [Symbol] the component name
83
+ # @return [Hash, nil] the popped scope hash
84
+ def kiso_pop_scope(component)
85
+ kiso_scope_stack[component]&.pop
86
+ end
87
+
88
+ # Read the current scope hash for a component (top of stack).
89
+ #
90
+ # @param component [Symbol] the component name
91
+ # @return [Hash] the current scope, or empty hash
92
+ def kiso_current_scope(component)
93
+ kiso_scope_stack.dig(component, -1) || {}
94
+ end
95
+
52
96
  private
53
97
 
54
- # @return [Hash{Symbol => Array<Hash>}] per-component stacks
98
+ # @return [Hash{Symbol => Array<Hash>}] per-component ui stacks
55
99
  def kiso_ui_stack
56
100
  @kiso_ui_stack ||= {}
57
101
  end
102
+
103
+ # @return [Hash{Symbol => Array<Hash>}] per-component scope stacks
104
+ def kiso_scope_stack
105
+ @kiso_scope_stack ||= {}
106
+ end
58
107
  end
59
108
  end
data/lib/kiso/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Kiso
4
4
  # @return [String] the current gem version
5
- VERSION = "0.4.1.pre"
5
+ VERSION = "0.4.3.pre"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kiso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1.pre
4
+ version: 0.4.3.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Clarke