@ea-lab/reactive-json-docs 1.3.1 → 1.4.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": "1.3.1",
3
+ "version": "1.4.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": "^1.2.0",
29
+ "@ea-lab/reactive-json": "^1.3.0",
30
30
  "@ea-lab/reactive-json-chartjs": "^1.0.0",
31
31
  "@npmcli/fs": "^4.0.0",
32
32
  "@reduxjs/toolkit": "^2.6.1",
@@ -8,42 +8,73 @@ Dynamically sets or modifies the value of an HTML attribute before rendering. Th
8
8
 
9
9
  ```yaml
10
10
  attributeTransforms:
11
- # Add CSS class
11
+ # Add CSS class (string mode)
12
12
  - what: setAttributeValue
13
13
  name: "class"
14
14
  value: "active"
15
15
 
16
- # Replace attribute value
16
+ # Replace attribute value (string mode)
17
17
  - what: setAttributeValue
18
18
  name: "data-status"
19
19
  mode: "replace"
20
20
  value: ~.currentStatus
21
+
22
+ # Merge style object (object mode)
23
+ - what: setAttributeValue
24
+ name: "style"
25
+ value:
26
+ borderColor: "#3b82f6"
27
+ backgroundColor: "#ffffff"
21
28
  ```
22
29
 
23
30
  ## Properties
24
31
 
25
32
  - **name** *(string, required)*: The name of the attribute to modify.
26
33
  - **mode** *(string, optional)*: The modification mode. Default: `"append"`.
27
- - `"append"`: Adds the value to the existing attribute value (space-separated).
34
+ - `"append"`: Adds the value to the existing attribute value (space-separated for strings, merges properties for objects).
28
35
  - `"replace"`: Completely replaces the existing attribute value.
29
- - **value** *(string, required)*: The value to set or append. Supports template evaluation (e.g., `~.dynamicValue`, `~~.globalValue`). Automatically converted to string if not already. Special characters are handled safely.
30
- - **preventDuplicateValues** *(boolean, optional)*: When `true` (default), prevents duplicate values when using append mode.
31
- - **separator** *(string, optional)*: The separator used between values. Default: `" "` (space).
36
+ - **value** *(string | object, required)*: The value to set or append. Supports template evaluation (e.g., `~.dynamicValue`, `~~.globalValue`).
37
+ - **String mode**: When `value` is a string, operates in string mode for simple attributes like `class`, `data-*`, etc.
38
+ - **Object mode**: When `value` is an object, operates in object mode for complex attributes like `style`. In append mode, merges properties property by property.
39
+ - **preventDuplicateValues** *(boolean, optional)*: When `true` (default), prevents duplicate values when using append mode (applies to string mode and string properties in object mode).
40
+ - **separator** *(string, optional)*: The separator used between values in string mode. Default: `" "` (space).
32
41
 
33
42
  ## Behavior
34
43
 
44
+ The transformer operates in two distinct modes based on the `value` type:
45
+
46
+ ### String Mode (when `value` is a string)
47
+
35
48
  - **Append mode**: Adds the new value to the existing attribute, separated by the specified separator.
36
49
  - **Replace mode**: Completely overwrites the existing attribute value.
37
50
  - **Duplicate prevention**: In append mode, prevents adding duplicate values when enabled.
38
51
 
52
+ ### Object Mode (when `value` is an object)
53
+
54
+ - **Replace mode**: Completely replaces the entire object attribute.
55
+ - **Append mode**: Merges properties property by property:
56
+ - Starts from the current object attribute
57
+ - For each property in `value`, applies the same logic as string mode:
58
+ - If both current and new values are strings: appends them (respecting `preventDuplicateValues`)
59
+ - Otherwise: replaces the property with the new value (new value has precedence)
60
+ - Handles nested objects recursively
61
+ - Works on a copy to avoid mutation issues
62
+
63
+ ### Undefined Values
64
+
65
+ - **Append mode**: `undefined` values are ignored, keeping the current attribute unchanged.
66
+ - **Replace mode**: `undefined` is assigned to the attribute.
67
+
39
68
  ## Common Use Cases
40
69
 
41
- - **Dynamic CSS classes**: Adding/removing CSS classes based on state.
42
- - **Data attributes**: Setting data-* attributes for JavaScript integration.
43
- - **ARIA attributes**: Dynamically updating accessibility attributes.
44
- - **Style attributes**: Modifying inline styles conditionally.
70
+ - **Dynamic CSS classes**: Adding/removing CSS classes based on state (string mode).
71
+ - **Data attributes**: Setting data-* attributes for JavaScript integration (string mode).
72
+ - **ARIA attributes**: Dynamically updating accessibility attributes (string mode).
73
+ - **Style attributes**: Modifying inline styles conditionally (object mode). Merge style properties without losing existing ones.
74
+
75
+ ## Examples
45
76
 
46
- ## Example
77
+ ### String Mode Example
47
78
 
48
79
  ```yaml
49
80
  renderView:
@@ -91,11 +122,73 @@ data:
91
122
  input_data: ""
92
123
  ```
93
124
 
125
+ ### Object Mode Example (Style Merging)
126
+
127
+ ```yaml
128
+ renderView:
129
+ - type: div
130
+ attributes:
131
+ style:
132
+ padding: "10px"
133
+ border: "2px solid #007bff"
134
+ borderRadius: "4px"
135
+ attributeTransforms:
136
+ # Merge additional style properties without losing existing ones
137
+ - what: setAttributeValue
138
+ name: "style"
139
+ value:
140
+ borderColor: "#3b82f6"
141
+ backgroundColor: "#f0f0f0"
142
+ when: ~.isHighlighted
143
+ is: true
144
+ # Result when isHighlighted is true:
145
+ # style: {
146
+ # padding: "10px",
147
+ # border: "2px solid #007bff",
148
+ # borderRadius: "4px",
149
+ # borderColor: "#3b82f6",
150
+ # backgroundColor: "#f0f0f0"
151
+ # }
152
+
153
+ data:
154
+ isHighlighted: false
155
+ ```
156
+
157
+ ### Object Mode Replace Example
158
+
159
+ ```yaml
160
+ renderView:
161
+ - type: div
162
+ attributes:
163
+ style:
164
+ padding: "10px"
165
+ border: "2px solid #007bff"
166
+ attributeTransforms:
167
+ # Completely replace the style object
168
+ - what: setAttributeValue
169
+ name: "style"
170
+ mode: "replace"
171
+ value:
172
+ backgroundColor: "#ffffff"
173
+ color: "#000000"
174
+ # Result:
175
+ # style: {
176
+ # backgroundColor: "#ffffff",
177
+ # color: "#000000"
178
+ # }
179
+ # (original padding and border are lost)
180
+ ```
181
+
94
182
  ## Notes
95
183
 
96
184
  - **Pre-render execution**: This transformer modifies attributes before the component renders, ensuring child components receive the transformed attributes.
97
- - **Append mode behavior**: Respects existing attribute values when using append mode.
98
- - **Replace mode**: Use when you need complete control over the attribute value.
99
- - **Duplicate prevention**: Only applies to append mode.
185
+ - **Mode detection**: The transformer automatically detects whether to use string mode or object mode based on the `value` type after template evaluation.
186
+ - **Append mode behavior**:
187
+ - **String mode**: Respects existing attribute values, adding new values separated by the specified separator.
188
+ - **Object mode**: Merges properties property by property, applying string append logic where both values are strings, otherwise replacing with the new value.
189
+ - **Replace mode**: Use when you need complete control over the attribute value. In object mode, completely replaces the entire object.
190
+ - **Duplicate prevention**: Only applies to append mode, and works for string values in both string mode and object mode.
191
+ - **Object merging**: In object mode append, nested objects are merged recursively. Properties that don't match the expected format for append are replaced (new value has precedence).
100
192
  - **Template evaluation**: The value property supports full template evaluation including `~.localData`, `~~.globalData`, `~>nearestKey`, and `~~>globalKey` patterns.
101
193
  - **Conditional execution**: Supports the same condition system as actions (`when`, `is`, `isEmpty`, `isNotEmpty`, etc.).
194
+ - **Undefined handling**: `undefined` values are ignored in append mode but assigned in replace mode.
@@ -12,16 +12,23 @@ renderView:
12
12
  - type: TabbedSerializer
13
13
  yamlSerializedContent: |
14
14
  attributeTransforms:
15
- # Add CSS class
15
+ # Add CSS class (string mode)
16
16
  - what: setAttributeValue
17
17
  name: "class"
18
18
  value: "active"
19
19
 
20
- # Replace attribute value
20
+ # Replace attribute value (string mode)
21
21
  - what: setAttributeValue
22
22
  name: "data-status"
23
23
  mode: "replace"
24
24
  value: ~.currentStatus
25
+
26
+ # Merge style object (object mode)
27
+ - what: setAttributeValue
28
+ name: "style"
29
+ value:
30
+ borderColor: "#3b82f6"
31
+ backgroundColor: "#ffffff"
25
32
 
26
33
  - type: Markdown
27
34
  content: |
@@ -44,8 +51,14 @@ renderView:
44
51
  - `"replace"`: Completely replaces the existing attribute value
45
52
  - term:
46
53
  code: value
47
- after: "(string, required)"
48
- details: The value to set or append. Supports template evaluation (e.g., `~.dynamicValue`, `~~.globalValue`). Automatically converted to string if not already. Special characters are handled safely.
54
+ after: "(string | object, required)"
55
+ details:
56
+ type: Markdown
57
+ content: |
58
+ The value to set or append. Supports template evaluation (e.g., `~.dynamicValue`, `~~.globalValue`).
59
+
60
+ - **String mode**: When `value` is a string, operates in string mode for simple attributes like `class`, `data-*`, etc.
61
+ - **Object mode**: When `value` is an object, operates in object mode for complex attributes like `style`. In append mode, merges properties property by property.
49
62
  - term:
50
63
  code: preventDuplicateValues
51
64
  after: "(boolean, optional)"
@@ -65,16 +78,36 @@ renderView:
65
78
 
66
79
  ## Behavior
67
80
 
81
+ The transformer operates in two distinct modes based on the `value` type:
82
+
83
+ ### String Mode (when `value` is a string)
84
+
68
85
  - **Append mode**: Adds the new value to the existing attribute, separated by the specified separator.
69
86
  - **Replace mode**: Completely overwrites the existing attribute value.
70
87
  - **Duplicate prevention**: In append mode, prevents adding duplicate values when enabled.
71
88
 
89
+ ### Object Mode (when `value` is an object)
90
+
91
+ - **Replace mode**: Completely replaces the entire object attribute.
92
+ - **Append mode**: Merges properties property by property:
93
+ - Starts from the current object attribute
94
+ - For each property in `value`, applies the same logic as string mode:
95
+ - If both current and new values are strings: appends them (respecting `preventDuplicateValues`)
96
+ - Otherwise: replaces the property with the new value (new value has precedence)
97
+ - Handles nested objects recursively
98
+ - Works on a copy to avoid mutation issues
99
+
100
+ ### Undefined Values
101
+
102
+ - **Append mode**: `undefined` values are ignored, keeping the current attribute unchanged.
103
+ - **Replace mode**: `undefined` is assigned to the attribute.
104
+
72
105
  ## Common Use Cases
73
106
 
74
- - **Dynamic CSS classes**: Adding/removing CSS classes based on state.
75
- - **Data attributes**: Setting data-* attributes for JavaScript integration.
76
- - **ARIA attributes**: Dynamically updating accessibility attributes.
77
- - **Style attributes**: Modifying inline styles conditionally.
107
+ - **Dynamic CSS classes**: Adding/removing CSS classes based on state (string mode).
108
+ - **Data attributes**: Setting data-* attributes for JavaScript integration (string mode).
109
+ - **ARIA attributes**: Dynamically updating accessibility attributes (string mode).
110
+ - **Style attributes**: Modifying inline styles conditionally (object mode). Merge style properties without losing existing ones.
78
111
 
79
112
  - type: RjBuildDescriber
80
113
  title: "SetAttributeValue Action Examples"
@@ -134,11 +167,90 @@ renderView:
134
167
  data:
135
168
  input_data: ""
136
169
 
170
+ - type: RjBuildDescriber
171
+ title: "Object Mode Example - Style Merging"
172
+ description:
173
+ - type: Markdown
174
+ content: |
175
+ This example demonstrates how to use `setAttributeValue` in object mode to merge style properties without losing existing ones.
176
+
177
+ **Expected behavior:**
178
+ - The div has initial styles (padding, border, borderRadius)
179
+ - When `isHighlighted` is true, additional style properties are merged
180
+ - The original styles are preserved, and new properties are added
181
+ - Try toggling the highlight to see the style merge in action
182
+
183
+ toDescribe:
184
+ renderView:
185
+ - type: div
186
+ attributes:
187
+ style:
188
+ padding: "10px"
189
+ border: "2px solid #007bff"
190
+ borderRadius: "4px"
191
+ attributeTransforms:
192
+ # Merge additional style properties without losing existing ones
193
+ - what: setAttributeValue
194
+ name: "style"
195
+ value:
196
+ borderColor: "#3b82f6"
197
+ backgroundColor: "#f0f0f0"
198
+ when: ~.isHighlighted
199
+ is: true
200
+ content: "Click to toggle highlight"
201
+
202
+ - type: button
203
+ content: "Toggle Highlight"
204
+ actions:
205
+ - what: setData
206
+ on: click
207
+ path: ~.isHighlighted
208
+ value: <reactive-json:not>~~.isHighlighted</reactive-json:not>
209
+
210
+ data:
211
+ isHighlighted: false
212
+
213
+ - type: RjBuildDescriber
214
+ title: "Object Mode Replace Example"
215
+ description:
216
+ - type: Markdown
217
+ content: |
218
+ This example demonstrates how to completely replace a style object using `mode: "replace"`.
219
+
220
+ **Expected behavior:**
221
+ - The div has initial styles (padding, border)
222
+ - When replace mode is used, the entire style object is replaced
223
+ - Original styles are lost, only the new styles remain
224
+
225
+ toDescribe:
226
+ renderView:
227
+ - type: div
228
+ attributes:
229
+ style:
230
+ padding: "10px"
231
+ border: "2px solid #007bff"
232
+ attributeTransforms:
233
+ # Completely replace the style object
234
+ - what: setAttributeValue
235
+ name: "style"
236
+ mode: "replace"
237
+ value:
238
+ backgroundColor: "#ffffff"
239
+ color: "#000000"
240
+ content: "This div's style was completely replaced"
241
+
137
242
  - type: Markdown
138
243
  content: |
139
244
  ## Notes
140
245
 
141
- - The action respects existing attribute values when using append mode.
142
- - Use replace mode when you need complete control over the attribute value.
143
- - Duplicate prevention only applies to append mode.
144
- - The value property supports full template evaluation including `~.localData`, `~~.globalData`, `~>nearestKey`, and `~~>globalKey` patterns.
246
+ - **Pre-render execution**: This transformer modifies attributes before the component renders, ensuring child components receive the transformed attributes.
247
+ - **Mode detection**: The transformer automatically detects whether to use string mode or object mode based on the `value` type after template evaluation.
248
+ - **Append mode behavior**:
249
+ - **String mode**: Respects existing attribute values, adding new values separated by the specified separator.
250
+ - **Object mode**: Merges properties property by property, applying string append logic where both values are strings, otherwise replacing with the new value.
251
+ - **Replace mode**: Use when you need complete control over the attribute value. In object mode, completely replaces the entire object.
252
+ - **Duplicate prevention**: Only applies to append mode, and works for string values in both string mode and object mode.
253
+ - **Object merging**: In object mode append, nested objects are merged recursively. Properties that don't match the expected format for append are replaced (new value has precedence).
254
+ - **Template evaluation**: The value property supports full template evaluation including `~.localData`, `~~.globalData`, `~>nearestKey`, and `~~>globalKey` patterns.
255
+ - **Conditional execution**: Supports the same condition system as actions (`when`, `is`, `isEmpty`, `isNotEmpty`, etc.).
256
+ - **Undefined handling**: `undefined` values are ignored in append mode but assigned in replace mode.
@@ -0,0 +1,211 @@
1
+ # DataFilter Example: Filtering Direct Array Items
2
+
3
+ This example demonstrates how to use `DataFilter` with arrays where each item is a direct object (not wrapped in a namespace property). This is useful when working with data from APIs that return arrays of objects directly.
4
+
5
+ ## Use Case
6
+
7
+ When your data structure is a direct array of objects like:
8
+ ```yaml
9
+ data:
10
+ rows:
11
+ - id: 1
12
+ label: "Operation 1"
13
+ done: "done"
14
+ operation: "create"
15
+ - id: 2
16
+ label: "Operation 2"
17
+ done: "pending"
18
+ operation: "update"
19
+ ```
20
+
21
+ Instead of:
22
+ ```yaml
23
+ data:
24
+ rows:
25
+ - item:
26
+ id: 1
27
+ label: "Operation 1"
28
+ ```
29
+
30
+ ## Solution
31
+
32
+ Use an existing property that is present in all items (like `id`) as the `subjectsWithProperty` namespace. In `whenFilterableData`, reference properties directly without the namespace prefix.
33
+
34
+ **Important**: When using string values for filtering (like status), use a special value like `"all"` to represent "no filter" instead of an empty string, as empty strings can cause issues with select elements.
35
+
36
+ ## Complete Example
37
+
38
+ ```yaml
39
+ renderView:
40
+ - type: DataFilter
41
+ context: global
42
+ filters:
43
+ - subjectsWithProperty: id
44
+ andConditions:
45
+ # Filter by status (string)
46
+ - orConditions:
47
+ - when: ~~._filters.done
48
+ is: "all"
49
+ - whenFilterableData: done
50
+ is: ~~._filters.done
51
+
52
+ # Filter by operation type (text search with contains)
53
+ - orConditions:
54
+ - when: ~~._filters.operation
55
+ is: ""
56
+ - andConditions:
57
+ - whenFilterableData: operation
58
+ isNotEmpty: true
59
+ - when: ~~._filters.operation
60
+ isNotEmpty: true
61
+ - whenFilterableData: operation
62
+ contains: ~~._filters.operation
63
+
64
+ # Filter by label (text search with contains)
65
+ - orConditions:
66
+ - when: ~~._filters.label
67
+ is: ""
68
+ - andConditions:
69
+ - whenFilterableData: label
70
+ isNotEmpty: true
71
+ - when: ~~._filters.label
72
+ isNotEmpty: true
73
+ - whenFilterableData: label
74
+ contains: ~~._filters.label
75
+ content:
76
+ - type: Switch
77
+ content: ~~.rows
78
+ singleOption:
79
+ load: operationRow
80
+
81
+ templates:
82
+ operationRow:
83
+ - type: tr
84
+ content:
85
+ - type: td
86
+ content: ~.id
87
+ - type: td
88
+ content: ~.label
89
+ - type: td
90
+ content: ~.done
91
+ - type: td
92
+ content: ~.operation
93
+
94
+ data:
95
+ rows:
96
+ - id: 1
97
+ label: "Operation 1"
98
+ done: "done"
99
+ operation: "create"
100
+ - id: 2
101
+ label: "Operation 2"
102
+ done: "pending"
103
+ operation: "update"
104
+ - id: 3
105
+ label: "Operation 3"
106
+ done: "done"
107
+ operation: "create"
108
+ _filters:
109
+ done: "all"
110
+ label: ""
111
+ operation: ""
112
+ ```
113
+
114
+ ## Key Points
115
+
116
+ 1. **Namespace Selection**: Choose a property that exists in all items (e.g., `id`, `name`, `key`). This property acts as the identifier for DataFilter to recognize filterable items.
117
+
118
+ 2. **Direct Property Access**: In `whenFilterableData`, reference properties directly:
119
+ - ✅ `whenFilterableData: label` (correct)
120
+ - ❌ `whenFilterableData: id.label` (incorrect - don't use namespace prefix)
121
+
122
+ 3. **String-based Filtering**: When using select elements for filtering, use a special value like `"all"` to represent "no filter" instead of an empty string:
123
+ ```yaml
124
+ - orConditions:
125
+ - when: ~~._filters.done
126
+ is: "all" # Shows all items
127
+ - whenFilterableData: done
128
+ is: ~~._filters.done # Filters by exact match
129
+ ```
130
+ This avoids issues where select elements might not properly handle empty string values.
131
+
132
+ 4. **Text Search**: For text search with `contains`, ensure both the filter value and the data property are not empty:
133
+ ```yaml
134
+ - orConditions:
135
+ - when: ~~._filters.label
136
+ is: "" # Shows all when empty
137
+ - andConditions:
138
+ - whenFilterableData: label
139
+ isNotEmpty: true
140
+ - when: ~~._filters.label
141
+ isNotEmpty: true
142
+ - whenFilterableData: label
143
+ contains: ~~._filters.label
144
+ ```
145
+ The `andConditions` wrapper ensures that both the data property and filter value are not empty before attempting the `contains` comparison.
146
+
147
+ 5. **Template Access**: In templates, access properties directly without namespace:
148
+ - ✅ `~.label`, `~.done`, `~.operation`
149
+ - ❌ `~.id.label` (incorrect)
150
+
151
+ ## Filter Types Demonstrated
152
+
153
+ - **Select Filter with "All" option**: Using `is: "all"` to show all items when a special "all" value is selected
154
+ - **Exact String Match**: Using `is` for exact string matching (e.g., status filtering)
155
+ - **Text Search**: Using `contains` for substring matching (case-insensitive) with proper empty checks
156
+
157
+ ## Additional Template Techniques
158
+
159
+ **Conditional Display in Templates**: The example uses `hide` actions to conditionally display badges based on data values. This is a common pattern for showing different UI elements based on data state:
160
+
161
+ ```yaml
162
+ - type: span
163
+ content: "Done"
164
+ actions:
165
+ - what: hide
166
+ when: ~.done
167
+ isNot: "done" # Hide if status is not "done"
168
+ - type: span
169
+ content: "Pending"
170
+ actions:
171
+ - what: hide
172
+ when: ~.done
173
+ isNot: "pending" # Hide if status is not "pending"
174
+ ```
175
+
176
+ This technique is used in the example to display colored status badges, but it's not part of the DataFilter pattern itself - it's just a way to enhance the visual display of filtered data.
177
+
178
+ ## Filter Patterns
179
+
180
+ ### Pattern 1: Select Filter with "All" Option
181
+ ```yaml
182
+ - orConditions:
183
+ - when: ~~._filters.status
184
+ is: "all" # Special value for "show all"
185
+ - whenFilterableData: status
186
+ is: ~~._filters.status # Exact match filter
187
+ ```
188
+
189
+ ### Pattern 2: Text Input Filter (Empty String Check)
190
+ ```yaml
191
+ - orConditions:
192
+ - when: ~~._filters.search
193
+ is: "" # Empty string means "show all"
194
+ - andConditions:
195
+ - whenFilterableData: searchField
196
+ isNotEmpty: true
197
+ - when: ~~._filters.search
198
+ isNotEmpty: true
199
+ - whenFilterableData: searchField
200
+ contains: ~~._filters.search
201
+ ```
202
+
203
+ ## Notes
204
+
205
+ - The `subjectsWithProperty` value (`id` in this example) must exist in every item of the array
206
+ - DataFilter filters the data before rendering, so no `hide` actions are needed in templates
207
+ - All filter conditions use `orConditions` with an empty/"all" check first, allowing "show all" when filters are empty or set to "all"
208
+ - For select elements, prefer using a special value like `"all"` instead of empty strings to avoid UI issues
209
+ - For text inputs, empty strings (`""`) work fine for the "show all" condition
210
+ - When using `contains` for text search, always wrap the condition in `andConditions` with `isNotEmpty` checks to avoid errors with empty values
211
+