@ea-lab/reactive-json-docs 0.1.10 → 0.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ea-lab/reactive-json-docs",
3
- "version": "0.1.10",
3
+ "version": "0.2.0",
4
4
  "description": "Complete documentation for Reactive-JSON - Components, examples and LLM-parsable guides",
5
5
  "main": "public/rjbuild/docs/index.yaml",
6
6
  "files": [
@@ -26,7 +26,7 @@
26
26
  "private": false,
27
27
  "devDependencies": {
28
28
  "@craco/craco": "^7.1.0",
29
- "@ea-lab/reactive-json": "^0.0.44",
29
+ "@ea-lab/reactive-json": "^0.1.0",
30
30
  "@ea-lab/reactive-json-chartjs": "^0.0.23",
31
31
  "@npmcli/fs": "^4.0.0",
32
32
  "@reduxjs/toolkit": "^2.6.1",
@@ -34,7 +34,7 @@ renderView:
34
34
  export const YourComponent = () => {
35
35
 
36
36
  const rjRootProps = {
37
- // Set your own props to rjRootProps such as dataUrl.
37
+ // Set your own props to rjRootProps such as rjBuildUrl.
38
38
  // ...
39
39
  };
40
40
 
@@ -4,24 +4,319 @@
4
4
 
5
5
  The `ReactiveJsonSubroot` component allows you to render a new Reactive-JSON root inside an existing application. It is useful for embedding a sub-application, isolating a part of the data tree, or rendering a separate rjbuild with its own options.
6
6
 
7
+ With the `sharedUpdates` feature, the component can also propagate data changes back to the parent, enabling seamless communication between parent and subroot when working with shared data references.
8
+
7
9
  ## Properties
8
- - `rjOptions` (object, required): Options to pass to the subroot (such as `dataUrl`, `data`, `renderView`, etc.)
9
- - Other properties are passed to the underlying `ReactiveJsonRoot`
10
+ - `rjOptions` (object, required): Options to pass to the subroot - accepts **all** `ReactiveJsonRoot` properties including:
11
+ - `rjBuildUrl`: URL to load the RjBuild from.
12
+ - `rjBuildFetchMethod`: HTTP method ("GET" or "POST").
13
+ - `headersForRjBuild`: Headers for the request.
14
+ - `dataOverride`: Override data for the loaded/defined RjBuild.
15
+ - `maybeRawAppRjBuild`: Inline RjBuild content (string or object) containing:
16
+ - `renderView`: View definition.
17
+ - `templates`: Template definitions.
18
+ - `data`: Initial data.
19
+ - `debugMode`: Enable debug mode and related wrapper components.
20
+ - `sharedUpdates` (boolean, optional): Enable upstream data propagation to parent (default: false).
21
+ - `dataOverrideEvaluationDepth` (number, optional): Special evaluation depth for dataOverride property.
22
+ - `actions` (array, optional): Action components to apply (passed to `ActionDependant` wrapper).
23
+ - Other standard component properties (e.g., `attributes`) are passed to the `ActionDependant` wrapper.
10
24
 
11
25
  ## Behavior
12
- - Renders a new `ReactiveJsonRoot` with the provided options
13
- - The subroot is isolated from the parent for data, templates, and rendering
14
- - Plugins from the parent are reused in the subroot
15
- - If `rjOptions` is not a valid object, nothing is rendered
26
+ - Renders a new `ReactiveJsonRoot` with the provided options.
27
+ - The subroot is typically isolated from the parent for data, templates, and rendering*.
28
+ - Plugins from the parent are automatically reused in the subroot.
29
+ - All properties in `rjOptions` are evaluated with template values using `evaluateTemplateValueCollection()`.
30
+ - If `rjOptions` is not a valid object, nothing is rendered.
31
+
32
+ *_Note: Data isolation is bypassed when `sharedUpdates: true` is enabled, allowing the subroot to propagate data changes back to the parent. Templates and rendering contexts remain isolated._
33
+
34
+ ## Shared Updates Feature
35
+
36
+ When `sharedUpdates: true` is enabled, the component automatically detects template references in `dataOverride` and creates update callbacks to propagate changes back to the parent.
37
+
38
+ **Data flow**: Parent data flows to subroot via `dataOverride` → Subroot changes flow back to parent via `sharedUpdates`
39
+
40
+ ### How it works
41
+ 1. **Automatic analysis**: The system analyzes `dataOverride` to detect references (`~~.`, `~.`, `~>`) to parent data
42
+ 2. **Callback creation**: For each detected reference, an update callback is created
43
+ 3. **Update interception**: When the subroot modifies data, the system checks if it corresponds to a parent reference
44
+ 4. **Propagation**: If so, the update is propagated to the parent instead of being applied locally
45
+
46
+ **Important**: Only data changes are shared. Templates, rendering contexts, and component state remain isolated between parent and subroot.
47
+
48
+ ### Advantages
49
+ 1. **Automatic synchronization**: Data remains consistent between parent and subroot
50
+ 2. **Simplicity**: No need to manually manage update callbacks
51
+ 3. **Performance**: Avoids unnecessary re-renders by propagating directly to the right level
52
+ 4. **Flexibility**: Supports different referencing patterns (~~., ~., ~>) and arrays containing references
53
+
54
+ ### Supported reference types
55
+ - `~~.parentData` - Global data references.
56
+ - `~.localData` - Local template context references.
57
+ - `~>key.data` - Hierarchical references.
58
+ - Arrays and nested objects containing references.
59
+
60
+ ### Supported vs Unsupported Cases
61
+
62
+ #### ✅ Supported cases
63
+
64
+ ##### 1. Direct reference
65
+ ```yaml
66
+ dataOverride: ~~.user
67
+ # Modifications in the subroot propagate to "user" in the parent
68
+ ```
69
+
70
+ ##### 2. Object mapping with references
71
+ ```yaml
72
+ dataOverride:
73
+ userInfo: ~~.user
74
+ settings: ~~.config
75
+ # Modifications to "userInfo" propagate to "user" in the parent
76
+ # Modifications to "settings" propagate to "config" in the parent
77
+ ```
78
+
79
+ ##### 3. Local references
80
+ ```yaml
81
+ dataOverride: ~.localData
82
+ # Modifications propagate to the local template context
83
+ ```
84
+
85
+ ##### 4. Hierarchical references
86
+ ```yaml
87
+ dataOverride: ~>key.someData
88
+ # Modifications propagate up the template hierarchy
89
+ ```
90
+
91
+ ##### 5. Arrays in dataOverride
92
+ ```yaml
93
+ dataOverride:
94
+ - ~~.firstItem
95
+ - ~~.secondItem
96
+ # Array items with template references are properly handled
97
+ ```
98
+
99
+ #### ❌ Unsupported cases
100
+
101
+ ##### Nested references in data
102
+ ```yaml
103
+ dataOverride:
104
+ someProperty: ~~.user
105
+ data:
106
+ someProperty: ~~.anotherProperty # Not supported
107
+ ```
108
+
109
+ ### Configuration example
110
+ ```yaml
111
+ - type: ReactiveJsonSubroot
112
+ sharedUpdates: true # Enable propagation.
113
+ rjOptions:
114
+ # Option 1: Load from URL with data override.
115
+ rjBuildUrl: "/api/user-form.yaml"
116
+ dataOverride: ~~.user
117
+ headersForRjBuild:
118
+ Authorization: ~~.authToken
119
+
120
+ # Option 2: Inline definition.
121
+ # dataOverride: ~~.user
122
+ # maybeRawAppRjBuild:
123
+ # renderView:
124
+ # form:
125
+ # - type: TextField
126
+ # dataLocation: ~.name
127
+ ```
128
+
129
+ ## Examples
130
+
131
+ ### Basic subroot from URL
132
+ This example demonstrates the simplest use case: loading and rendering a separate RjBuild file as an isolated subroot. No data sharing occurs between parent and subroot.
16
133
 
17
- ## Example
18
134
  ```yaml
19
135
  renderView:
20
136
  - type: ReactiveJsonSubroot
21
137
  rjOptions:
22
- dataUrl: "/rjs-build/home.yaml"
138
+ rjBuildUrl: "/rjs-build/home.yaml"
139
+ ```
140
+
141
+ ### Inline definition with shared updates
142
+ This example shows how to create an editable form where changes in the subroot automatically update the parent display. The key feature here is `sharedUpdates: true` which enables data synchronization between the form fields and the parent data display.
143
+
144
+ ```yaml
145
+ data:
146
+ user:
147
+ name: "John"
148
+ email: "john@example.com"
149
+
150
+ renderView:
151
+ userDisplay:
152
+ - type: p
153
+ content: ["Name: ", ~~.user.name] # This displays the current user name.
154
+
155
+ editForm:
156
+ - type: ReactiveJsonSubroot
157
+ sharedUpdates: true # Required to update userDisplay when form changes.
158
+ rjOptions:
159
+ dataOverride: ~~.user
160
+ maybeRawAppRjBuild:
161
+ renderView:
162
+ form:
163
+ - type: TextField
164
+ label: "Name"
165
+ dataLocation: ~.name # Changes propagate to ~~.user.name.
166
+ - type: TextField
167
+ label: "Email"
168
+ dataLocation: ~.email # Changes propagate to ~~.user.email.
169
+ ```
170
+
171
+ ### Multi-section configuration
172
+ This example demonstrates how to map different parts of the parent data to different sections within the subroot. The `dataOverride` object creates custom mappings (`userProfile` and `userSettings`) that allow the subroot to work with reorganized data while still propagating changes back to their original locations in the parent.
173
+
174
+ ```yaml
175
+ data:
176
+ profile: { name: "John", age: 30 }
177
+ settings: { theme: "dark", lang: "en" }
178
+
179
+ renderView:
180
+ editor:
181
+ - type: ReactiveJsonSubroot
182
+ sharedUpdates: true
183
+ rjOptions:
184
+ dataOverride:
185
+ userProfile: ~~.profile
186
+ userSettings: ~~.settings
187
+ maybeRawAppRjBuild:
188
+ renderView:
189
+ sections:
190
+ - type: TextField
191
+ label: "Name"
192
+ dataLocation: ~.userProfile.name
193
+ - type: TextField
194
+ label: "Theme"
195
+ dataLocation: ~.userSettings.theme
196
+ ```
197
+
198
+ ### Loading from URL with authentication
199
+ This example shows how to load an external RjBuild file while providing authentication headers and data overrides. The external form loaded from the URL will receive the user profile data and any changes made will be propagated back to the parent thanks to `sharedUpdates`. This pattern is useful for reusable form components that need to work with dynamic data and authentication.
200
+
201
+ ```yaml
202
+ data:
203
+ user:
204
+ profile: { name: "John", role: "admin" }
205
+ authToken: "abc123"
206
+
207
+ renderView:
208
+ profileEditor:
209
+ - type: ReactiveJsonSubroot
210
+ sharedUpdates: true
211
+ rjOptions:
212
+ rjBuildUrl: "/forms/user-profile-form.yaml"
213
+ dataOverride: ~~.user.profile
214
+ headersForRjBuild:
215
+ Authorization: ["Bearer ", ~~.authToken]
216
+ ```
217
+
218
+ ### Array with references
219
+ This example demonstrates how to work with arrays in `dataOverride` where each array item is mapped to different parts of the parent data. The subroot can edit individual array items and changes will be propagated back to their respective locations in the parent array.
220
+
221
+ ```yaml
222
+ data:
223
+ items: [
224
+ { title: "Item 1", active: true },
225
+ { title: "Item 2", active: false }
226
+ ]
227
+
228
+ renderView:
229
+ listEditor:
230
+ - type: ReactiveJsonSubroot
231
+ sharedUpdates: true
232
+ rjOptions:
233
+ dataOverride:
234
+ - ~~.items.0
235
+ - ~~.items.1
236
+ maybeRawAppRjBuild:
237
+ renderView:
238
+ editors:
239
+ - type: TextField
240
+ label: "First item title"
241
+ dataLocation: ~.0.title
242
+ - type: TextField
243
+ label: "Second item title"
244
+ dataLocation: ~.1.title
23
245
  ```
24
246
 
247
+ ## Technical Details
248
+
249
+ - Uses `dataLocationToPath()` from the template system for consistent path resolution.
250
+ - Supports all template reference types: `~~.`, `~.`, and `~>`.
251
+ - Handles arrays and nested objects in `dataOverride` when analyzing references.
252
+ - Falls back to local updates if upstream propagation fails.
253
+ - All `rjOptions` properties are evaluated with `evaluateTemplateValueCollection()`.
254
+ - Template evaluation respects the `dataOverrideEvaluationDepth` property for special cases.
255
+
256
+ ## Debugging
257
+
258
+ For troubleshooting shared updates:
259
+
260
+ 1. **Browser console**: Propagation errors are logged with descriptive messages.
261
+ 2. **dataOverride structure**: Ensure template references are valid and exist in parent data.
262
+ 3. **Data context**: Verify that referenced data exists in the expected locations.
263
+ 4. **Data paths**: Confirm that `dataLocation` values in the subroot match the dataOverride structure.
264
+
265
+ ## Caveat: Data Loss Risk with sharedUpdates
266
+
267
+ **⚠️ Important Warning**: When using `sharedUpdates`, there is a risk of data loss in specific scenarios.
268
+
269
+ ### The Problem
270
+ If the subroot modifies data that is **not** covered by a template reference from the parent's `dataOverride`, and subsequently the parent re-renders the subroot, the local modifications will be **lost**.
271
+
272
+ ### When This Happens
273
+ 1. **Subroot modifies local data**: The subroot changes a value that doesn't correspond to any template reference in the parent's `dataOverride`.
274
+ 2. **Parent re-renders**: This can occur when:
275
+ - The parent updates itself for any reason.
276
+ - A subroot action triggers an upstream update that causes the parent to re-render.
277
+ 3. **Data loss**: The parent's `dataOverride` completely overwrites the subroot's data, erasing local modifications.
278
+
279
+ ### Example Scenario
280
+ ```yaml
281
+ # Parent has this data structure
282
+ data:
283
+ user: { name: "John", email: "john@example.com" }
284
+
285
+ # Subroot configured like this
286
+ - type: ReactiveJsonSubroot
287
+ sharedUpdates: true
288
+ rjOptions:
289
+ dataOverride: ~~.user # Only user data is referenced
290
+ maybeRawAppRjBuild:
291
+ renderView:
292
+ - type: TextField
293
+ label: "Name"
294
+ dataLocation: ~.name # ✅ Safe - covered by ~~.user
295
+ - type: TextField
296
+ label: "Temporary Note"
297
+ dataLocation: ~.tempNote # ⚠️ Risk - NOT in parent data
298
+ ```
299
+
300
+ In this example, if the user types in "Temporary Note" and then any parent update occurs, the `tempNote` value will be lost because it's not part of the original `~~.user` data.
301
+
302
+ ### Best Practices to Avoid Data Loss
303
+ 1. **Map all needed data**: Ensure all data fields the subroot might modify are included in the parent's data structure.
304
+ 2. **Use complete dataOverride**: Include all necessary data paths in your `dataOverride` mapping.
305
+ 3. **Avoid local-only modifications**: Design your data flow so that all user inputs correspond to parent data.
306
+ 4. **Consider alternatives**: For truly local data, consider using component state or separate data management instead of `sharedUpdates`.
307
+
25
308
  ## Limitations
26
- - The subroot is isolated from the parent; data and state are not shared
27
- - No built-in communication between parent and subroot (except via plugins or explicit data passing)
309
+ - **Data loss risk**: Local modifications in subroot may be lost when parent re-renders (see Caveat section above).
310
+ - **Nested references in data**: References within references are not supported (e.g., `dataOverride: { prop: "~~.user" }` where data contains `{ prop: "~~.other" }`).
311
+ - **Circular references**: May cause infinite loops if data structures reference each other.
312
+ - **Template isolation**: Templates and rendering contexts remain isolated even with `sharedUpdates`.
313
+ - **Data isolation by default**: Without `sharedUpdates`, data changes in the subroot do not affect the parent.
314
+ - **One-way shared updates**: `sharedUpdates` only propagates changes from subroot to parent, not vice versa.
315
+ - **Backward compatibility**: `sharedUpdates` is disabled by default to maintain existing behavior.
316
+
317
+ ## Changelog
318
+
319
+ ### reactive-json@0.1.0
320
+ - **New**: `sharedUpdates` feature - enables automatic data synchronization between subroot and parent
321
+ - **New**: `dataOverride` property - allows complete data replacement in subroot with support for template references
322
+ - **New**: Automatic analysis of template references in `dataOverride` for shared updates propagation
@@ -5,15 +5,88 @@ renderView:
5
5
 
6
6
  The `ReactiveJsonSubroot` component allows you to render a new Reactive-JSON root inside an existing application. It is useful for embedding a sub-application, isolating a part of the data tree, or rendering a separate rjbuild with its own options.
7
7
 
8
+ With the `sharedUpdates` feature, the component can also propagate data changes back to the parent, enabling seamless communication between parent and subroot when working with shared data references.
9
+
8
10
  ## Properties
9
- - `rjOptions` (object, required): Options to pass to the subroot (such as `dataUrl`, `data`, `renderView`, etc.)
10
- - Other properties are passed to the underlying `ReactiveJsonRoot`
11
+ - `rjOptions` (object, required): Options to pass to the subroot - accepts **all** `ReactiveJsonRoot` properties.
12
+ - Direct properties: `rjBuildUrl`, `dataOverride`, `headersForRjBuild`, `debugMode`, etc.
13
+ - For inline content: use `maybeRawAppRjBuild` containing `renderView`, `templates`, `data`.
14
+ - `sharedUpdates` (boolean, optional): Enable upstream data propagation to parent (default: false).
15
+ - `dataOverrideEvaluationDepth` (number, optional): Special evaluation depth for dataOverride property.
16
+ - Other properties are passed to the underlying `ActionDependant` wrapper.
11
17
 
12
18
  ## Behavior
13
- - Renders a new `ReactiveJsonRoot` with the provided options
14
- - The subroot is isolated from the parent for data, templates, and rendering
15
- - Plugins from the parent are reused in the subroot
16
- - If `rjOptions` is not a valid object, nothing is rendered
19
+ - Renders a new `ReactiveJsonRoot` with the provided options.
20
+ - The subroot is typically isolated from the parent for data, templates, and rendering¹.
21
+ - Plugins from the parent are automatically reused in the subroot.
22
+ - All properties in `rjOptions` are evaluated with template values.
23
+ - If `rjOptions` is not a valid object, nothing is rendered.
24
+
25
+ ¹Note: Data isolation is bypassed when `sharedUpdates: true` is enabled, allowing the subroot to propagate data changes back to the parent. Templates and rendering contexts remain isolated.
26
+
27
+ ## Shared Updates Feature
28
+ When `sharedUpdates: true` is enabled, the component automatically detects template references in `dataOverride` and creates update callbacks to propagate changes back to the parent.
29
+
30
+ ### How it works
31
+ 1. **Automatic analysis**: The system analyzes `dataOverride` to detect references (`~~.`, `~.`, `~>`) to parent data
32
+ 2. **Callback creation**: For each detected reference, an update callback is created
33
+ 3. **Update interception**: When the subroot modifies data, the system checks if it corresponds to a parent reference
34
+ 4. **Propagation**: If so, the update is propagated to the parent instead of being applied locally
35
+
36
+ ### Advantages
37
+ 1. **Automatic synchronization**: Data remains consistent between parent and subroot
38
+ 2. **Simplicity**: No need to manually manage update callbacks
39
+ 3. **Performance**: Avoids unnecessary re-renders by propagating directly to the right level
40
+ 4. **Flexibility**: Supports different referencing patterns (~~., ~., ~>) and arrays containing references
41
+
42
+ ### Supported vs Unsupported Cases
43
+
44
+ #### ✅ Supported cases
45
+
46
+ ##### 1. Direct reference
47
+ ```yaml
48
+ dataOverride: ~~.user
49
+ # Modifications in the subroot propagate to "user" in the parent
50
+ ```
51
+
52
+ ##### 2. Object mapping with references
53
+ ```yaml
54
+ dataOverride:
55
+ userInfo: ~~.user
56
+ settings: ~~.config
57
+ # Modifications to "userInfo" propagate to "user" in the parent
58
+ # Modifications to "settings" propagate to "config" in the parent
59
+ ```
60
+
61
+ ##### 3. Local references
62
+ ```yaml
63
+ dataOverride: ~.localData
64
+ # Modifications propagate to the local template context
65
+ ```
66
+
67
+ ##### 4. Hierarchical references
68
+ ```yaml
69
+ dataOverride: ~>key.someData
70
+ # Modifications propagate up the template hierarchy
71
+ ```
72
+
73
+ ##### 5. Arrays in dataOverride
74
+ ```yaml
75
+ dataOverride:
76
+ - ~~.firstItem
77
+ - ~~.secondItem
78
+ # Array items with template references are properly handled
79
+ ```
80
+
81
+ #### ❌ Unsupported cases
82
+
83
+ ##### Nested references in data
84
+ ```yaml
85
+ dataOverride:
86
+ someProperty: ~~.user
87
+ data:
88
+ someProperty: ~~.anotherProperty # Not supported
89
+ ```
17
90
 
18
91
  - type: RjBuildDescriber
19
92
  title: Example
@@ -22,16 +95,16 @@ renderView:
22
95
  renderView:
23
96
  - type: ReactiveJsonSubroot
24
97
  rjOptions:
25
- dataUrl: "/rjbuild/component/message.yaml"
98
+ rjBuildUrl: "/rjbuild/component/message.yaml"
26
99
 
27
100
  - type: RjBuildDescriber
28
101
  title: Example with inline JSON data
29
- description: This example demonstrates two approaches for using ReactiveJsonSubroot with inline data. The first shows passing JSON data directly as a string via maybeRawAppData. The second shows loading subroot options dynamically from the main RjBuild's data using template interpolation. Both approaches are useful for embedding sub-applications without external files.
102
+ description: This example demonstrates two approaches for using ReactiveJsonSubroot with inline data. The first shows passing JSON data directly as a string via maybeRawAppRjBuild. The second shows loading subroot options dynamically from the main RjBuild's data using template interpolation. Both approaches are useful for embedding sub-applications without external files.
30
103
  toDescribe:
31
104
  renderView:
32
105
  - type: ReactiveJsonSubroot
33
106
  rjOptions:
34
- maybeRawAppData: '{"data":{"userName":"Alice","messageCount":3},"renderView":[{"type":"div","attributes":{"style":{"padding":"1rem","border":"1px solid #ddd","borderRadius":"8px","backgroundColor":"#f9f9f9"}},"content":[{"type":"h3","content":"~~.userName"},{"type":"p","content":["You have ","~~.messageCount"," new messages."]},{"type":"button","content":"Mark as read","attributes":{"style":{"backgroundColor":"#007bff","color":"white","border":"none","padding":"0.5rem 1rem","borderRadius":"4px"}}}]}]}'
107
+ maybeRawAppRjBuild: '{"data":{"userName":"Alice","messageCount":3},"renderView":[{"type":"div","attributes":{"style":{"padding":"1rem","border":"1px solid #ddd","borderRadius":"8px","backgroundColor":"#f9f9f9"}},"content":[{"type":"h3","content":"~~.userName"},{"type":"p","content":["You have ","~~.messageCount"," new messages."]},{"type":"button","content":"Mark as read","attributes":{"style":{"backgroundColor":"#007bff","color":"white","border":"none","padding":"0.5rem 1rem","borderRadius":"4px"}}}]}]}'
35
108
 
36
109
  - type: hr
37
110
 
@@ -39,13 +112,255 @@ renderView:
39
112
  rjOptions: ~~.subrootToLoad
40
113
  data:
41
114
  subrootToLoad:
42
- maybeRawAppData:
115
+ maybeRawAppRjBuild:
43
116
  renderView:
44
117
  - type: div
45
118
  content: This second subroot is loaded from the "data" key of the main root.
46
119
 
120
+ - type: RjBuildDescriber
121
+ title: Example with Shared Updates
122
+ description: This example demonstrates the `sharedUpdates` feature where changes in the subroot automatically propagate back to the parent data. Notice how modifying the text field in the subroot will update the display in the parent above it.
123
+ toDescribe:
124
+ data:
125
+ user:
126
+ name: "John Doe"
127
+ email: "john@example.com"
128
+ renderView:
129
+ - type: div
130
+ attributes:
131
+ style:
132
+ padding: "1rem"
133
+ border: "2px solid #007bff"
134
+ borderRadius: "8px"
135
+ backgroundColor: "#f8f9fa"
136
+ marginBottom: "1rem"
137
+ content:
138
+ - type: h4
139
+ content: "Parent Data Display"
140
+ - type: p
141
+ content: ["Name: ", ~~.user.name]
142
+ - type: p
143
+ content: ["Email: ", ~~.user.email]
144
+
145
+ - type: ReactiveJsonSubroot
146
+ sharedUpdates: true
147
+ rjOptions:
148
+ dataOverride: ~~.user
149
+ maybeRawAppRjBuild:
150
+ renderView:
151
+ - type: div
152
+ attributes:
153
+ style:
154
+ padding: "1rem"
155
+ border: "2px solid #28a745"
156
+ borderRadius: "8px"
157
+ backgroundColor: "#e8f5e9"
158
+ content:
159
+ - type: h4
160
+ content: "Subroot Editor (with sharedUpdates)"
161
+ - type: TextField
162
+ label: "Name"
163
+ dataLocation: ~.name
164
+ - type: TextField
165
+ label: "Email"
166
+ dataLocation: ~.email
167
+ - type: p
168
+ attributes:
169
+ style:
170
+ fontSize: "0.9em"
171
+ color: "#666"
172
+ marginTop: "0.5rem"
173
+ content: "Changes here automatically update the parent data above ↑"
174
+
175
+ - type: RjBuildDescriber
176
+ title: Example with Multi-Section Configuration
177
+ description: This example shows how `sharedUpdates` works with complex data mappings where different parts of the parent data are mapped to different sections in the subroot.
178
+ toDescribe:
179
+ data:
180
+ profile:
181
+ name: "Alice Smith"
182
+ age: 28
183
+ settings:
184
+ theme: "dark"
185
+ language: "en"
186
+ renderView:
187
+ - type: div
188
+ attributes:
189
+ style:
190
+ display: "grid"
191
+ gridTemplateColumns: "1fr 1fr"
192
+ gap: "1rem"
193
+ marginBottom: "1rem"
194
+ content:
195
+ - type: div
196
+ attributes:
197
+ style:
198
+ padding: "1rem"
199
+ border: "1px solid #ddd"
200
+ borderRadius: "4px"
201
+ backgroundColor: "#f5f5f5"
202
+ content:
203
+ - type: h5
204
+ content: "Profile Data"
205
+ - type: p
206
+ content: ["Name: ", ~~.profile.name]
207
+ - type: p
208
+ content: ["Age: ", ~~.profile.age]
209
+ - type: div
210
+ attributes:
211
+ style:
212
+ padding: "1rem"
213
+ border: "1px solid #ddd"
214
+ borderRadius: "4px"
215
+ backgroundColor: "#f5f5f5"
216
+ content:
217
+ - type: h5
218
+ content: "Settings Data"
219
+ - type: p
220
+ content: ["Theme: ", ~~.settings.theme]
221
+ - type: p
222
+ content: ["Language: ", ~~.settings.language]
223
+
224
+ - type: ReactiveJsonSubroot
225
+ sharedUpdates: true
226
+ rjOptions:
227
+ dataOverride:
228
+ userProfile: ~~.profile
229
+ userSettings: ~~.settings
230
+ maybeRawAppRjBuild:
231
+ renderView:
232
+ - type: div
233
+ attributes:
234
+ style:
235
+ display: "grid"
236
+ gridTemplateColumns: "1fr 1fr"
237
+ gap: "1rem"
238
+ padding: "1rem"
239
+ border: "2px solid #17a2b8"
240
+ borderRadius: "8px"
241
+ backgroundColor: "#e3f2fd"
242
+ content:
243
+ - type: div
244
+ content:
245
+ - type: h5
246
+ content: "Edit Profile"
247
+ - type: TextField
248
+ label: "Name"
249
+ dataLocation: ~.userProfile.name
250
+ - type: NumberField
251
+ label: "Age"
252
+ dataLocation: ~.userProfile.age
253
+ - type: div
254
+ content:
255
+ - type: h5
256
+ content: "Edit Settings"
257
+ - type: TextField
258
+ label: "Theme"
259
+ dataLocation: ~.userSettings.theme
260
+ - type: TextField
261
+ label: "Language"
262
+ dataLocation: ~.userSettings.language
263
+
264
+ - type: RjBuildDescriber
265
+ title: Example with Array References
266
+ description: This example demonstrates how to work with arrays in `dataOverride` where each array item is mapped to different parts of the parent data. The subroot can edit individual array items and changes will be propagated back to their respective locations in the parent array.
267
+ toDescribe:
268
+ data:
269
+ items:
270
+ - title: "Task 1"
271
+ completed: false
272
+ - title: "Task 2"
273
+ completed: true
274
+ renderView:
275
+ - type: div
276
+ attributes:
277
+ style:
278
+ padding: "1rem"
279
+ border: "1px solid #ddd"
280
+ borderRadius: "4px"
281
+ backgroundColor: "#f9f9f9"
282
+ marginBottom: "1rem"
283
+ content:
284
+ - type: h4
285
+ content: "Parent Items Display"
286
+ - type: p
287
+ content: ["Item 1: ", ~~.items.0.title, " (", ~~.items.0.completed, ")"]
288
+ - type: p
289
+ content: ["Item 2: ", ~~.items.1.title, " (", ~~.items.1.completed, ")"]
290
+
291
+ - type: ReactiveJsonSubroot
292
+ sharedUpdates: true
293
+ rjOptions:
294
+ dataOverride:
295
+ - ~~.items.0
296
+ - ~~.items.1
297
+ maybeRawAppRjBuild:
298
+ renderView:
299
+ - type: div
300
+ attributes:
301
+ style:
302
+ padding: "1rem"
303
+ border: "2px solid #ffc107"
304
+ borderRadius: "8px"
305
+ backgroundColor: "#fff3cd"
306
+ content:
307
+ - type: h4
308
+ content: "Array Items Editor"
309
+ - type: div
310
+ content:
311
+ - type: h5
312
+ content: "First Item"
313
+ - type: TextField
314
+ label: "Title"
315
+ dataLocation: ~.0.title
316
+ - type: CheckBoxField
317
+ label: "Completed"
318
+ dataLocation: ~.0.completed
319
+ - type: div
320
+ content:
321
+ - type: h5
322
+ content: "Second Item"
323
+ - type: TextField
324
+ label: "Title"
325
+ dataLocation: ~.1.title
326
+ - type: CheckBoxField
327
+ label: "Completed"
328
+ dataLocation: ~.1.completed
329
+
47
330
  - type: Markdown
48
331
  content: |
332
+ ## Caveat: Data Loss Risk with sharedUpdates
333
+
334
+ **⚠️ Important Warning**: When using `sharedUpdates`, there is a risk of data loss in specific scenarios.
335
+
336
+ ### The Problem
337
+ If the subroot modifies data that is **not** covered by a template reference from the parent's `dataOverride`, and subsequently the parent re-renders the subroot, the local modifications will be **lost**.
338
+
339
+ ### When This Happens
340
+ 1. **Subroot modifies local data**: The subroot changes a value that doesn't correspond to any template reference in the parent's `dataOverride`.
341
+ 2. **Parent re-renders**: This can occur when:
342
+ - The parent updates itself for any reason.
343
+ - A subroot action triggers an upstream update that causes the parent to re-render.
344
+ 3. **Data loss**: The parent's `dataOverride` completely overwrites the subroot's data, erasing local modifications.
345
+
346
+ ### Best Practices to Avoid Data Loss
347
+ 1. **Map all needed data**: Ensure all data fields the subroot might modify are included in the parent's data structure.
348
+ 2. **Use complete dataOverride**: Include all necessary data paths in your `dataOverride` mapping.
349
+ 3. **Avoid local-only modifications**: Design your data flow so that all user inputs correspond to parent data.
350
+ 4. **Consider alternatives**: For truly local data, consider using component state or separate data management instead of `sharedUpdates`.
351
+
49
352
  ## Limitations
50
- - The subroot is isolated from the parent; data and state are not shared
51
- - No built-in communication between parent and subroot (except via plugins or explicit data passing)
353
+ - **Data loss risk**: Local modifications in subroot may be lost when parent re-renders (see Caveat section above).
354
+ - **Nested references in data**: References within references are not supported.
355
+ - **Circular references**: May cause infinite loops if data structures reference each other.
356
+ - **Isolation by default**: Without `sharedUpdates`, the subroot is completely isolated from the parent.
357
+ - **Backward compatibility**: `sharedUpdates` is disabled by default to maintain existing behavior.
358
+
359
+ - type: Markdown
360
+ content: |
361
+ ## Changelog
362
+
363
+ ### reactive-json@0.1.0
364
+ - **New**: `sharedUpdates` feature - enables automatic data synchronization between subroot and parent
365
+ - **New**: `dataOverride` property - allows complete data replacement in subroot with support for template references
366
+ - **New**: Automatic analysis of template references in `dataOverride` for shared updates propagation
@@ -188,7 +188,7 @@ Other specialized contexts are available.
188
188
  - **PaginationContext**: Used by components that integrate pagination, such as Switch.
189
189
 
190
190
  ### Key Functions
191
- - **evaluateTemplateValue()**: Evaluates template patterns (`~.value`, `~~.value`, `~>.value`)
191
+ - **evaluateTemplateValue()**: Evaluates template patterns (`~.value`, `~~.value`, `~>key` for nearest, `~~>key` for global)
192
192
  - **useEvaluatedAttributes()**: Hook to evaluate dynamic attributes
193
193
  - **propsDataLocationToPathAndValue()**: Form-specific data location handling
194
194
 
@@ -351,7 +351,8 @@ data:
351
351
  renderView:
352
352
  - content: ~~.global_value # From root data
353
353
  - content: ~.nested_value # From current template
354
- - content: ~>.nested_value # Search up hierarchy
354
+ - content: ~>parent_key.nested_value # Get from nearest parent_key
355
+ - content: ~~>parent_key.nested_value # Get from top-level parent_key
355
356
  ```
356
357
 
357
358
  ### Common RjBuild Patterns
@@ -130,7 +130,7 @@ export const MyWrapper = ({ props, path, currentData, datafield }) => {
130
130
  ## Key APIs and Utilities
131
131
 
132
132
  ### Template Evaluation
133
- - **evaluateTemplateValue()**: Evaluates template patterns like `~.value`, `~~.value`, `~>.value`
133
+ - **evaluateTemplateValue()**: Evaluates template patterns like `~.value`, `~~.value`, `~>key` (nearest), `~~>key` (global)
134
134
  - **evaluateTemplateValueCollection()**: Evaluates collections and arrays with template patterns, supports multiple elements
135
135
  - **useEvaluatedAttributes()**: Hook to evaluate dynamic attributes object
136
136
 
@@ -144,7 +144,7 @@ renderView:
144
144
  ## Key APIs and Utilities
145
145
 
146
146
  ### Template Evaluation
147
- - **evaluateTemplateValue()**: Evaluates template patterns like `~.value`, `~~.value`, `~>.value`
147
+ - **evaluateTemplateValue()**: Evaluates template patterns like `~.value`, `~~.value`, `~>key` (nearest), `~~>key` (global)
148
148
  - **evaluateTemplateValueCollection()**: Evaluates collections and arrays with template patterns, supports multiple elements
149
149
  - **useEvaluatedAttributes()**: Hook to evaluate dynamic attributes object
150
150
 
@@ -30,13 +30,12 @@ data: # Defines the data to be used (optional)
30
30
 
31
31
  ## Key Concepts
32
32
 
33
- ### 1. Template System
33
+ ### Template System
34
34
 
35
- Reactive-JSON uses three main notations to access data:
35
+ In Reactive-JSON, you will often find those notations to access data:
36
36
 
37
- - `~.` : Local context (relative to current template)
37
+ - `~.` : Local context (relative to current template)
38
38
  - `~~.` : Global context (access to global data)
39
- - `~>field` : Access to a specific parent context
40
39
 
41
40
  Example:
42
41
  ```yaml
@@ -48,9 +47,15 @@ templates:
48
47
  content: ["Name: ", ~.name] # Local access to user data
49
48
  - type: div
50
49
  content: ["Admin: ", ~~.isAdmin] # Global access to isAdmin
50
+
51
+ data:
52
+ name: "John"
53
+ isAdmin: true
51
54
  ```
52
55
 
53
- ### 2. Basic Elements
56
+ > 💡 **Advanced navigation:** For complex hierarchical data access, see the [Template System documentation](/docs/template) which covers `~>key` and `~~>key` notations.
57
+
58
+ ### Basic Elements
54
59
 
55
60
  Reactive-JSON provides several types of elements:
56
61
 
@@ -80,12 +85,15 @@ renderView:
80
85
  renderView:
81
86
  - type: Switch
82
87
  content: ~.items
83
- template:
84
- type: div
85
- content: ~.name
88
+ singleOption:
89
+ load: itemTemplate
90
+ templates:
91
+ itemTemplate:
92
+ type: div
93
+ content: ~.name
86
94
  ```
87
95
 
88
- ### 3. Actions and Reactions
96
+ ### Actions and Reactions
89
97
 
90
98
  #### Actions
91
99
  Actions modify element behavior:
@@ -33,12 +33,13 @@ renderView:
33
33
  content: |
34
34
  ## Key Concepts
35
35
 
36
- ### 1. Template System
36
+ ### Template System
37
37
 
38
- Reactive-JSON uses three main notations to access data:
38
+ In Reactive-JSON, you will often find those notations to access data:
39
39
  - `~.` : Local context (relative to current template)
40
40
  - `~~.` : Global context (access to global data)
41
- - `~>field` : Access to a specific parent context
41
+
42
+ > 💡 **Advanced navigation:** For complex hierarchical data access, see the [Template System documentation](/docs/template) which covers `~>key` and `~~>key` notations.
42
43
 
43
44
  - type: RjBuildDescriber
44
45
  title: "Template System Example"
@@ -62,7 +63,7 @@ renderView:
62
63
 
63
64
  - type: Markdown
64
65
  content: |
65
- ### 2. Basic Elements
66
+ ### Basic Elements
66
67
 
67
68
  Reactive-JSON provides several types of elements:
68
69
 
@@ -114,9 +115,12 @@ renderView:
114
115
  renderView:
115
116
  - type: Switch
116
117
  content: ~.items
117
- template:
118
- type: div
119
- content: ~.name
118
+ singleOption:
119
+ load: itemTemplate
120
+ templates:
121
+ itemTemplate:
122
+ type: div
123
+ content: ~.name
120
124
  data:
121
125
  items:
122
126
  - name: "Item 1"
@@ -124,7 +128,7 @@ renderView:
124
128
 
125
129
  - type: Markdown
126
130
  content: |
127
- ### 3. Actions and Reactions
131
+ ### Actions and Reactions
128
132
 
129
133
  #### Actions
130
134
  Actions modify element behavior.
@@ -243,7 +243,7 @@ import { ReactiveJsonRoot } from '@ea-lab/reactive-json'
243
243
  import 'bootstrap/dist/css/bootstrap.min.css'
244
244
 
245
245
  function App() {
246
- return <ReactiveJsonRoot dataUrl="/config.yaml" dataFetchMethod="GET" />
246
+ return <ReactiveJsonRoot rjBuildUrl="/config.yaml" rjBuildFetchMethod="GET" />
247
247
  }
248
248
 
249
249
  export default App
@@ -350,8 +350,8 @@ function App() {
350
350
  path={route.path}
351
351
  element={
352
352
  <ReactiveJsonRoot
353
- dataUrl={route.rjbuild}
354
- dataFetchMethod="GET"
353
+ rjBuildUrl={route.rjbuild}
354
+ rjBuildFetchMethod="GET"
355
355
  />
356
356
  }
357
357
  />
@@ -248,7 +248,7 @@ renderView:
248
248
  import 'bootstrap/dist/css/bootstrap.min.css'
249
249
 
250
250
  function App() {
251
- return <ReactiveJsonRoot dataUrl="/config.yaml" dataFetchMethod="GET" />
251
+ return <ReactiveJsonRoot rjBuildUrl="/config.yaml" rjBuildFetchMethod="GET" />
252
252
  }
253
253
 
254
254
  export default App
@@ -355,8 +355,8 @@ renderView:
355
355
  path={route.path}
356
356
  element={
357
357
  <ReactiveJsonRoot
358
- dataUrl={route.rjbuild}
359
- dataFetchMethod="GET"
358
+ rjBuildUrl={route.rjbuild}
359
+ rjBuildFetchMethod="GET"
360
360
  />
361
361
  }
362
362
  />
@@ -663,7 +663,7 @@ renderView:
663
663
  import 'bootstrap/dist/css/bootstrap.min.css'
664
664
 
665
665
  function App() {
666
- return <ReactiveJsonRoot dataUrl="/config.yaml" dataFetchMethod="GET" />
666
+ return <ReactiveJsonRoot rjBuildUrl="/config.yaml" rjBuildFetchMethod="GET" />
667
667
  }
668
668
 
669
669
  export default App
@@ -784,8 +784,8 @@ renderView:
784
784
  path={route.path}
785
785
  element={
786
786
  <ReactiveJsonRoot
787
- dataUrl={route.rjbuild}
788
- dataFetchMethod="GET"
787
+ rjBuildUrl={route.rjbuild}
788
+ rjBuildFetchMethod="GET"
789
789
  />
790
790
  }
791
791
  />
@@ -6,41 +6,134 @@ The template system in reactive-json efficiently manages data contexts and their
6
6
 
7
7
  ## Context Notations
8
8
 
9
- There are three main notations for accessing data:
9
+ There are four main notations for accessing data:
10
10
 
11
11
  - `~.` : Local context (relative to current template)
12
12
  - `~~.` : Global context (access to global data)
13
- - `~>field` : Access to a specific parent context by climbing up to a given key
13
+ - `~>key` : Finds the nearest "key" by going up the hierarchy (useful when multiple keys exist)
14
+ - `~~>key` : Finds the top-level "key" from root (useful for global settings)
14
15
 
15
- ### Context Usage Example
16
+ Each notation is explained with examples below.
17
+
18
+ #### Local Context (`~.`)
19
+
20
+ ```yaml
21
+ renderView:
22
+ - type: div
23
+ content: ["Hello ", ~.username] # Accesses username from current context
24
+
25
+ data:
26
+ username: "John"
27
+ ```
28
+
29
+ #### Global Context (`~~.`)
16
30
 
17
31
  ```yaml
18
32
  templates:
19
- userList:
20
- type: Switch
21
- content: ~~.users
22
- template:
23
- type: div
33
+ userCard:
34
+ - type: div
24
35
  content:
25
- - type: div
26
- content: ["Name: ", ~.name] # Local access to current user data
27
- - type: div
28
- content: ["Admin: ", ~~.isAdmin] # Global access to isAdmin data
29
- - type: div
30
- content: ["Parent: ", ~>userList.title] # Climbs up to 'userList' template to access title
36
+ - "Admin: "
37
+ - type: LabelFromValue
38
+ dataLocation: ~~.isAdmin # Accesses isAdmin from global data
39
+ options:
40
+ - label: "Yes"
41
+ value: true
42
+ - label: "No"
43
+ value: false
44
+
45
+ renderView:
46
+ - load: userCard
31
47
 
32
48
  data:
33
- users:
34
- - name: "John"
35
49
  isAdmin: true
36
- userList:
37
- title: "User List"
38
50
  ```
39
51
 
40
- In this example:
41
- - `~.name` accesses the `name` property from the local context (current user)
42
- - `~~.isAdmin` accesses the `isAdmin` property from the global context
43
- - `~>userList.title` climbs up to the "userList" template and accesses its `title` property
52
+ #### Nearest Key (`~>key`)
53
+
54
+ ```yaml
55
+ templates:
56
+ themeDisplay:
57
+ type: div
58
+ content: ["Theme: ", ~>config.theme] # Gets theme from nearest config
59
+
60
+ renderView:
61
+ - type: Switch
62
+ content: ~~.config.userSection.config.items
63
+ singleOption:
64
+ load: themeDisplay
65
+
66
+ data:
67
+ config:
68
+ theme: "dark"
69
+ userSection:
70
+ config:
71
+ theme: "light" # This will be found (nearest)
72
+ items:
73
+ - name: "Item 1" # themeDisplay template runs here
74
+ ```
75
+
76
+ #### Top-level Key (`~~>key`)
77
+
78
+ ```yaml
79
+ templates:
80
+ themeDisplay:
81
+ type: div
82
+ content: ["Theme: ", ~~>config.theme] # Gets theme from top-level config
83
+
84
+ renderView:
85
+ - type: Switch
86
+ content: ~~.config.userSection.config.items
87
+ singleOption:
88
+ load: themeDisplay
89
+
90
+ data:
91
+ config:
92
+ theme: "dark" # This will be found (top-level)
93
+ userSection:
94
+ config:
95
+ theme: "light"
96
+ items:
97
+ - name: "Item 1" # themeDisplay template runs here
98
+ ```
99
+
100
+ ### Complete Practical Example
101
+
102
+ Here's a complete working example that demonstrates all four syntaxes in action:
103
+
104
+ ```yaml
105
+ data:
106
+ global_value: "Hello"
107
+ config:
108
+ theme: "dark"
109
+ userSection:
110
+ title: "User List"
111
+ config:
112
+ theme: "light"
113
+ level1:
114
+ items:
115
+ - name: "Item 1"
116
+ # userList template instances run here at: data.config.userSection.level1.items
117
+
118
+ templates:
119
+ userList:
120
+ type: div
121
+ content:
122
+ - type: div
123
+ content: ["Global: ", ~~.global_value] # From root data
124
+ - type: div
125
+ content: ["Local: ", ~.name] # From current template
126
+ - type: div
127
+ content: ["Theme (nearest): ", ~>config.theme] # Get from nearest config → "light"
128
+ - type: div
129
+ content: ["Theme (global): ", ~~>config.theme] # Get from top-level config → "dark"
130
+
131
+ renderView:
132
+ - type: Switch
133
+ content: ~~.config.userSection.level1.items
134
+ singleOption:
135
+ load: userList
136
+ ```
44
137
 
45
138
  ## Containerization Principle
46
139
 
@@ -85,10 +178,12 @@ data:
85
178
  2. Actions and reactions respect the context where they are defined
86
179
  3. Containerization allows isolating modifications until validation
87
180
  4. `~~.` allows "escaping" the container to access global data
88
- 5. `~>field` allows climbing up to a specific parent context using the template name as reference
181
+ 5. `~>key` finds the nearest "key" by going up step by step (useful for local overrides)
182
+ 6. `~~>key` finds the top-level "key" from root (useful for global settings)
89
183
 
90
184
  ## Best Practices
91
185
 
92
186
  1. **Context Coherence**: Ensure components that need to share data are in the same context
93
187
  2. **Global Access**: Use `~~.` for data that needs to be shared between different templates
94
- 3. **Hierarchical Navigation**: Use `~>field` to access specific parent template data by explicitly naming it
188
+ 3. **Hierarchical Navigation**: Use `~>key` to find nearest occurrence or `~~>key` to find global setting
189
+ 4. **Local vs Global**: `~>` prioritizes local overrides, `~~>` prioritizes global settings
@@ -7,46 +7,117 @@ renderView:
7
7
 
8
8
  The template system in reactive-json efficiently manages data contexts and their access. Understanding how templates "containerize" data is essential for properly using components, actions, and reactions.
9
9
 
10
+ - type: Markdown
11
+ content: |
12
+ There are four main notations for accessing data:
13
+
14
+ - `~.` : Local context (relative to current template)
15
+ - `~~.` : Global context (access to global data)
16
+ - `~>key` : Finds the nearest "key" by going up the hierarchy (useful when multiple keys exist)
17
+ - `~~>key` : Finds the top-level "key" from root (useful for global settings)
18
+
19
+ Each notation is explained with examples below.
20
+
21
+ - type: RjBuildDescriber
22
+ title: "Local Context (`~.`)"
23
+ description:
24
+ - type: Markdown
25
+ content: |
26
+ Accesses data from the current template context.
27
+
28
+ toDescribe:
29
+ renderView:
30
+ - type: div
31
+ content: ["Hello ", ~.username] # Accesses username from current context
32
+
33
+ data:
34
+ username: "John"
35
+
10
36
  - type: RjBuildDescriber
11
- title: "Context Notations"
37
+ title: "Global Context (`~~.`)"
12
38
  description:
13
39
  - type: Markdown
14
40
  content: |
15
- There are three main notations for accessing data:
16
-
17
- - `~.` : Local context (relative to current template)
18
- - `~~.` : Global context (access to global data)
19
- - `~>field` : Access to a specific parent context by climbing up to a given key
41
+ Accesses data from the global (root) data, regardless of current template context.
20
42
 
21
43
  toDescribe:
22
44
  templates:
23
- userList:
24
- type: Switch
25
- content: ~~.users
26
- template:
27
- type: div
45
+ userCard:
46
+ - type: div
28
47
  content:
29
- - type: div
30
- content: ["Name: ", ~.name] # Local access to current user data
31
- - type: div
32
- content: ["Admin: ", ~~.isAdmin] # Global access to isAdmin data
33
- - type: div
34
- content: ["Parent: ", ~>userList.title] # Climbs up to 'userList' template to access title
48
+ - "Admin: "
49
+ - type: LabelFromValue
50
+ dataLocation: ~~.isAdmin # Accesses isAdmin from global data
51
+ options:
52
+ - label: "Yes"
53
+ value: true
54
+ - label: "No"
55
+ value: false
56
+
57
+ renderView:
58
+ - load: userCard
35
59
 
36
60
  data:
37
- users:
38
- - name: "John"
39
61
  isAdmin: true
40
- userList:
41
- title: "User List"
62
+
63
+ - type: RjBuildDescriber
64
+ title: "Nearest Key (`~>key`)"
65
+ description:
66
+ - type: Markdown
67
+ content: |
68
+ Searches for "key" by going up the hierarchy, finds the nearest occurrence.
69
+
70
+ toDescribe:
71
+ templates:
72
+ themeDisplay:
73
+ type: div
74
+ content: ["Theme: ", ~>config.theme] # Gets theme from nearest config
75
+
76
+ renderView:
77
+ - type: Switch
78
+ content: ~~.config.userSection.config.items
79
+ singleOption:
80
+ load: themeDisplay
81
+
82
+ data:
83
+ config:
84
+ theme: "dark"
85
+ userSection:
86
+ config:
87
+ theme: "light" # This will be found (nearest)
88
+ items:
89
+ - name: "Item 1" # themeDisplay template runs here
90
+
91
+ - type: RjBuildDescriber
92
+ title: "Top-level Key (`~~>key`)"
93
+ description:
94
+ - type: Markdown
95
+ content: |
96
+ Searches for "key" starting from root, finds the top-level occurrence.
97
+
98
+ toDescribe:
99
+ templates:
100
+ themeDisplay:
101
+ type: div
102
+ content: ["Theme: ", ~~>config.theme] # Gets theme from top-level config
103
+
104
+ renderView:
105
+ - type: Switch
106
+ content: ~~.config.userSection.config.items
107
+ singleOption:
108
+ load: themeDisplay
109
+
110
+ data:
111
+ config:
112
+ theme: "dark" # This will be found (top-level)
113
+ userSection:
114
+ config:
115
+ theme: "light"
116
+ items:
117
+ - name: "Item 1" # themeDisplay template runs here
42
118
 
43
119
  - type: Markdown
44
120
  content: |
45
- In this example:
46
- - `~.name` accesses the `name` property from the local context (current user)
47
- - `~~.isAdmin` accesses the `isAdmin` property from the global context
48
- - `~>userList.title` climbs up to the "userList" template and accesses its `title` property
49
-
50
121
  ## Containerization Principle
51
122
 
52
123
  Templates create context "containers". This means each template defines its own local data space.
@@ -96,13 +167,55 @@ renderView:
96
167
  2. Actions and reactions respect the context where they are defined
97
168
  3. Containerization allows isolating modifications until validation
98
169
  4. `~~.` allows "escaping" the container to access global data
99
- 5. `~>field` allows climbing up to a specific parent context using the template name as reference
170
+ 5. `~>key` finds the nearest "key" by going up step by step (useful for local overrides)
171
+ 6. `~~>key` finds the top-level "key" from root (useful for global settings)
100
172
 
101
173
  ## Best Practices
102
174
 
103
175
  1. **Context Coherence**: Ensure components that need to share data are in the same context
104
176
  2. **Global Access**: Use `~~.` for data that needs to be shared between different templates
105
- 3. **Hierarchical Navigation**: Use `~>field` to access specific parent template data by explicitly naming it
177
+ 3. **Hierarchical Navigation**: Use `~>key` to find nearest occurrence or `~~>key` to find global setting
178
+ 4. **Local vs Global**: `~>` prioritizes local overrides, `~~>` prioritizes global settings
179
+
180
+ - type: RjBuildDescriber
181
+ title: "Complete Practical Example"
182
+ description:
183
+ - type: Markdown
184
+ content: |
185
+ Here's a complete working example that demonstrates all four syntaxes in action with a functional renderView.
186
+
187
+ toDescribe:
188
+ data:
189
+ global_value: "Hello"
190
+ config:
191
+ theme: "dark"
192
+ userSection:
193
+ title: "User List"
194
+ config:
195
+ theme: "light"
196
+ level1:
197
+ items:
198
+ - name: "Item 1"
199
+ # userList template instances run here at: data.config.userSection.level1.items
200
+
201
+ templates:
202
+ userList:
203
+ type: div
204
+ content:
205
+ - type: div
206
+ content: ["Global: ", ~~.global_value] # From root data
207
+ - type: div
208
+ content: ["Local: ", ~.name] # From current template
209
+ - type: div
210
+ content: ["Theme (nearest): ", ~>config.theme] # Get from nearest config → "light"
211
+ - type: div
212
+ content: ["Theme (global): ", ~~>config.theme] # Get from top-level config → "dark"
213
+
214
+ renderView:
215
+ - type: Switch
216
+ content: ~~.config.userSection.level1.items
217
+ singleOption:
218
+ load: userList
106
219
 
107
220
  templates:
108
221