@player-ui/player 0.11.0-next.2 → 0.11.0-next.4
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/dist/Player.native.js +61 -1
- package/dist/Player.native.js.map +1 -1
- package/dist/cjs/index.cjs +61 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.legacy-esm.js +61 -1
- package/dist/index.mjs +61 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/view/builder/index.test.ts +29 -1
- package/src/view/builder/index.ts +29 -1
- package/src/view/parser/types.ts +4 -1
- package/src/view/plugins/__tests__/__snapshots__/template.test.ts.snap +328 -48
- package/src/view/plugins/__tests__/template.test.ts +592 -128
- package/src/view/plugins/template.ts +67 -4
- package/types/view/builder/index.d.ts +8 -0
- package/types/view/parser/types.d.ts +3 -1
- package/types/view/plugins/template.d.ts +4 -1
package/package.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"types"
|
|
7
7
|
],
|
|
8
8
|
"name": "@player-ui/player",
|
|
9
|
-
"version": "0.11.0-next.
|
|
9
|
+
"version": "0.11.0-next.4",
|
|
10
10
|
"main": "dist/cjs/index.cjs",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@player-ui/partial-match-registry": "0.11.0-next.
|
|
13
|
-
"@player-ui/make-flow": "0.11.0-next.
|
|
14
|
-
"@player-ui/types": "0.11.0-next.
|
|
12
|
+
"@player-ui/partial-match-registry": "0.11.0-next.4",
|
|
13
|
+
"@player-ui/make-flow": "0.11.0-next.4",
|
|
14
|
+
"@player-ui/types": "0.11.0-next.4",
|
|
15
15
|
"@types/dlv": "^1.1.4",
|
|
16
16
|
"dequal": "^2.0.2",
|
|
17
17
|
"dlv": "^1.1.3",
|
|
@@ -102,6 +102,34 @@ describe("addChild", () => {
|
|
|
102
102
|
const value = Builder.value({ id: 2 });
|
|
103
103
|
Builder.addChild(asset, ["path1", "path2"], value);
|
|
104
104
|
|
|
105
|
-
expect(asset.children?.[0]
|
|
105
|
+
expect(asset.children?.[0]?.path).toStrictEqual(["path1", "path2"]);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe("updateChildrenByPath", () => {
|
|
110
|
+
test("updates children with matching path in the same order", () => {
|
|
111
|
+
const parent = Builder.value();
|
|
112
|
+
const child1 = Builder.value({ foo: "child1Value" });
|
|
113
|
+
const child2 = Builder.value({ foo: "child2Value" });
|
|
114
|
+
const child3 = Builder.value({ foo: "child3Value" });
|
|
115
|
+
|
|
116
|
+
Builder.addChild(parent, "child1", child1);
|
|
117
|
+
// Child 2 has the same path as child 1
|
|
118
|
+
Builder.addChild(parent, "child1", child2);
|
|
119
|
+
Builder.addChild(parent, "child3", child3);
|
|
120
|
+
|
|
121
|
+
// Update matching children
|
|
122
|
+
const updated = Builder.updateChildrenByPath(parent, ["child1"], (child) =>
|
|
123
|
+
Builder.value({
|
|
124
|
+
transformed: true,
|
|
125
|
+
original: (child as any).value?.foo,
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
expect(updated.children).toHaveLength(3);
|
|
130
|
+
// Verify children are in the correct order
|
|
131
|
+
expect(updated.children?.[0]?.path).toStrictEqual(["child1"]);
|
|
132
|
+
expect(updated.children?.[1]?.path).toStrictEqual(["child1"]);
|
|
133
|
+
expect(updated.children?.[2]?.path).toStrictEqual(["child3"]);
|
|
106
134
|
});
|
|
107
135
|
});
|
|
@@ -87,7 +87,7 @@ export class Builder {
|
|
|
87
87
|
node: N,
|
|
88
88
|
path: Node.PathSegment | Node.PathSegment[],
|
|
89
89
|
child: Node.Node,
|
|
90
|
-
) {
|
|
90
|
+
): N {
|
|
91
91
|
child.parent = node as Node.Node;
|
|
92
92
|
|
|
93
93
|
const newChild: Node.Child = {
|
|
@@ -100,4 +100,32 @@ export class Builder {
|
|
|
100
100
|
|
|
101
101
|
return node;
|
|
102
102
|
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Updates children of a node of the same path and preserves order
|
|
106
|
+
*
|
|
107
|
+
* @param node - The node to update children for
|
|
108
|
+
* @param pathToMatch - The path to match against child paths
|
|
109
|
+
* @param mapFn - Function to transform matching children
|
|
110
|
+
*/
|
|
111
|
+
static updateChildrenByPath<T extends Node.ViewOrAsset | Node.Value>(
|
|
112
|
+
node: T,
|
|
113
|
+
pathToMatch: Node.PathSegment[],
|
|
114
|
+
updateFn: (child: Node.Child) => Node.Node,
|
|
115
|
+
): T {
|
|
116
|
+
if (!node.children) return node;
|
|
117
|
+
|
|
118
|
+
// Use map to preserve original order
|
|
119
|
+
const updatedChildren = node.children.map((child) =>
|
|
120
|
+
// Check if paths match exactly
|
|
121
|
+
child.path.join() === pathToMatch.join()
|
|
122
|
+
? { ...child, value: updateFn(child) }
|
|
123
|
+
: child,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
...node,
|
|
128
|
+
children: updatedChildren,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
103
131
|
}
|
package/src/view/parser/types.ts
CHANGED
|
@@ -74,8 +74,11 @@ export declare namespace Node {
|
|
|
74
74
|
/** The number of nested templates so far */
|
|
75
75
|
depth: number;
|
|
76
76
|
|
|
77
|
-
/**
|
|
77
|
+
/** Should the template recompute when data changes */
|
|
78
78
|
dynamic?: boolean;
|
|
79
|
+
|
|
80
|
+
/** Specifies the template placement in relation to existing elements*/
|
|
81
|
+
placement?: "prepend" | "append";
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
export interface Value
|
|
@@ -1,6 +1,119 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`
|
|
3
|
+
exports[`templates > Should preserve order when multiple templates have the same placement 1`] = `
|
|
4
|
+
[
|
|
5
|
+
{
|
|
6
|
+
"asset": {
|
|
7
|
+
"id": "static-value",
|
|
8
|
+
"type": "text",
|
|
9
|
+
"value": "Static value in the collection",
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"asset": {
|
|
14
|
+
"id": "first-0",
|
|
15
|
+
"type": "text",
|
|
16
|
+
"value": "first A",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"asset": {
|
|
21
|
+
"id": "first-1",
|
|
22
|
+
"type": "text",
|
|
23
|
+
"value": "first B",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"asset": {
|
|
28
|
+
"id": "second-0",
|
|
29
|
+
"type": "text",
|
|
30
|
+
"value": "second C",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"asset": {
|
|
35
|
+
"id": "second-1",
|
|
36
|
+
"type": "text",
|
|
37
|
+
"value": "second D",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
]
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
exports[`templates > Works with template items plus value items > Should show dynamic template items first when using placement prepend 1`] = `
|
|
44
|
+
[
|
|
45
|
+
{
|
|
46
|
+
"asset": {
|
|
47
|
+
"id": "dynamic-0",
|
|
48
|
+
"type": "text",
|
|
49
|
+
"value": "item Ginger",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"asset": {
|
|
54
|
+
"id": "dynamic-1",
|
|
55
|
+
"type": "text",
|
|
56
|
+
"value": "item Vokey",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"asset": {
|
|
61
|
+
"id": "value-1",
|
|
62
|
+
"type": "text",
|
|
63
|
+
"value": "First value in the collection",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"asset": {
|
|
68
|
+
"id": "value-2",
|
|
69
|
+
"type": "text",
|
|
70
|
+
"value": "Second value in the collection",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
]
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
exports[`templates > Works with template items plus value items > Should show dynamic template items first when using placement prepend 2`] = `
|
|
77
|
+
[
|
|
78
|
+
{
|
|
79
|
+
"asset": {
|
|
80
|
+
"id": "dynamic-0",
|
|
81
|
+
"type": "text",
|
|
82
|
+
"value": "item Louis",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"asset": {
|
|
87
|
+
"id": "dynamic-1",
|
|
88
|
+
"type": "text",
|
|
89
|
+
"value": "item Bob",
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"asset": {
|
|
94
|
+
"id": "dynamic-2",
|
|
95
|
+
"type": "text",
|
|
96
|
+
"value": "item Nuri",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"asset": {
|
|
101
|
+
"id": "value-1",
|
|
102
|
+
"type": "text",
|
|
103
|
+
"value": "First value in the collection",
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"asset": {
|
|
108
|
+
"id": "value-2",
|
|
109
|
+
"type": "text",
|
|
110
|
+
"value": "Second value in the collection",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
]
|
|
114
|
+
`;
|
|
115
|
+
|
|
116
|
+
exports[`templates > Works with template items plus value items > Should show static template item first when coming before values on lexical order 1`] = `
|
|
4
117
|
[
|
|
5
118
|
{
|
|
6
119
|
"asset": {
|
|
@@ -33,7 +146,7 @@ exports[`dynamic templates > Works with template items plus value items > Should
|
|
|
33
146
|
]
|
|
34
147
|
`;
|
|
35
148
|
|
|
36
|
-
exports[`
|
|
149
|
+
exports[`templates > Works with template items plus value items > Should show static template item last when coming after values on lexical order 1`] = `
|
|
37
150
|
[
|
|
38
151
|
{
|
|
39
152
|
"asset": {
|
|
@@ -66,7 +179,219 @@ exports[`dynamic templates > Works with template items plus value items > Should
|
|
|
66
179
|
]
|
|
67
180
|
`;
|
|
68
181
|
|
|
69
|
-
exports[`templates >
|
|
182
|
+
exports[`templates > Works with template items plus value items > Should show static template items first when using placement prepend 1`] = `
|
|
183
|
+
[
|
|
184
|
+
{
|
|
185
|
+
"asset": {
|
|
186
|
+
"id": "value-0",
|
|
187
|
+
"type": "text",
|
|
188
|
+
"value": "item 1",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"asset": {
|
|
193
|
+
"id": "value-1",
|
|
194
|
+
"type": "text",
|
|
195
|
+
"value": "item 2",
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"asset": {
|
|
200
|
+
"id": "value-2",
|
|
201
|
+
"type": "text",
|
|
202
|
+
"value": "First value in the collection",
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"asset": {
|
|
207
|
+
"id": "value-3",
|
|
208
|
+
"type": "text",
|
|
209
|
+
"value": "Second value in the collection",
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
]
|
|
213
|
+
`;
|
|
214
|
+
|
|
215
|
+
exports[`templates > Works with template items plus value items > Should show static template items last when using placement append 1`] = `
|
|
216
|
+
[
|
|
217
|
+
{
|
|
218
|
+
"asset": {
|
|
219
|
+
"id": "value-2",
|
|
220
|
+
"type": "text",
|
|
221
|
+
"value": "First value in the collection",
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"asset": {
|
|
226
|
+
"id": "value-3",
|
|
227
|
+
"type": "text",
|
|
228
|
+
"value": "Second value in the collection",
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"asset": {
|
|
233
|
+
"id": "value-0",
|
|
234
|
+
"type": "text",
|
|
235
|
+
"value": "item 1",
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"asset": {
|
|
240
|
+
"id": "value-1",
|
|
241
|
+
"type": "text",
|
|
242
|
+
"value": "item 2",
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
]
|
|
246
|
+
`;
|
|
247
|
+
|
|
248
|
+
exports[`templates > Works with template items plus value items > Should support placement for both static and dynamic templates 1`] = `
|
|
249
|
+
[
|
|
250
|
+
{
|
|
251
|
+
"asset": {
|
|
252
|
+
"id": "static-0",
|
|
253
|
+
"type": "text",
|
|
254
|
+
"value": "static Ginger",
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"asset": {
|
|
259
|
+
"id": "static-1",
|
|
260
|
+
"type": "text",
|
|
261
|
+
"value": "static Vokey",
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"asset": {
|
|
266
|
+
"id": "value-1",
|
|
267
|
+
"type": "text",
|
|
268
|
+
"value": "First value in the collection",
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"asset": {
|
|
273
|
+
"id": "value-2",
|
|
274
|
+
"type": "text",
|
|
275
|
+
"value": "Second value in the collection",
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"asset": {
|
|
280
|
+
"id": "dynamic-0",
|
|
281
|
+
"type": "text",
|
|
282
|
+
"value": "dynamic Ginger",
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"asset": {
|
|
287
|
+
"id": "dynamic-1",
|
|
288
|
+
"type": "text",
|
|
289
|
+
"value": "dynamic Vokey",
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
]
|
|
293
|
+
`;
|
|
294
|
+
|
|
295
|
+
exports[`templates > Works with template items plus value items > Should support placement for both static and dynamic templates 2`] = `
|
|
296
|
+
[
|
|
297
|
+
{
|
|
298
|
+
"asset": {
|
|
299
|
+
"id": "static-0",
|
|
300
|
+
"type": "text",
|
|
301
|
+
"value": "static Louis",
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"asset": {
|
|
306
|
+
"id": "static-1",
|
|
307
|
+
"type": "text",
|
|
308
|
+
"value": "static Bob",
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"asset": {
|
|
313
|
+
"id": "value-1",
|
|
314
|
+
"type": "text",
|
|
315
|
+
"value": "First value in the collection",
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"asset": {
|
|
320
|
+
"id": "value-2",
|
|
321
|
+
"type": "text",
|
|
322
|
+
"value": "Second value in the collection",
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"asset": {
|
|
327
|
+
"id": "dynamic-0",
|
|
328
|
+
"type": "text",
|
|
329
|
+
"value": "dynamic Louis",
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
"asset": {
|
|
334
|
+
"id": "dynamic-1",
|
|
335
|
+
"type": "text",
|
|
336
|
+
"value": "dynamic Bob",
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"asset": {
|
|
341
|
+
"id": "dynamic-2",
|
|
342
|
+
"type": "text",
|
|
343
|
+
"value": "dynamic Nuri",
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
]
|
|
347
|
+
`;
|
|
348
|
+
|
|
349
|
+
exports[`templates > works with simple ones 1`] = `
|
|
350
|
+
{
|
|
351
|
+
"children": [
|
|
352
|
+
{
|
|
353
|
+
"path": [
|
|
354
|
+
"values",
|
|
355
|
+
],
|
|
356
|
+
"value": {
|
|
357
|
+
"override": false,
|
|
358
|
+
"parent": [Circular],
|
|
359
|
+
"type": "multi-node",
|
|
360
|
+
"values": [
|
|
361
|
+
{
|
|
362
|
+
"parent": [Circular],
|
|
363
|
+
"type": "value",
|
|
364
|
+
"value": {
|
|
365
|
+
"value": "{{foo.bar.0}}",
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
"parent": [Circular],
|
|
370
|
+
"type": "value",
|
|
371
|
+
"value": {
|
|
372
|
+
"value": "{{foo.bar.1}}",
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"parent": [Circular],
|
|
377
|
+
"type": "value",
|
|
378
|
+
"value": {
|
|
379
|
+
"value": "{{foo.bar.2}}",
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
],
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
"type": "value",
|
|
387
|
+
"value": {
|
|
388
|
+
"id": "foo",
|
|
389
|
+
"type": "collection",
|
|
390
|
+
},
|
|
391
|
+
}
|
|
392
|
+
`;
|
|
393
|
+
|
|
394
|
+
exports[`templates > works with static nested templates 1`] = `
|
|
70
395
|
{
|
|
71
396
|
"children": [
|
|
72
397
|
{
|
|
@@ -233,48 +558,3 @@ exports[`templates > works with nested templates 1`] = `
|
|
|
233
558
|
},
|
|
234
559
|
}
|
|
235
560
|
`;
|
|
236
|
-
|
|
237
|
-
exports[`templates > works with simple ones 1`] = `
|
|
238
|
-
{
|
|
239
|
-
"children": [
|
|
240
|
-
{
|
|
241
|
-
"path": [
|
|
242
|
-
"values",
|
|
243
|
-
],
|
|
244
|
-
"value": {
|
|
245
|
-
"override": false,
|
|
246
|
-
"parent": [Circular],
|
|
247
|
-
"type": "multi-node",
|
|
248
|
-
"values": [
|
|
249
|
-
{
|
|
250
|
-
"parent": [Circular],
|
|
251
|
-
"type": "value",
|
|
252
|
-
"value": {
|
|
253
|
-
"value": "{{foo.bar.0}}",
|
|
254
|
-
},
|
|
255
|
-
},
|
|
256
|
-
{
|
|
257
|
-
"parent": [Circular],
|
|
258
|
-
"type": "value",
|
|
259
|
-
"value": {
|
|
260
|
-
"value": "{{foo.bar.1}}",
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
"parent": [Circular],
|
|
265
|
-
"type": "value",
|
|
266
|
-
"value": {
|
|
267
|
-
"value": "{{foo.bar.2}}",
|
|
268
|
-
},
|
|
269
|
-
},
|
|
270
|
-
],
|
|
271
|
-
},
|
|
272
|
-
},
|
|
273
|
-
],
|
|
274
|
-
"type": "value",
|
|
275
|
-
"value": {
|
|
276
|
-
"id": "foo",
|
|
277
|
-
"type": "collection",
|
|
278
|
-
},
|
|
279
|
-
}
|
|
280
|
-
`;
|