@kaskad/component-tree 0.0.1 → 0.0.3
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/fesm2022/kaskad-component-tree.mjs +2380 -0
- package/fesm2022/kaskad-component-tree.mjs.map +1 -0
- package/package.json +10 -10
- package/types/kaskad-component-tree.d.ts +582 -0
- package/esm2022/index.js +0 -12
- package/esm2022/index.js.map +0 -1
- package/esm2022/kaskad-component-tree.js +0 -5
- package/esm2022/kaskad-component-tree.js.map +0 -1
- package/esm2022/lib/component-lookup/index.js +0 -68
- package/esm2022/lib/component-lookup/index.js.map +0 -1
- package/esm2022/lib/component-lookup/traverses/array-traverser.js +0 -18
- package/esm2022/lib/component-lookup/traverses/array-traverser.js.map +0 -1
- package/esm2022/lib/component-lookup/traverses/component-traverser.js +0 -120
- package/esm2022/lib/component-lookup/traverses/component-traverser.js.map +0 -1
- package/esm2022/lib/component-lookup/traverses/index.js +0 -29
- package/esm2022/lib/component-lookup/traverses/index.js.map +0 -1
- package/esm2022/lib/component-lookup/traverses/object-traverser.js +0 -22
- package/esm2022/lib/component-lookup/traverses/object-traverser.js.map +0 -1
- package/esm2022/lib/component-lookup/types.js +0 -1
- package/esm2022/lib/component-lookup/types.js.map +0 -1
- package/esm2022/lib/component-tree-api.js +0 -121
- package/esm2022/lib/component-tree-api.js.map +0 -1
- package/esm2022/lib/computation/computation-frame.js +0 -27
- package/esm2022/lib/computation/computation-frame.js.map +0 -1
- package/esm2022/lib/computation/computation-stack.js +0 -83
- package/esm2022/lib/computation/computation-stack.js.map +0 -1
- package/esm2022/lib/computation/index.js +0 -3
- package/esm2022/lib/computation/index.js.map +0 -1
- package/esm2022/lib/config.js +0 -6
- package/esm2022/lib/config.js.map +0 -1
- package/esm2022/lib/mobx/component.js +0 -110
- package/esm2022/lib/mobx/component.js.map +0 -1
- package/esm2022/lib/mobx/create-root-node.js +0 -21
- package/esm2022/lib/mobx/create-root-node.js.map +0 -1
- package/esm2022/lib/mobx/ref-space.js +0 -25
- package/esm2022/lib/mobx/ref-space.js.map +0 -1
- package/esm2022/lib/mobx/store.js +0 -827
- package/esm2022/lib/mobx/store.js.map +0 -1
- package/esm2022/lib/node/create-node-options.js +0 -16
- package/esm2022/lib/node/create-node-options.js.map +0 -1
- package/esm2022/lib/node/creators/array-creator.js +0 -9
- package/esm2022/lib/node/creators/array-creator.js.map +0 -1
- package/esm2022/lib/node/creators/command-creator.js +0 -16
- package/esm2022/lib/node/creators/command-creator.js.map +0 -1
- package/esm2022/lib/node/creators/component-creator.js +0 -58
- package/esm2022/lib/node/creators/component-creator.js.map +0 -1
- package/esm2022/lib/node/creators/leaf-creator.js +0 -5
- package/esm2022/lib/node/creators/leaf-creator.js.map +0 -1
- package/esm2022/lib/node/creators/map-creator.js +0 -14
- package/esm2022/lib/node/creators/map-creator.js.map +0 -1
- package/esm2022/lib/node/creators/object-creator.js +0 -17
- package/esm2022/lib/node/creators/object-creator.js.map +0 -1
- package/esm2022/lib/node/creators/set-creator.js +0 -13
- package/esm2022/lib/node/creators/set-creator.js.map +0 -1
- package/esm2022/lib/node/creators/shape-creator.js +0 -15
- package/esm2022/lib/node/creators/shape-creator.js.map +0 -1
- package/esm2022/lib/node/creators/variant-shape-creator.js +0 -23
- package/esm2022/lib/node/creators/variant-shape-creator.js.map +0 -1
- package/esm2022/lib/node/guards.js +0 -5
- package/esm2022/lib/node/guards.js.map +0 -1
- package/esm2022/lib/node/node-creation.js +0 -47
- package/esm2022/lib/node/node-creation.js.map +0 -1
- package/esm2022/lib/node/node-type.js +0 -1
- package/esm2022/lib/node/node-type.js.map +0 -1
- package/esm2022/lib/node/node.js +0 -305
- package/esm2022/lib/node/node.js.map +0 -1
- package/esm2022/lib/parsers/index.js +0 -3
- package/esm2022/lib/parsers/index.js.map +0 -1
- package/esm2022/lib/parsers/node-selector.types.js +0 -1
- package/esm2022/lib/parsers/node-selector.types.js.map +0 -1
- package/esm2022/lib/parsers/parse-component-selector.js +0 -43
- package/esm2022/lib/parsers/parse-component-selector.js.map +0 -1
- package/esm2022/lib/parsers/parse-node-selector.js +0 -263
- package/esm2022/lib/parsers/parse-node-selector.js.map +0 -1
- package/esm2022/lib/types/command.js +0 -1
- package/esm2022/lib/types/command.js.map +0 -1
- package/esm2022/lib/types/index.js +0 -5
- package/esm2022/lib/types/index.js.map +0 -1
- package/esm2022/lib/types/node.guards.js +0 -7
- package/esm2022/lib/types/node.guards.js.map +0 -1
- package/esm2022/lib/types/schema.js +0 -1
- package/esm2022/lib/types/schema.js.map +0 -1
- package/esm2022/lib/util/extract-node-value.js +0 -45
- package/esm2022/lib/util/extract-node-value.js.map +0 -1
- package/esm2022/lib/util/format-source.js +0 -7
- package/esm2022/lib/util/format-source.js.map +0 -1
- package/esm2022/lib/util/get-component.js +0 -8
- package/esm2022/lib/util/get-component.js.map +0 -1
- package/esm2022/lib/util/id-generator.js +0 -10
- package/esm2022/lib/util/id-generator.js.map +0 -1
- package/esm2022/lib/util/traverse-node.js +0 -50
- package/esm2022/lib/util/traverse-node.js.map +0 -1
- package/index.d.ts +0 -11
- package/kaskad-component-tree.d.ts +0 -5
- package/lib/component-lookup/index.d.ts +0 -8
- package/lib/component-lookup/traverses/array-traverser.d.ts +0 -3
- package/lib/component-lookup/traverses/component-traverser.d.ts +0 -3
- package/lib/component-lookup/traverses/index.d.ts +0 -9
- package/lib/component-lookup/traverses/object-traverser.d.ts +0 -3
- package/lib/component-lookup/types.d.ts +0 -13
- package/lib/component-tree-api.d.ts +0 -21
- package/lib/computation/computation-frame.d.ts +0 -14
- package/lib/computation/computation-stack.d.ts +0 -48
- package/lib/computation/index.d.ts +0 -2
- package/lib/config.d.ts +0 -4
- package/lib/mobx/component.d.ts +0 -45
- package/lib/mobx/create-root-node.d.ts +0 -3
- package/lib/mobx/ref-space.d.ts +0 -10
- package/lib/mobx/store.d.ts +0 -238
- package/lib/node/create-node-options.d.ts +0 -12
- package/lib/node/creators/array-creator.d.ts +0 -4
- package/lib/node/creators/command-creator.d.ts +0 -4
- package/lib/node/creators/component-creator.d.ts +0 -4
- package/lib/node/creators/leaf-creator.d.ts +0 -4
- package/lib/node/creators/map-creator.d.ts +0 -4
- package/lib/node/creators/object-creator.d.ts +0 -4
- package/lib/node/creators/set-creator.d.ts +0 -4
- package/lib/node/creators/shape-creator.d.ts +0 -4
- package/lib/node/creators/variant-shape-creator.d.ts +0 -4
- package/lib/node/guards.d.ts +0 -3
- package/lib/node/node-creation.d.ts +0 -4
- package/lib/node/node-type.d.ts +0 -49
- package/lib/node/node.d.ts +0 -107
- package/lib/parsers/index.d.ts +0 -5
- package/lib/parsers/node-selector.types.d.ts +0 -25
- package/lib/parsers/parse-component-selector.d.ts +0 -8
- package/lib/parsers/parse-node-selector.d.ts +0 -87
- package/lib/types/command.d.ts +0 -3
- package/lib/types/index.d.ts +0 -4
- package/lib/types/node.guards.d.ts +0 -4
- package/lib/types/schema.d.ts +0 -13
- package/lib/util/extract-node-value.d.ts +0 -3
- package/lib/util/format-source.d.ts +0 -1
- package/lib/util/get-component.d.ts +0 -4
- package/lib/util/id-generator.d.ts +0 -5
- package/lib/util/traverse-node.d.ts +0 -26
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { Delimiters } from '@kaskad/config';
|
|
2
|
-
import { parseComponentSelector } from './parse-component-selector';
|
|
3
|
-
/**
|
|
4
|
-
* Parse a path string into structured segments.
|
|
5
|
-
*
|
|
6
|
-
* ## Path Notation Rules
|
|
7
|
-
*
|
|
8
|
-
* **Dot notation (.)** - Access object properties
|
|
9
|
-
* - `user.profile.name` - Access nested object properties
|
|
10
|
-
* - `config.0` - Access object property named "0" (string key)
|
|
11
|
-
*
|
|
12
|
-
* **Bracket notation ([])** - Access array elements by numeric index
|
|
13
|
-
* - `items[0].name` - Access first array element, then its 'name' property
|
|
14
|
-
* - `matrix[0][1]` - Access multi-dimensional arrays
|
|
15
|
-
*
|
|
16
|
-
* **Optional chaining (?.)** - Safely access potentially missing properties
|
|
17
|
-
* - `user?.profile?.email` - Returns null if any segment is missing
|
|
18
|
-
*
|
|
19
|
-
* **Variable prefix ($)** - Access variables instead of properties
|
|
20
|
-
* - `$config.theme` - Access variable 'config', then its 'theme' property
|
|
21
|
-
* - `$items[0]` - Access variable 'items' array, then first element
|
|
22
|
-
*
|
|
23
|
-
* **Component selector (->)** - Access properties on other components
|
|
24
|
-
* - `&ref->prop.field` - Access 'prop.field' on component with ref
|
|
25
|
-
* - `:Button[disabled=true]->label` - Access 'label' on Button with condition
|
|
26
|
-
* - `^parent->config` - Access 'config' on parent component
|
|
27
|
-
*
|
|
28
|
-
* **Optional component selector (?->)** - Safely access components that might not exist
|
|
29
|
-
* - `&ref?->value` - Returns null if component with ref doesn't exist
|
|
30
|
-
* - `:OptionalType?->property` - Returns null if component type not found
|
|
31
|
-
* - `^Parent?->config` - Returns null if parent doesn't match
|
|
32
|
-
*
|
|
33
|
-
* ## Component Selector Syntax
|
|
34
|
-
*
|
|
35
|
-
* Component selectors support modifiers and conditions:
|
|
36
|
-
* - `&ref` - Select by ref
|
|
37
|
-
* - `:ComponentType` - Select by component type
|
|
38
|
-
* - `^parent` - Select parent component
|
|
39
|
-
* - `[prop=value]` - Filter by property value
|
|
40
|
-
* - Multiple conditions: `:Button[disabled=true][type=submit]`
|
|
41
|
-
*
|
|
42
|
-
* ## Notation Disambiguation
|
|
43
|
-
*
|
|
44
|
-
* The choice between dot and bracket notation determines the access type:
|
|
45
|
-
* ```typescript
|
|
46
|
-
* 'data.0' // Object property named "0" (string key)
|
|
47
|
-
* 'data[0]' // Array element at index 0 (numeric index)
|
|
48
|
-
* 'columns.1' // Object property named "1"
|
|
49
|
-
* 'columns[1]' // Array element at index 1
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* parseNodeSelector('users[0].name')
|
|
54
|
-
* // => { kind: 'property', head: 'users', tail: [{ key: 0, optional: false }, { key: 'name', optional: false }] }
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* parseNodeSelector('config.0')
|
|
58
|
-
* // => { kind: 'property', head: 'config', tail: [{ key: '0', optional: false }] }
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* parseNodeSelector('prop?.nested?.field')
|
|
62
|
-
* // => { kind: 'property', head: 'prop', tail: [{ key: 'nested', optional: true }, { key: 'field', optional: true }] }
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* parseNodeSelector('$varName.field')
|
|
66
|
-
* // => { kind: 'variable', head: 'varName', tail: [{ key: 'field', optional: false }] }
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* parseNodeSelector('&ref->prop.field')
|
|
70
|
-
* // => {
|
|
71
|
-
* // componentSelector: [{ qualifier: 'ref', modifier: '&', conditions: [] }],
|
|
72
|
-
* // kind: 'property',
|
|
73
|
-
* // head: 'prop',
|
|
74
|
-
* // tail: [{ key: 'field', optional: false }]
|
|
75
|
-
* // }
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* parseNodeSelector(':Button[disabled=true]->label.text')
|
|
79
|
-
* // => {
|
|
80
|
-
* // componentSelector: [{ qualifier: 'Button', modifier: ':', conditions: [['disabled', 'true']] }],
|
|
81
|
-
* // kind: 'property',
|
|
82
|
-
* // head: 'label',
|
|
83
|
-
* // tail: [{ key: 'text', optional: false }]
|
|
84
|
-
* // }
|
|
85
|
-
*/
|
|
86
|
-
export function parseNodeSelector(path) {
|
|
87
|
-
if (!path) {
|
|
88
|
-
throw new Error('Empty path provided');
|
|
89
|
-
}
|
|
90
|
-
// Handle variable prefix
|
|
91
|
-
if (path.startsWith(Delimiters.Variable)) {
|
|
92
|
-
const withoutPrefix = path.slice(1);
|
|
93
|
-
// Check for both . and ?. separators
|
|
94
|
-
const dotIndex = withoutPrefix.indexOf(Delimiters.NodePath);
|
|
95
|
-
const optionalIndex = withoutPrefix.indexOf('?.');
|
|
96
|
-
// If no separator found, it's just the variable name
|
|
97
|
-
if (dotIndex === -1 && optionalIndex === -1) {
|
|
98
|
-
return {
|
|
99
|
-
kind: 'variable',
|
|
100
|
-
head: withoutPrefix,
|
|
101
|
-
tail: [],
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
// Find the first separator (. or ?.)
|
|
105
|
-
let firstSeparatorIndex;
|
|
106
|
-
let isOptional;
|
|
107
|
-
if (dotIndex === -1) {
|
|
108
|
-
firstSeparatorIndex = optionalIndex;
|
|
109
|
-
isOptional = true;
|
|
110
|
-
}
|
|
111
|
-
else if (optionalIndex === -1) {
|
|
112
|
-
firstSeparatorIndex = dotIndex;
|
|
113
|
-
isOptional = false;
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
firstSeparatorIndex = Math.min(dotIndex, optionalIndex);
|
|
117
|
-
isOptional = firstSeparatorIndex === optionalIndex;
|
|
118
|
-
}
|
|
119
|
-
const varName = withoutPrefix.substring(0, firstSeparatorIndex);
|
|
120
|
-
const restPath = withoutPrefix.substring(firstSeparatorIndex + (isOptional ? 2 : 1));
|
|
121
|
-
return {
|
|
122
|
-
kind: 'variable',
|
|
123
|
-
head: varName,
|
|
124
|
-
tail: parseSegments(restPath, isOptional), // Pass the optional flag
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
// Handle component selector arrow (both ?-> and ->)
|
|
128
|
-
const optionalArrowIndex = path.indexOf('?->');
|
|
129
|
-
const strictArrowIndex = path.indexOf('->');
|
|
130
|
-
// Determine which arrow to use (prefer ?-> if both are found)
|
|
131
|
-
let arrowIndex = -1;
|
|
132
|
-
let arrowLength = 2;
|
|
133
|
-
let isOptionalComponent = false;
|
|
134
|
-
if (optionalArrowIndex !== -1 && (strictArrowIndex === -1 || optionalArrowIndex < strictArrowIndex)) {
|
|
135
|
-
arrowIndex = optionalArrowIndex;
|
|
136
|
-
arrowLength = 3;
|
|
137
|
-
isOptionalComponent = true;
|
|
138
|
-
}
|
|
139
|
-
else if (strictArrowIndex !== -1) {
|
|
140
|
-
arrowIndex = strictArrowIndex;
|
|
141
|
-
arrowLength = 2;
|
|
142
|
-
isOptionalComponent = false;
|
|
143
|
-
}
|
|
144
|
-
if (arrowIndex !== -1) {
|
|
145
|
-
const componentSelectorStr = path.substring(0, arrowIndex);
|
|
146
|
-
const nodePath = path.substring(arrowIndex + arrowLength);
|
|
147
|
-
const parsed = parseNodeSelector(nodePath);
|
|
148
|
-
return {
|
|
149
|
-
component: {
|
|
150
|
-
selector: parseComponentSelector(componentSelectorStr),
|
|
151
|
-
optional: isOptionalComponent,
|
|
152
|
-
},
|
|
153
|
-
kind: parsed.kind,
|
|
154
|
-
head: parsed.head,
|
|
155
|
-
tail: parsed.tail,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
// Regular property path
|
|
159
|
-
return parsePropertyPath(path);
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Parse a property path (no variable prefix or component selector)
|
|
163
|
-
*/
|
|
164
|
-
function parsePropertyPath(path) {
|
|
165
|
-
if (!path) {
|
|
166
|
-
throw new Error('Empty property path provided');
|
|
167
|
-
}
|
|
168
|
-
const allSegments = parseSegments(path);
|
|
169
|
-
if (allSegments.length === 0) {
|
|
170
|
-
throw new Error('Empty property path provided');
|
|
171
|
-
}
|
|
172
|
-
const [first, ...rest] = allSegments;
|
|
173
|
-
return {
|
|
174
|
-
kind: 'property',
|
|
175
|
-
head: first.key,
|
|
176
|
-
tail: rest,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Parse path segments, handling optional chaining and array notation
|
|
181
|
-
* @param path - The path to parse
|
|
182
|
-
* @param startOptional - If true, the first segment should be marked as optional
|
|
183
|
-
*/
|
|
184
|
-
function parseSegments(path, startOptional = false) {
|
|
185
|
-
if (!path)
|
|
186
|
-
return [];
|
|
187
|
-
const segments = [];
|
|
188
|
-
let current = '';
|
|
189
|
-
let nextOptional = startOptional; // Start with the passed optional flag
|
|
190
|
-
let i = 0;
|
|
191
|
-
while (i < path.length) {
|
|
192
|
-
const char = path[i];
|
|
193
|
-
const nextChar = path[i + 1];
|
|
194
|
-
// Handle optional chaining ?.
|
|
195
|
-
if (char === '?' && nextChar === '.') {
|
|
196
|
-
if (current) {
|
|
197
|
-
segments.push(makeSegment(current, nextOptional, false));
|
|
198
|
-
current = '';
|
|
199
|
-
}
|
|
200
|
-
nextOptional = true;
|
|
201
|
-
i += 2;
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
// Handle array bracket notation [0]
|
|
205
|
-
if (char === '[') {
|
|
206
|
-
if (current) {
|
|
207
|
-
segments.push(makeSegment(current, nextOptional, false));
|
|
208
|
-
current = '';
|
|
209
|
-
nextOptional = false;
|
|
210
|
-
}
|
|
211
|
-
let index = '';
|
|
212
|
-
i++;
|
|
213
|
-
while (i < path.length && path[i] !== ']') {
|
|
214
|
-
index += path[i];
|
|
215
|
-
i++;
|
|
216
|
-
}
|
|
217
|
-
if (path[i] === ']') {
|
|
218
|
-
segments.push(makeSegment(index, nextOptional, true)); // fromBracket = true
|
|
219
|
-
i++; // Skip ]
|
|
220
|
-
// Skip following . if present
|
|
221
|
-
if (path[i] === '.')
|
|
222
|
-
i++;
|
|
223
|
-
}
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
// Handle regular . separator
|
|
227
|
-
if (char === '.') {
|
|
228
|
-
if (current) {
|
|
229
|
-
segments.push(makeSegment(current, nextOptional, false));
|
|
230
|
-
current = '';
|
|
231
|
-
nextOptional = false;
|
|
232
|
-
}
|
|
233
|
-
i++;
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
current += char;
|
|
237
|
-
i++;
|
|
238
|
-
}
|
|
239
|
-
if (current) {
|
|
240
|
-
segments.push(makeSegment(current, nextOptional, false));
|
|
241
|
-
}
|
|
242
|
-
return segments;
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Create a path segment, parsing numbers only for bracket notation.
|
|
246
|
-
* Dot notation keeps keys as strings to allow object properties named "0", "1", etc.
|
|
247
|
-
*
|
|
248
|
-
* @param key - The segment key
|
|
249
|
-
* @param optional - Whether this segment uses optional chaining
|
|
250
|
-
* @param fromBracket - True if this came from bracket notation [0], false if from dot notation
|
|
251
|
-
*/
|
|
252
|
-
function makeSegment(key, optional, fromBracket = false) {
|
|
253
|
-
// Only convert to number if it came from bracket notation
|
|
254
|
-
if (fromBracket) {
|
|
255
|
-
const asNumber = Number(key);
|
|
256
|
-
if (!Number.isNaN(asNumber)) {
|
|
257
|
-
return { key: asNumber, optional };
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
// Keep as string for dot notation or non-numeric bracket content
|
|
261
|
-
return { key, optional };
|
|
262
|
-
}
|
|
263
|
-
//# sourceMappingURL=parse-node-selector.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse-node-selector.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/parsers/parse-node-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import { Delimiters } from '@kaskad/config';\n\nimport { NodeSelector, PathSegment } from './node-selector.types';\nimport { parseComponentSelector } from './parse-component-selector';\n\nexport type PathPart = string | number;\nexport type PathArray = PathPart[];\n\n/**\n * Parse a path string into structured segments.\n *\n * ## Path Notation Rules\n *\n * **Dot notation (.)** - Access object properties\n * - `user.profile.name` - Access nested object properties\n * - `config.0` - Access object property named \"0\" (string key)\n *\n * **Bracket notation ([])** - Access array elements by numeric index\n * - `items[0].name` - Access first array element, then its 'name' property\n * - `matrix[0][1]` - Access multi-dimensional arrays\n *\n * **Optional chaining (?.)** - Safely access potentially missing properties\n * - `user?.profile?.email` - Returns null if any segment is missing\n *\n * **Variable prefix ($)** - Access variables instead of properties\n * - `$config.theme` - Access variable 'config', then its 'theme' property\n * - `$items[0]` - Access variable 'items' array, then first element\n *\n * **Component selector (->)** - Access properties on other components\n * - `&ref->prop.field` - Access 'prop.field' on component with ref\n * - `:Button[disabled=true]->label` - Access 'label' on Button with condition\n * - `^parent->config` - Access 'config' on parent component\n *\n * **Optional component selector (?->)** - Safely access components that might not exist\n * - `&ref?->value` - Returns null if component with ref doesn't exist\n * - `:OptionalType?->property` - Returns null if component type not found\n * - `^Parent?->config` - Returns null if parent doesn't match\n *\n * ## Component Selector Syntax\n *\n * Component selectors support modifiers and conditions:\n * - `&ref` - Select by ref\n * - `:ComponentType` - Select by component type\n * - `^parent` - Select parent component\n * - `[prop=value]` - Filter by property value\n * - Multiple conditions: `:Button[disabled=true][type=submit]`\n *\n * ## Notation Disambiguation\n *\n * The choice between dot and bracket notation determines the access type:\n * ```typescript\n * 'data.0' // Object property named \"0\" (string key)\n * 'data[0]' // Array element at index 0 (numeric index)\n * 'columns.1' // Object property named \"1\"\n * 'columns[1]' // Array element at index 1\n * ```\n *\n * @example\n * parseNodeSelector('users[0].name')\n * // => { kind: 'property', head: 'users', tail: [{ key: 0, optional: false }, { key: 'name', optional: false }] }\n *\n * @example\n * parseNodeSelector('config.0')\n * // => { kind: 'property', head: 'config', tail: [{ key: '0', optional: false }] }\n *\n * @example\n * parseNodeSelector('prop?.nested?.field')\n * // => { kind: 'property', head: 'prop', tail: [{ key: 'nested', optional: true }, { key: 'field', optional: true }] }\n *\n * @example\n * parseNodeSelector('$varName.field')\n * // => { kind: 'variable', head: 'varName', tail: [{ key: 'field', optional: false }] }\n *\n * @example\n * parseNodeSelector('&ref->prop.field')\n * // => {\n * // componentSelector: [{ qualifier: 'ref', modifier: '&', conditions: [] }],\n * // kind: 'property',\n * // head: 'prop',\n * // tail: [{ key: 'field', optional: false }]\n * // }\n *\n * @example\n * parseNodeSelector(':Button[disabled=true]->label.text')\n * // => {\n * // componentSelector: [{ qualifier: 'Button', modifier: ':', conditions: [['disabled', 'true']] }],\n * // kind: 'property',\n * // head: 'label',\n * // tail: [{ key: 'text', optional: false }]\n * // }\n */\nexport function parseNodeSelector(path: string): NodeSelector {\n if (!path) {\n throw new Error('Empty path provided');\n }\n\n // Handle variable prefix\n if (path.startsWith(Delimiters.Variable)) {\n const withoutPrefix = path.slice(1);\n\n // Check for both . and ?. separators\n const dotIndex = withoutPrefix.indexOf(Delimiters.NodePath);\n const optionalIndex = withoutPrefix.indexOf('?.');\n\n // If no separator found, it's just the variable name\n if (dotIndex === -1 && optionalIndex === -1) {\n return {\n kind: 'variable',\n head: withoutPrefix,\n tail: [],\n };\n }\n\n // Find the first separator (. or ?.)\n let firstSeparatorIndex: number;\n let isOptional: boolean;\n\n if (dotIndex === -1) {\n firstSeparatorIndex = optionalIndex;\n isOptional = true;\n } else if (optionalIndex === -1) {\n firstSeparatorIndex = dotIndex;\n isOptional = false;\n } else {\n firstSeparatorIndex = Math.min(dotIndex, optionalIndex);\n isOptional = firstSeparatorIndex === optionalIndex;\n }\n\n const varName = withoutPrefix.substring(0, firstSeparatorIndex);\n const restPath = withoutPrefix.substring(firstSeparatorIndex + (isOptional ? 2 : 1));\n\n return {\n kind: 'variable',\n head: varName,\n tail: parseSegments(restPath, isOptional), // Pass the optional flag\n };\n }\n\n // Handle component selector arrow (both ?-> and ->)\n const optionalArrowIndex = path.indexOf('?->');\n const strictArrowIndex = path.indexOf('->');\n\n // Determine which arrow to use (prefer ?-> if both are found)\n let arrowIndex = -1;\n let arrowLength = 2;\n let isOptionalComponent = false;\n\n if (optionalArrowIndex !== -1 && (strictArrowIndex === -1 || optionalArrowIndex < strictArrowIndex)) {\n arrowIndex = optionalArrowIndex;\n arrowLength = 3;\n isOptionalComponent = true;\n } else if (strictArrowIndex !== -1) {\n arrowIndex = strictArrowIndex;\n arrowLength = 2;\n isOptionalComponent = false;\n }\n\n if (arrowIndex !== -1) {\n const componentSelectorStr = path.substring(0, arrowIndex);\n const nodePath = path.substring(arrowIndex + arrowLength);\n const parsed = parseNodeSelector(nodePath);\n\n return {\n component: {\n selector: parseComponentSelector(componentSelectorStr),\n optional: isOptionalComponent,\n },\n kind: parsed.kind,\n head: parsed.head,\n tail: parsed.tail,\n };\n }\n\n // Regular property path\n return parsePropertyPath(path);\n}\n\n/**\n * Parse a property path (no variable prefix or component selector)\n */\nfunction parsePropertyPath(path: string): NodeSelector {\n if (!path) {\n throw new Error('Empty property path provided');\n }\n\n const allSegments = parseSegments(path);\n\n if (allSegments.length === 0) {\n throw new Error('Empty property path provided');\n }\n\n const [first, ...rest] = allSegments;\n\n return {\n kind: 'property',\n head: first.key as string,\n tail: rest,\n };\n}\n\n/**\n * Parse path segments, handling optional chaining and array notation\n * @param path - The path to parse\n * @param startOptional - If true, the first segment should be marked as optional\n */\nfunction parseSegments(path: string, startOptional = false): PathSegment[] {\n if (!path) return [];\n\n const segments: PathSegment[] = [];\n let current = '';\n let nextOptional = startOptional; // Start with the passed optional flag\n let i = 0;\n\n while (i < path.length) {\n const char = path[i];\n const nextChar = path[i + 1];\n\n // Handle optional chaining ?.\n if (char === '?' && nextChar === '.') {\n if (current) {\n segments.push(makeSegment(current, nextOptional, false));\n current = '';\n }\n nextOptional = true;\n i += 2;\n continue;\n }\n\n // Handle array bracket notation [0]\n if (char === '[') {\n if (current) {\n segments.push(makeSegment(current, nextOptional, false));\n current = '';\n nextOptional = false;\n }\n\n let index = '';\n i++;\n while (i < path.length && path[i] !== ']') {\n index += path[i];\n i++;\n }\n\n if (path[i] === ']') {\n segments.push(makeSegment(index, nextOptional, true)); // fromBracket = true\n i++; // Skip ]\n\n // Skip following . if present\n if (path[i] === '.') i++;\n }\n continue;\n }\n\n // Handle regular . separator\n if (char === '.') {\n if (current) {\n segments.push(makeSegment(current, nextOptional, false));\n current = '';\n nextOptional = false;\n }\n i++;\n continue;\n }\n\n current += char;\n i++;\n }\n\n if (current) {\n segments.push(makeSegment(current, nextOptional, false));\n }\n\n return segments;\n}\n\n/**\n * Create a path segment, parsing numbers only for bracket notation.\n * Dot notation keeps keys as strings to allow object properties named \"0\", \"1\", etc.\n *\n * @param key - The segment key\n * @param optional - Whether this segment uses optional chaining\n * @param fromBracket - True if this came from bracket notation [0], false if from dot notation\n */\nfunction makeSegment(key: string, optional: boolean, fromBracket = false): PathSegment {\n // Only convert to number if it came from bracket notation\n if (fromBracket) {\n const asNumber = Number(key);\n if (!Number.isNaN(asNumber)) {\n return { key: asNumber, optional };\n }\n }\n\n // Keep as string for dot notation or non-numeric bracket content\n return { key, optional };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=command.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/types/command.ts"],"names":[],"mappings":"","sourcesContent":["export interface CommandRef<_TParams = unknown[], TResult = unknown> {\n execute(...params: unknown[]): Promise<TResult>;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC","sourcesContent":["export * from './schema';\nexport * from './command';\nexport * from './node.guards';\nexport * from '../computation';\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node.guards.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/types/node.guards.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,WAAW,CAAC,IAA6B;IACvD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAA6B;IACzD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC;AAC3C,CAAC","sourcesContent":["import { ValueType } from '@kaskad/types';\n\nimport { AbstractNode, ArrayNode, CommandNode } from '../node/node';\n\nexport function isArrayNode(node: AbstractNode<ValueType>): node is ArrayNode {\n return node.valueType.type === 'array';\n}\n\nexport function isCommandNode(node: AbstractNode<ValueType>): node is CommandNode {\n return node.valueType.type === 'command';\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/types/schema.ts"],"names":[],"mappings":"","sourcesContent":["import { ComponentId } from '@kaskad/types';\n\nimport { CommandNode } from '../node/node';\n\nexport interface CommandNodeStructure {\n runnerType: string;\n owner: ComponentId;\n target: string;\n init?: string;\n finalize?: string;\n}\n\nexport interface NodeChangeHandler {\n readonly selector: string;\n readonly command: CommandNode;\n}\n"]}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ComponentStore } from '../mobx/store';
|
|
2
|
-
const componentIdExtractors = {
|
|
3
|
-
array: (value, ids) => {
|
|
4
|
-
if (!Array.isArray(value))
|
|
5
|
-
return; // the check is needed for booleanInputGroup value proxies (TODO: verify)
|
|
6
|
-
for (const node of value) {
|
|
7
|
-
extractComponentsIds(node, ids);
|
|
8
|
-
}
|
|
9
|
-
},
|
|
10
|
-
object: (value, ids) => {
|
|
11
|
-
if (!value)
|
|
12
|
-
return;
|
|
13
|
-
for (const node of Object.values(value)) {
|
|
14
|
-
extractComponentsIds(node, ids);
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
map: (value, ids) => {
|
|
18
|
-
if (!value)
|
|
19
|
-
return;
|
|
20
|
-
for (const node of Object.values(value)) {
|
|
21
|
-
extractComponentsIds(node, ids);
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
component: (value, ids) => {
|
|
25
|
-
if (!value)
|
|
26
|
-
return;
|
|
27
|
-
const componentId = value;
|
|
28
|
-
ids.push(componentId);
|
|
29
|
-
const component = ComponentStore.getInstance().getComponent(componentId);
|
|
30
|
-
if (component) {
|
|
31
|
-
for (const [, propNode] of component.props) {
|
|
32
|
-
extractComponentsIds(propNode, ids);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
export function extractComponentsIds(node, ids = []) {
|
|
38
|
-
const value = node.structure;
|
|
39
|
-
const extractor = componentIdExtractors[node.valueType.type];
|
|
40
|
-
if (extractor) {
|
|
41
|
-
extractor(value, ids);
|
|
42
|
-
}
|
|
43
|
-
return ids;
|
|
44
|
-
}
|
|
45
|
-
//# sourceMappingURL=extract-node-value.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extract-node-value.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/util/extract-node-value.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,MAAM,qBAAqB,GAAiE;IAC1F,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACpB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,yEAAyE;QAC5G,KAAK,MAAM,IAAI,IAAI,KAAkC,EAAE,CAAC;YACtD,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAgD,CAAC,EAAE,CAAC;YACnF,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAClB,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAgD,CAAC,EAAE,CAAC;YACnF,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACxB,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,WAAW,GAAG,KAAoB,CAAC;QACzC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEtB,MAAM,SAAS,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QACzE,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,MAAM,CAAC,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;gBAC3C,oBAAoB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,IAA6B,EAAE,MAAqB,EAAE;IACzF,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC;IAC7B,MAAM,SAAS,GAAG,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAE7D,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["import { ComponentId, ValueType } from '@kaskad/types';\n\nimport { ComponentStore } from '../mobx/store';\nimport { AbstractNode } from '../node/node';\n\nconst componentIdExtractors: Record<string, (value: unknown, ids: ComponentId[]) => void> = {\n array: (value, ids) => {\n if (!Array.isArray(value)) return; // the check is needed for booleanInputGroup value proxies (TODO: verify)\n for (const node of value as AbstractNode<ValueType>[]) {\n extractComponentsIds(node, ids);\n }\n },\n object: (value, ids) => {\n if (!value) return;\n for (const node of Object.values(value as Record<string, AbstractNode<ValueType>>)) {\n extractComponentsIds(node, ids);\n }\n },\n map: (value, ids) => {\n if (!value) return;\n for (const node of Object.values(value as Record<string, AbstractNode<ValueType>>)) {\n extractComponentsIds(node, ids);\n }\n },\n component: (value, ids) => {\n if (!value) return;\n const componentId = value as ComponentId;\n ids.push(componentId);\n\n const component = ComponentStore.getInstance().getComponent(componentId);\n if (component) {\n for (const [, propNode] of component.props) {\n extractComponentsIds(propNode, ids);\n }\n }\n },\n};\n\nexport function extractComponentsIds(node: AbstractNode<ValueType>, ids: ComponentId[] = []): ComponentId[] {\n const value = node.structure;\n const extractor = componentIdExtractors[node.valueType.type];\n\n if (extractor) {\n extractor(value, ids);\n }\n\n return ids;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"format-source.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/util/format-source.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,SAAoC,EAAE,IAA0B;IAC3F,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,OAAO,IAAI,SAAS,GAAG,OAAO,GAAG,CAAC;AACpC,CAAC","sourcesContent":["export function formatSource(sourceUrl: string | null | undefined, path?: (string | number)[]): string {\n if (!sourceUrl) return '';\n const pathStr = path?.length ? ` @ ${path.join('.')}` : '';\n return `[${sourceUrl}${pathStr}]`;\n}\n"]}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ComponentStore } from '../mobx/store';
|
|
2
|
-
export function getComponent(node) {
|
|
3
|
-
if (!node.position.componentId) {
|
|
4
|
-
throw new Error('Node does not have a component context');
|
|
5
|
-
}
|
|
6
|
-
return ComponentStore.getInstance().getComponentOrThrow(node.position.componentId);
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=get-component.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-component.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/util/get-component.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,MAAM,UAAU,YAAY,CAAC,IAA6B;IACxD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,cAAc,CAAC,WAAW,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACrF,CAAC","sourcesContent":["import { ValueType } from '@kaskad/types';\n\nimport { TComponent } from '../mobx/component';\nimport { ComponentStore } from '../mobx/store';\nimport { AbstractNode } from '../node/node';\n\nexport function getComponent(node: AbstractNode<ValueType>): TComponent {\n if (!node.position.componentId) {\n throw new Error('Node does not have a component context');\n }\n return ComponentStore.getInstance().getComponentOrThrow(node.position.componentId);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"id-generator.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/util/id-generator.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,SAAS,EAAE,CAAC;IACZ,UAAU;QACR,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvE,CAAC;IACD,KAAK;QACH,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACrB,CAAC;CACF,CAAC","sourcesContent":["export const componentIdGenerator = {\n increment: 0,\n generateId() {\n return ['csid', ++this.increment].filter((item) => !!item).join('-');\n },\n reset() {\n this.increment = 0;\n },\n};\n"]}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Traverse a node using parsed path segments, respecting optional chaining.
|
|
3
|
-
*
|
|
4
|
-
* @param node - The starting node
|
|
5
|
-
* @param segments - Array of path segments to traverse
|
|
6
|
-
* @returns The found node, or null if not found and optional chaining was used
|
|
7
|
-
* @throws Error if a required segment is not found
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* const userNode = component.getNode('user');
|
|
11
|
-
* const nameNode = traverseNode(userNode, [
|
|
12
|
-
* { key: 'profile', optional: false },
|
|
13
|
-
* { key: 'name', optional: false }
|
|
14
|
-
* ]);
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* // With optional chaining - returns null instead of throwing
|
|
18
|
-
* const emailNode = traverseNode(userNode, [
|
|
19
|
-
* { key: 'contact', optional: true },
|
|
20
|
-
* { key: 'email', optional: false }
|
|
21
|
-
* ]);
|
|
22
|
-
*/
|
|
23
|
-
export function traverseNode(node, segments) {
|
|
24
|
-
if (segments.length === 0) {
|
|
25
|
-
return node;
|
|
26
|
-
}
|
|
27
|
-
const [head, ...tail] = segments;
|
|
28
|
-
const found = node.getNodeByPath([head.key]);
|
|
29
|
-
if (!found) {
|
|
30
|
-
if (head.optional) {
|
|
31
|
-
return null; // Optional chaining returns null
|
|
32
|
-
}
|
|
33
|
-
// Check if this is a shape/object-like node with null value
|
|
34
|
-
// In this case, accessing properties should return null instead of throwing
|
|
35
|
-
// This is common in reactive systems where shape values might not be initialized yet
|
|
36
|
-
if (node.nodeType === 'shape' ||
|
|
37
|
-
node.nodeType === 'variantShape' ||
|
|
38
|
-
node.nodeType === 'object' ||
|
|
39
|
-
node.nodeType === 'map') {
|
|
40
|
-
const extracted = node.extractedValue;
|
|
41
|
-
if (extracted === null || extracted === undefined) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
throw new Error(`Cannot access ${typeof head.key === 'number' ? 'index' : 'property'} ` +
|
|
46
|
-
`'${head.key}' on ${node.nodeType} node at path ${node.position.path.join('.')}`);
|
|
47
|
-
}
|
|
48
|
-
return traverseNode(found, tail);
|
|
49
|
-
}
|
|
50
|
-
//# sourceMappingURL=traverse-node.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"traverse-node.js","sourceRoot":"","sources":["../../../../../../libs/component-tree/src/lib/util/traverse-node.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,YAAY,CAAC,IAA6B,EAAE,QAAuB;IACjF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAE7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,CAAC,iCAAiC;QAChD,CAAC;QAED,4DAA4D;QAC5D,4EAA4E;QAC5E,qFAAqF;QACrF,IACE,IAAI,CAAC,QAAQ,KAAK,OAAO;YACzB,IAAI,CAAC,QAAQ,KAAK,cAAc;YAChC,IAAI,CAAC,QAAQ,KAAK,QAAQ;YAC1B,IAAI,CAAC,QAAQ,KAAK,KAAK,EACvB,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC;YACtC,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAClD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CACb,iBAAiB,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,GAAG;YACrE,IAAI,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,QAAQ,iBAAiB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACnF,CAAC;IACJ,CAAC;IAED,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC","sourcesContent":["import { ValueType } from '@kaskad/types';\n\nimport { AbstractNode } from '../node/node';\nimport { PathSegment } from '../parsers';\n\n/**\n * Traverse a node using parsed path segments, respecting optional chaining.\n *\n * @param node - The starting node\n * @param segments - Array of path segments to traverse\n * @returns The found node, or null if not found and optional chaining was used\n * @throws Error if a required segment is not found\n *\n * @example\n * const userNode = component.getNode('user');\n * const nameNode = traverseNode(userNode, [\n * { key: 'profile', optional: false },\n * { key: 'name', optional: false }\n * ]);\n *\n * @example\n * // With optional chaining - returns null instead of throwing\n * const emailNode = traverseNode(userNode, [\n * { key: 'contact', optional: true },\n * { key: 'email', optional: false }\n * ]);\n */\nexport function traverseNode(node: AbstractNode<ValueType>, segments: PathSegment[]): AbstractNode<ValueType> | null {\n if (segments.length === 0) {\n return node;\n }\n\n const [head, ...tail] = segments;\n const found = node.getNodeByPath([head.key]);\n\n if (!found) {\n if (head.optional) {\n return null; // Optional chaining returns null\n }\n\n // Check if this is a shape/object-like node with null value\n // In this case, accessing properties should return null instead of throwing\n // This is common in reactive systems where shape values might not be initialized yet\n if (\n node.nodeType === 'shape' ||\n node.nodeType === 'variantShape' ||\n node.nodeType === 'object' ||\n node.nodeType === 'map'\n ) {\n const extracted = node.extractedValue;\n if (extracted === null || extracted === undefined) {\n return null;\n }\n }\n\n throw new Error(\n `Cannot access ${typeof head.key === 'number' ? 'index' : 'property'} ` +\n `'${head.key}' on ${node.nodeType} node at path ${node.position.path.join('.')}`,\n );\n }\n\n return traverseNode(found, tail);\n}\n"]}
|
package/index.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export * from './lib/types';
|
|
2
|
-
export * from './lib/node/node';
|
|
3
|
-
export * from './lib/node/node-type';
|
|
4
|
-
export * from './lib/mobx/component';
|
|
5
|
-
export * from './lib/mobx/ref-space';
|
|
6
|
-
export * from './lib/mobx/store';
|
|
7
|
-
export * from './lib/mobx/create-root-node';
|
|
8
|
-
export * from './lib/util/get-component';
|
|
9
|
-
export * from './lib/util/format-source';
|
|
10
|
-
export * from './lib/config';
|
|
11
|
-
export * from './lib/component-tree-api';
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ComponentId } from '@kaskad/types';
|
|
2
|
-
import { TComponent } from '../mobx/component';
|
|
3
|
-
import { parseComponentSelector, SelectorSegment } from '../parsers';
|
|
4
|
-
export { parseComponentSelector };
|
|
5
|
-
export type { SelectorSegment };
|
|
6
|
-
export declare function findComponent(relativeTo: ComponentId, selector: SelectorSegment[]): TComponent | null;
|
|
7
|
-
export declare function findComponents(relativeTo: ComponentId, selector: SelectorSegment[]): TComponent[];
|
|
8
|
-
export declare function findComponentsIds(relativeTo: ComponentId, selector: SelectorSegment[]): ComponentId[];
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ValueType } from '@kaskad/types';
|
|
2
|
-
import { Context, NodeQueue, TraverseResult } from '../types';
|
|
3
|
-
type TraversFn = (ctx: Context<ValueType>, nodeQueue: NodeQueue, foundComponents: TraverseResult) => void;
|
|
4
|
-
type Registry = {
|
|
5
|
-
_registry: Record<string, unknown>;
|
|
6
|
-
get(key: string): TraversFn;
|
|
7
|
-
};
|
|
8
|
-
export declare const traversesRegistry: Registry;
|
|
9
|
-
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { ComponentId, ValueType } from '@kaskad/types';
|
|
2
|
-
import { NodeExtractedValue } from '../node/node-type';
|
|
3
|
-
import { SelectorSegment } from '../parsers';
|
|
4
|
-
export interface Context<T extends ValueType> {
|
|
5
|
-
currentNode: {
|
|
6
|
-
valueType: T;
|
|
7
|
-
value: NodeExtractedValue<T> | null;
|
|
8
|
-
};
|
|
9
|
-
relativeTo: ComponentId;
|
|
10
|
-
selectorSegments: SelectorSegment[];
|
|
11
|
-
}
|
|
12
|
-
export type NodeQueue = Array<Context<ValueType>>;
|
|
13
|
-
export type TraverseResult = ComponentId[];
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { ComponentId, ValueType } from '@kaskad/types';
|
|
2
|
-
import { TComponent } from './mobx/component';
|
|
3
|
-
import { AbstractNode } from './node/node';
|
|
4
|
-
export declare class ComponentTreeApi {
|
|
5
|
-
private static store;
|
|
6
|
-
static findComponent(relativeTo: ComponentId, componentSelector: string): TComponent | null;
|
|
7
|
-
static findComponentsIds(relativeTo: ComponentId, componentSelector: string): ComponentId[];
|
|
8
|
-
static findComponents(relativeTo: ComponentId, componentSelector: string): TComponent[];
|
|
9
|
-
static getComponent(relativeTo: ComponentId, componentSelector: string): TComponent;
|
|
10
|
-
static findNode(relativeTo: ComponentId, componentSelector: string): AbstractNode<ValueType> | null;
|
|
11
|
-
static getNode(relativeTo: ComponentId, componentSelector: string): AbstractNode<ValueType>;
|
|
12
|
-
static collectValuesArray<T>(componentId: ComponentId, componentSelector: string, nodeSelector: string): T;
|
|
13
|
-
static collectValuesMap<T>(componentId: ComponentId, componentSelector: string, keyNodeSelector: string, valueNodeSelector: string): T;
|
|
14
|
-
static isCommandRunning(componentId: ComponentId, selector: string): boolean;
|
|
15
|
-
static runCommandNode(componentId: ComponentId, selector: string, ...args: unknown[]): unknown;
|
|
16
|
-
static setNodeRawSchema(componentId: ComponentId, selector: string, value: unknown): void;
|
|
17
|
-
static appendArrayItem(componentId: ComponentId, selector: string, item: unknown): void;
|
|
18
|
-
static insertArrayItem(componentId: ComponentId, selector: string, index: number, item: unknown): void;
|
|
19
|
-
static removeArrayItem(componentId: ComponentId, selector: string, index: number): void;
|
|
20
|
-
static replaceArrayItem(componentId: ComponentId, selector: string, index: number, item: unknown): void;
|
|
21
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ComputationSchema } from '@kaskad/types';
|
|
2
|
-
import { IReactionDisposer } from 'mobx';
|
|
3
|
-
export declare class ComputationFrame {
|
|
4
|
-
readonly schema: ComputationSchema;
|
|
5
|
-
readonly disposers: IReactionDisposer[];
|
|
6
|
-
activated: boolean;
|
|
7
|
-
constructor(schema: ComputationSchema, disposers?: IReactionDisposer[], activated?: boolean);
|
|
8
|
-
/**
|
|
9
|
-
* Mark this computation frame as activated.
|
|
10
|
-
* This is an action that ensures MobX compliance.
|
|
11
|
-
*/
|
|
12
|
-
markActivated(): void;
|
|
13
|
-
dispose(): void;
|
|
14
|
-
}
|