@ea-lab/reactive-json-docs 0.3.0 → 0.5.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 (52) hide show
  1. package/package.json +2 -2
  2. package/public/rjbuild/docs/advanced-concepts/data-mapping.md +76 -0
  3. package/public/rjbuild/docs/advanced-concepts/data-mapping.yaml +140 -0
  4. package/public/rjbuild/docs/advanced-concepts/data-processors.md +373 -0
  5. package/public/rjbuild/docs/advanced-concepts/data-processors.yaml +309 -0
  6. package/public/rjbuild/docs/advanced-concepts/index.md +10 -0
  7. package/public/rjbuild/docs/advanced-concepts/index.yaml +16 -0
  8. package/public/rjbuild/docs/{extend → advanced-concepts/plugins}/component-development-guide-llm.md +2 -0
  9. package/public/rjbuild/docs/{extend → advanced-concepts/plugins}/component-development.md +1 -1
  10. package/public/rjbuild/docs/{extend → advanced-concepts/plugins}/component-development.yaml +1 -1
  11. package/public/rjbuild/docs/{extend → advanced-concepts/plugins}/plugin-system.md +2 -0
  12. package/public/rjbuild/docs/{extend → advanced-concepts/plugins}/plugin-system.yaml +2 -0
  13. package/public/rjbuild/docs/core/action/Hide.md +1 -1
  14. package/public/rjbuild/docs/core/action/Hide.yaml +10 -10
  15. package/public/rjbuild/docs/core/action/ReactOnEvent.md +12 -12
  16. package/public/rjbuild/docs/core/action/ReactOnEvent.yaml +61 -101
  17. package/public/rjbuild/docs/core/action/Redirect.md +10 -2
  18. package/public/rjbuild/docs/core/action/Redirect.yaml +18 -51
  19. package/public/rjbuild/docs/core/action/VisuallyHide.yaml +10 -12
  20. package/public/rjbuild/docs/core/action/index.md +19 -204
  21. package/public/rjbuild/docs/core/action/index.yaml +19 -264
  22. package/public/rjbuild/docs/core/dataMapping/index.md +31 -0
  23. package/public/rjbuild/docs/core/dataMapping/index.yaml +24 -0
  24. package/public/rjbuild/docs/core/dataMapping/simpleMapping.md +131 -0
  25. package/public/rjbuild/docs/core/dataMapping/simpleMapping.yaml +376 -0
  26. package/public/rjbuild/docs/core/element/form/DateField.md +1 -1
  27. package/public/rjbuild/docs/core/element/form/DateField.yaml +4 -4
  28. package/public/rjbuild/docs/core/element/form/SelectField.yaml +2 -2
  29. package/public/rjbuild/docs/core/element/special/ReactiveJsonSubroot.md +4 -3
  30. package/public/rjbuild/docs/core/element/special/ReactiveJsonSubroot.yaml +114 -6
  31. package/public/rjbuild/docs/core/example/website.yaml +10 -10
  32. package/public/rjbuild/docs/core/reaction/index.md +17 -229
  33. package/public/rjbuild/docs/core/reaction/index.yaml +14 -242
  34. package/public/rjbuild/docs/core/reaction/setData.md +1 -1
  35. package/public/rjbuild/docs/core/reaction/setData.yaml +1 -1
  36. package/public/rjbuild/docs/docs-components/index.md +0 -2
  37. package/public/rjbuild/docs/docs-components/index.yaml +0 -2
  38. package/public/rjbuild/docs/getting-started/actions.md +294 -0
  39. package/public/rjbuild/docs/getting-started/actions.yaml +403 -0
  40. package/public/rjbuild/docs/{getting-started.md → getting-started/index.md} +30 -6
  41. package/public/rjbuild/docs/{getting-started.yaml → getting-started/index.yaml} +22 -6
  42. package/public/rjbuild/docs/getting-started/reactions.md +301 -0
  43. package/public/rjbuild/docs/getting-started/reactions.yaml +300 -0
  44. package/public/rjbuild/docs/getting-started/rjbuild-structure.md +358 -0
  45. package/public/rjbuild/docs/getting-started/rjbuild-structure.yaml +421 -0
  46. package/public/rjbuild/docs/{template.md → getting-started/template-contexts-data-binding.md} +16 -12
  47. package/public/rjbuild/docs/{template.yaml → getting-started/template-contexts-data-binding.yaml} +28 -14
  48. package/public/rjbuild/docs/install.yaml +682 -681
  49. /package/public/rjbuild/docs/{core/reaction → advanced-concepts}/forward-update.md +0 -0
  50. /package/public/rjbuild/docs/{core/reaction → advanced-concepts}/forward-update.yaml +0 -0
  51. /package/public/rjbuild/docs/{extend → advanced-concepts/plugins}/index.md +0 -0
  52. /package/public/rjbuild/docs/{extend → advanced-concepts/plugins}/index.yaml +0 -0
@@ -0,0 +1,309 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Data Processors
5
+
6
+ Data Processors are a powerful feature in Reactive-JSON that allow you to intercept and modify data received via `fetchData`, `submitData`, and `additionalDataSources`. This enables you to implement data transformation, validation, security filtering, and other data processing logic in a centralized and reusable way.
7
+
8
+ ## How Data Processors Work
9
+
10
+ When Reactive-JSON receives data from HTTP requests, it automatically passes the data through all registered Data Processors in order. Each processor:
11
+
12
+ 1. **Examines the request and response context** (URL, method, headers, status, etc.)
13
+ 2. **Receives the current data** being processed
14
+ 3. **Must return the data** - either transformed or unchanged
15
+ 4. **Chains with other processors** (processed data flows to the next processor)
16
+
17
+ - type: Markdown
18
+ content: |
19
+ ## Basic Structure
20
+
21
+ A Data Processor is a function that receives context and data, then **must return** the processed data:
22
+
23
+ - type: SyntaxHighlighter
24
+ language: javascript
25
+ content: |
26
+ const myDataProcessor = ({ requestContext, responseContext, dataToProcess, originalDataToProcess }) => {
27
+ // Check if we want to process this data
28
+ if (!requestContext.url.includes('/api/users')) {
29
+ return dataToProcess; // Return unchanged data
30
+ }
31
+
32
+ // Check response status
33
+ if (responseContext.status >= 400) {
34
+ return dataToProcess; // Return unchanged data
35
+ }
36
+
37
+ // Transform the data
38
+ const processedData = {
39
+ ...dataToProcess,
40
+ timestamp: new Date().toISOString(),
41
+ source: requestContext.url
42
+ };
43
+
44
+ return processedData; // Return transformed data
45
+ };
46
+
47
+ - type: Markdown
48
+ content: |
49
+ ## Function Parameters
50
+
51
+ - type: DefinitionList
52
+ content:
53
+ - term: requestContext
54
+ details:
55
+ type: Markdown
56
+ content: |
57
+ Information about the HTTP request:
58
+ - `url`: The URL that was called
59
+ - `method`: HTTP method (GET, POST, etc.)
60
+ - `headers`: Request headers object
61
+ - `body`: Request body (for POST, PUT, etc.)
62
+
63
+ - term: responseContext
64
+ details:
65
+ type: Markdown
66
+ content: |
67
+ Information about the HTTP response:
68
+ - `headers`: Response headers object
69
+ - `status`: HTTP status code (200, 404, etc.)
70
+ - `data`: Raw response data
71
+
72
+ - term: dataToProcess
73
+ details:
74
+ type: Markdown
75
+ content: |
76
+ The data currently being processed. This may have been modified by previous Data Processors in the chain.
77
+
78
+ - term: originalDataToProcess
79
+ details:
80
+ type: Markdown
81
+ content: |
82
+ The original data before any processing, useful for comparison or logging.
83
+
84
+ - type: Markdown
85
+ content: |
86
+ ## Plugin Registration
87
+
88
+ Data Processors are registered through the plugin system:
89
+
90
+ - type: SyntaxHighlighter
91
+ language: javascript
92
+ content: |
93
+ import { mergeComponentCollections } from "@ea-lab/reactive-json";
94
+
95
+ const myPlugins = {
96
+ element: {
97
+ // Your custom components
98
+ },
99
+ dataProcessor: {
100
+ "timestamp-processor": {
101
+ callback: timestampProcessor,
102
+ order: 0
103
+ },
104
+ "security-filter": {
105
+ callback: securityProcessor,
106
+ order: 10
107
+ }
108
+ }
109
+ };
110
+
111
+ export const MyReactiveJsonRoot = (props) => {
112
+ const plugins = mergeComponentCollections([myPlugins]);
113
+ return <ReactiveJsonRoot {...props} plugins={plugins} />;
114
+ };
115
+
116
+ - type: Markdown
117
+ content: |
118
+ ### Plugin Structure
119
+
120
+ - type: DefinitionList
121
+ content:
122
+ - term: Key
123
+ details: Unique identifier for the processor.
124
+ - term: callback
125
+ details: The processor function.
126
+ - term:
127
+ code: order
128
+ after: "(number)"
129
+ details: Execution order (lower numbers run first).
130
+
131
+ - type: Markdown
132
+ content: |
133
+ ## Common Use Cases
134
+
135
+ ### Adding Timestamps
136
+
137
+ - type: SyntaxHighlighter
138
+ language: javascript
139
+ content: |
140
+ const timestampProcessor = ({ requestContext, responseContext, dataToProcess, originalDataToProcess }) => {
141
+ if (typeof dataToProcess !== 'object' || dataToProcess === null) {
142
+ return dataToProcess; // Return unchanged for non-objects
143
+ }
144
+
145
+ return {
146
+ ...dataToProcess,
147
+ __metadata: {
148
+ processedAt: new Date().toISOString(),
149
+ sourceUrl: requestContext.url,
150
+ responseStatus: responseContext.status
151
+ }
152
+ };
153
+ };
154
+
155
+ - type: Markdown
156
+ content: |
157
+ ### Security Filtering
158
+
159
+ - type: SyntaxHighlighter
160
+ language: javascript
161
+ content: |
162
+ const securityProcessor = ({ requestContext, responseContext, dataToProcess, originalDataToProcess }) => {
163
+ // Only filter external API responses
164
+ if (!requestContext.url.includes('external-api')) {
165
+ return dataToProcess; // Return unchanged
166
+ }
167
+
168
+ if (typeof dataToProcess !== 'object' || dataToProcess === null) {
169
+ return dataToProcess; // Return unchanged for non-objects
170
+ }
171
+
172
+ // Remove sensitive fields
173
+ const sensitiveFields = ['password', 'secret', 'apiKey', 'token'];
174
+ const cleanedData = { ...dataToProcess };
175
+
176
+ sensitiveFields.forEach(field => {
177
+ if (cleanedData.hasOwnProperty(field)) {
178
+ delete cleanedData[field];
179
+ console.log(`🔒 Removed sensitive field: ${field}`);
180
+ }
181
+ });
182
+
183
+ return cleanedData;
184
+ };
185
+
186
+ - type: Markdown
187
+ content: |
188
+ ### Data Format Transformation
189
+
190
+ - type: SyntaxHighlighter
191
+ language: javascript
192
+ content: |
193
+ const dateFormatProcessor = ({ requestContext, responseContext, dataToProcess, originalDataToProcess }) => {
194
+ if (typeof dataToProcess !== 'object' || dataToProcess === null) {
195
+ return dataToProcess; // Return unchanged for non-objects
196
+ }
197
+
198
+ const processedData = { ...dataToProcess };
199
+
200
+ // Convert DD/MM/YYYY dates to YYYY-MM-DD
201
+ Object.keys(processedData).forEach(key => {
202
+ if (typeof processedData[key] === 'string' && /^\d{2}\/\d{2}\/\d{4}$/.test(processedData[key])) {
203
+ const [day, month, year] = processedData[key].split('/');
204
+ processedData[key] = `${year}-${month}-${day}`;
205
+ }
206
+ });
207
+
208
+ return processedData;
209
+ };
210
+
211
+ - type: Markdown
212
+ content: |
213
+ ## Best Practices
214
+
215
+ ### Always Return Data
216
+ Data Processors **must always return data**. To skip processing, return the original data:
217
+
218
+ - type: SyntaxHighlighter
219
+ language: javascript
220
+ content: |
221
+ const myProcessor = ({ requestContext, responseContext, dataToProcess, originalDataToProcess }) => {
222
+ // Skip processing for certain conditions
223
+ if (!requestContext.url.includes('/api/')) {
224
+ return dataToProcess; // Return unchanged
225
+ }
226
+ if (responseContext.status >= 400) {
227
+ return dataToProcess; // Return unchanged
228
+ }
229
+ if (typeof dataToProcess !== 'object') {
230
+ return dataToProcess; // Return unchanged
231
+ }
232
+
233
+ // Process and return transformed data
234
+ return { ...dataToProcess, processed: true };
235
+ };
236
+
237
+ - type: Markdown
238
+ content: |
239
+ ### Immutable Updates
240
+ Always clone data before modifying:
241
+
242
+ - type: SyntaxHighlighter
243
+ language: javascript
244
+ content: |
245
+ const processedData = { ...dataToProcess }; // Shallow clone
246
+ // Or for deep cloning, use JSON.parse(JSON.stringify(...)):
247
+ const processedData = JSON.parse(JSON.stringify(dataToProcess));
248
+ // Or with lodash:
249
+ const processedData = _.cloneDeep(dataToProcess);
250
+
251
+ - type: Markdown
252
+ content: |
253
+ ### Error Handling
254
+ The system automatically catches errors, but you can add your own:
255
+
256
+ - type: SyntaxHighlighter
257
+ language: javascript
258
+ content: |
259
+ const safeProcessor = ({ requestContext, responseContext, dataToProcess, originalDataToProcess }) => {
260
+ try {
261
+ // Your processing logic
262
+ return processedData;
263
+ } catch (error) {
264
+ console.error('Processing failed:', error);
265
+ return dataToProcess; // Return original data on error
266
+ }
267
+ };
268
+
269
+ - type: Markdown
270
+ content: |
271
+ ## RjBuild vs Data Processing
272
+
273
+ The system automatically detects whether the response is a complete RjBuild or just data:
274
+
275
+ - **Complete RjBuild**: Processors only modify the `data` section
276
+ - **Data only**: Processors modify the entire response
277
+
278
+ This happens automatically based on the `updateOnlyData` parameter in `fetchData`/`submitData`.
279
+
280
+ ## Execution Context
281
+
282
+ ### With `fetchData`/`submitData`
283
+
284
+ - type: SyntaxHighlighter
285
+ language: yaml
286
+ content: |
287
+ - type: button
288
+ content: "Load User Data"
289
+ actions:
290
+ - what: fetchData
291
+ on: click
292
+ url: "/api/users/123"
293
+ refreshAppOnResponse: true
294
+ updateOnlyData: false # The response is expected to be a complete RjBuild.
295
+ # When the response is a complete RjBuild, the processors will receive the data only.
296
+
297
+ - type: Markdown
298
+ content: |
299
+ ### With `additionalDataSources`
300
+
301
+ - type: SyntaxHighlighter
302
+ language: yaml
303
+ content: |
304
+ additionalDataSource:
305
+ - src: "/api/config"
306
+ path: "~~.config"
307
+ # Processors will automatically process this data
308
+
309
+ data:
@@ -0,0 +1,10 @@
1
+ # Advanced Concepts
2
+
3
+ This section covers advanced features and concepts in Reactive-JSON that enable more sophisticated data processing and application behavior.
4
+
5
+ ## Topics
6
+
7
+ - **[Data Mapping](data-mapping.md)**: Learn how to selectively dispatch and transform response data using the Data Mapping system
8
+ - **[Data Processors](data-processors.md)**: Learn how to intercept and modify data from HTTP requests using the DataProcessor system
9
+ - **[Forward Update](forward-update.md)**: Implementation details about the retrieval of event values.
10
+ - **[Plugins](plugins/index.md)**: Learn how to extend Reactive-JSON with custom components and plugins.
@@ -0,0 +1,16 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Advanced Concepts
5
+
6
+ This section covers advanced features and concepts in Reactive-JSON that enable more sophisticated data processing and application behavior.
7
+
8
+ ## Topics
9
+
10
+ - **[Data Mapping](data-mapping)**: Learn how to selectively dispatch and transform response data using the Data Mapping system.
11
+ - **[Data Processors](data-processors)**: Learn how to intercept and modify data from HTTP requests using the DataProcessor system.
12
+ - **[Forward Update](forward-update)**: Implementation details about the retrieval of event values.
13
+ - **[Plugins](plugins/index)**: Learn how to extend Reactive-JSON with custom components and plugins.
14
+
15
+ data:
16
+ page_title: "Advanced Concepts - Reactive-JSON Documentation"
@@ -277,6 +277,8 @@ export const CustomRoot = (props) => {
277
277
  ```js
278
278
  {
279
279
  action: { /* Action components */ },
280
+ dataMapping: { /* Data mapping processors */ },
281
+ dataProcessor: { /* Data processing functions */ },
280
282
  element: { /* Element components */ },
281
283
  hook: { /* React hooks */ },
282
284
  reaction: { /* Reaction functions */ },
@@ -19,7 +19,7 @@ All components have access to these React contexts:
19
19
  - **TemplateContext**: Contains current template data for evaluation
20
20
 
21
21
  Other specialized contexts are available.
22
- - **EventDispatcherContext**: Centralized event handling system, mostly used by the [reaction system](/docs/core/reaction/index).
22
+ - **EventDispatcherContext**: Centralized event handling system, mostly used by the [reaction system](/docs/getting-started/reactions).
23
23
  - **PaginationContext**: Used by components that integrate pagination, such as [Switch](/docs/core/element/special/Switch).
24
24
 
25
25
  ## Basic Element Component
@@ -22,7 +22,7 @@ renderView:
22
22
  - **TemplateContext**: Contains current template data for evaluation
23
23
 
24
24
  Other specialized contexts are available.
25
- - **EventDispatcherContext**: Centralized event handling system, mostly used by the [reaction system](/docs/core/reaction/index).
25
+ - **EventDispatcherContext**: Centralized event handling system, mostly used by the [reaction system](/docs/getting-started/reactions).
26
26
  - **PaginationContext**: Used by components that integrate pagination, such as [Switch](/docs/core/element/special/Switch).
27
27
 
28
28
  ## Basic Element Component
@@ -12,6 +12,8 @@ A plugin is a JavaScript object that exports components organized by type. The s
12
12
  - **action**: Components that perform side effects or modify behavior
13
13
  - **reaction**: Event-driven components that respond to user interactions
14
14
  - **hook**: React hooks that provide additional functionality
15
+ - **dataProcessor**: Functions that intercept and modify HTTP response data
16
+ - **dataMapping**: Processors that selectively dispatch response data to specific locations
15
17
 
16
18
  ## Plugin Registration
17
19
 
@@ -15,6 +15,8 @@ renderView:
15
15
  - **action**: Components that perform side effects or modify behavior
16
16
  - **reaction**: Event-driven components that respond to user interactions
17
17
  - **hook**: React hooks that provide additional functionality
18
+ - **dataProcessor**: Functions that intercept and modify HTTP response data
19
+ - **dataMapping**: Processors that selectively dispatch response data to specific locations
18
20
 
19
21
  ## Plugin Registration
20
22
 
@@ -19,4 +19,4 @@ renderView:
19
19
  ```
20
20
 
21
21
  ## Limitation
22
- - The element no longer exists in the DOM, so no events can be attached to it.
22
+ - When hidden, the element no longer exists in the DOM, so no events can be attached to it.
@@ -30,31 +30,31 @@ renderView:
30
30
  actions:
31
31
  - what: setData
32
32
  on: click
33
- path: "shouldHide"
34
- value: ~.shouldHide
35
- is: false
33
+ path: ~.shouldHide
34
+ value: "true"
35
+ when: ~.shouldHide
36
+ is: "false"
36
37
  - what: setData
37
38
  on: click
38
- path: "shouldHide"
39
- value: ~.shouldHide
40
- is: true
39
+ path: ~.shouldHide
40
+ value: "false"
41
41
  when: ~.shouldHide
42
- is: false
42
+ is: "true"
43
43
 
44
44
  - type: div
45
45
  content: "This text will be hidden when shouldHide is true."
46
46
  actions:
47
47
  - what: hide
48
48
  when: ~.shouldHide
49
- is: true
49
+ is: "true"
50
50
 
51
51
  - type: div
52
52
  content: ["Current state: shouldHide = ", ~.shouldHide]
53
53
 
54
54
  data:
55
- shouldHide: false
55
+ shouldHide: "false"
56
56
 
57
57
  - type: Markdown
58
58
  content: |
59
59
  ## Limitation
60
- - The element no longer exists in the DOM, so no events can be attached to it.
60
+ - When hidden, the element no longer exists in the DOM, so no events can be attached to it.
@@ -1,8 +1,8 @@
1
1
  # ReactOnEvent
2
2
 
3
- **Type**: Internal Action Component
3
+ ReactOnEvent is an internal action component that is automatically instantiated by the Actions system when reactions with event handlers (`on: "eventName"`) are detected. It should **not** be used directly as an element type.
4
4
 
5
- **Description**: ReactOnEvent is an internal action component that is automatically instantiated by the Actions system when reactions with event handlers (`on: "eventName"`) are detected. It should **not** be used directly as an element type.
5
+ > **Important**: It should **not** be used directly as an element type. The Reactive-JSON engine will automatically instantiate it when needed.
6
6
 
7
7
  ## How it Works
8
8
 
@@ -43,8 +43,8 @@ ReactOnEvent supports any DOM event by prefixing with `on` and capitalizing the
43
43
 
44
44
  Some events have special handling and **do not** use ReactOnEvent:
45
45
 
46
- - `on: "message"` → Uses MessageListener component (listens on window)
47
- - `on: "hashchange"` → Uses HashChangeListener component (listens on window)
46
+ - `on: "message"` → Uses the [MessageListener](MessageListener.md) component (listens on window)
47
+ - `on: "hashchange"` → Uses the [HashChangeListener](HashChangeListener.md) component (listens on window)
48
48
 
49
49
  ## Event Propagation Control
50
50
 
@@ -67,15 +67,15 @@ actions:
67
67
  - **Context preservation**: Maintains access to global and template data contexts
68
68
  - **Early termination**: Supports `stopPropagation: true` to halt reaction chain execution
69
69
 
70
+ ## Important Notes
71
+
72
+ - **Never use `type: ReactOnEvent`** in your renderView - it's an internal component
73
+ - **Use `actions` with `on: "eventName"`** - this is the correct way to handle events
74
+ - **ReactOnEvent is automatically instantiated** by the Actions system when needed
75
+ - **Event propagation is stopped by default** - use `stopPropagation: false` to change this
76
+
70
77
  ## Related Components
71
78
 
72
79
  - **[MessageListener](MessageListener.md)**: Handles `on: "message"` events
73
80
  - **[HashChangeListener](HashChangeListener.md)**: Handles `on: "hashchange"` events
74
- - **[Reactions System](../reaction/index.md)**: The actual reaction functions that ReactOnEvent executes
75
-
76
- ## Important Notes
77
-
78
- - **Not for direct use**: Never use `type: ReactOnEvent` in your renderView
79
- - **Automatic instantiation**: The Actions system creates this component automatically
80
- - **Internal implementation**: This is part of the framework's internal architecture
81
- - **Event binding**: Events are bound to the actual DOM elements, not wrapper components
81
+ - **[Reactions System](../../getting-started/reactions.md)**: The actual reaction functions that ReactOnEvent executes
@@ -3,9 +3,9 @@ renderView:
3
3
  content: |
4
4
  # ReactOnEvent
5
5
 
6
- **Type**: Internal Action Component
7
-
8
- **Description**: ReactOnEvent is an internal action component that is automatically instantiated by the Actions system when reactions with event handlers (`on: "eventName"`) are detected. It should **not** be used directly as an element type.
6
+ ReactOnEvent is an internal action component that is automatically instantiated by the Actions system when reactions with event handlers (`on: "eventName"`) are detected.
7
+
8
+ > **Important**: It should **not** be used directly as an element type. The Reactive-JSON engine will automatically instantiate it when needed.
9
9
 
10
10
  ## How it Works
11
11
 
@@ -16,105 +16,66 @@ renderView:
16
16
  3. Creates a ReactOnEvent component that attaches the appropriate event listeners
17
17
  4. Wraps the target element with these event handlers
18
18
 
19
- - type: RjBuildDescriber
20
- title: "Correct Usage: Reactions with Events"
21
- description:
22
- - type: Markdown
23
- content: |
24
- This example shows the **correct** way to use event handling in Reactive-JSON.
25
-
26
- ReactOnEvent is automatically created by the system when you use `on: "eventName"` in actions.
19
+ ## Usage Pattern
27
20
 
28
- toDescribe:
29
- renderView:
30
- - type: div
31
- content:
32
- - type: button
33
- content: "Click me"
34
- actions:
35
- - what: setData
36
- on: click # ReactOnEvent handles this automatically
37
- path: "clicked"
38
- value: true
39
- - what: setData
40
- on: click
41
- path: "clickCount"
42
- value: 1
43
- when: ~.clickCount
44
- isEmpty: true
45
- - what: setData
46
- on: click
47
- path: "clickCount"
48
- value: "~.clickCount + 1"
49
- when: ~.clickCount
50
- isEmpty: "not"
51
-
52
- - type: input
53
- props:
54
- type: "text"
55
- placeholder: "Type something..."
56
- actions:
57
- - what: setData
58
- on: change # ReactOnEvent handles this automatically
59
- path: "inputValue"
60
- value: "~event.target.value"
61
-
62
- - type: div
63
- content: "Mouse over this area"
64
- props:
65
- style:
66
- padding: "10px"
67
- border: "1px solid #ccc"
68
- backgroundColor: "~.hovered ? '#f0f0f0' : 'white'"
69
- actions:
70
- - what: setData
71
- on: mouseover # ReactOnEvent handles this automatically
72
- path: "hovered"
73
- value: true
74
- - what: setData
75
- on: mouseleave # ReactOnEvent handles this automatically
76
- path: "hovered"
77
- value: false
78
-
79
- - type: div
80
- content:
81
- - type: div
82
- content: ["Button clicked: ", ~.clicked]
83
-
84
- - type: div
85
- content: ["Click count: ", ~.clickCount]
86
-
87
- - type: div
88
- content: ["Input value: '", ~.inputValue, "'"]
89
-
90
- - type: div
91
- content: ["Mouse hover state: ", ~.hovered]
21
+ Instead of using ReactOnEvent directly, you define reactions in the `actions` array of any element:
92
22
 
23
+ ```yaml
24
+ renderView:
93
25
  - type: button
94
- content: "Reset all"
26
+ content: "Click me"
95
27
  actions:
96
28
  - what: setData
97
- on: click
98
- path: "clicked"
99
- value: false
100
- - what: setData
101
- on: click
102
- path: "clickCount"
103
- value: 0
104
- - what: setData
105
- on: click
106
- path: "inputValue"
107
- value: ""
108
- - what: setData
109
- on: click
110
- path: "hovered"
111
- value: false
29
+ on: click # This triggers ReactOnEvent internally
30
+ path: "buttonClicked"
31
+ value: true
32
+ ```
33
+
34
+ ## Supported Event Types
35
+
36
+ ReactOnEvent supports any DOM event by prefixing with `on` and capitalizing the first letter:
37
+
38
+ - `on: click` → `onClick`
39
+ - `on: change` → `onChange`
40
+ - `on: mouseover` → `onMouseOver`
41
+ - `on: keydown` → `onKeyDown`
42
+ - `on: submit` → `onSubmit`
43
+ - etc.
44
+
45
+ ## Special Event Handling
46
+
47
+ Some events have special handling and **do not** use ReactOnEvent:
48
+
49
+ - `on: "message"` → Uses the [MessageListener](MessageListener.md) component (listens on window)
50
+ - `on: "hashchange"` → Uses the [HashChangeListener](HashChangeListener.md) component (listens on window)
51
+
52
+ ## Event Propagation Control
53
+
54
+ By default, ReactOnEvent stops event propagation. You can control this behavior:
55
+
56
+ ```yaml
57
+ actions:
58
+ - what: setData
59
+ on: click
60
+ path: "clicked"
61
+ value: true
62
+ stopPropagation: false # Allow event to continue propagating
63
+ ```
64
+
65
+ ## Event Placeholders
66
+
67
+ ReactOnEvent supports special placeholders to access event data:
68
+
69
+ - `<reactive-json:event-new-value>`: Returns the most relevant value from form events (checked for checkboxes, value for inputs)
70
+ - `<reactive-json:event>.propertyPath`: Access any event property (e.g., `.data.message` for MessageEvent, `.key` for KeyboardEvent)
71
+
72
+ ## Technical Implementation
112
73
 
113
- data:
114
- clicked: false
115
- clickCount: 0
116
- inputValue: ""
117
- hovered: false
74
+ - **Event attachment**: Uses React's event system via `cloneElement`
75
+ - **Multiple events**: Can handle multiple event types on the same element
76
+ - **Reaction execution**: Executes reactions in the order they appear
77
+ - **Context preservation**: Maintains access to global and template data contexts
78
+ - **Early termination**: Supports `stopPropagation: true` to halt reaction chain execution
118
79
 
119
80
  - type: Markdown
120
81
  content: |
@@ -125,9 +86,8 @@ renderView:
125
86
  - **ReactOnEvent is automatically instantiated** by the Actions system when needed
126
87
  - **Event propagation is stopped by default** - use `stopPropagation: false` to change this
127
88
 
128
- ## Related Documentation
89
+ ## Related Components
129
90
 
130
- - **[Actions System](index.md)**: Learn about the actions system that uses ReactOnEvent
131
- - **[Reactions](../reaction/index.md)**: The reaction functions that ReactOnEvent executes
132
- - **[MessageListener](MessageListener.md)**: For `on: "message"` events
133
- - **[HashChangeListener](HashChangeListener.md)**: For `on: "hashchange"` events
91
+ - **[MessageListener](MessageListener.md)**: Handles `on: "message"` events
92
+ - **[HashChangeListener](HashChangeListener.md)**: Handles `on: "hashchange"` events
93
+ - **[Reactions System](../../getting-started/reactions.md)**: The actual reaction functions that ReactOnEvent executes