@player-ui/player 0.11.0-next.3 → 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
|
@@ -12,6 +12,8 @@ import type { Options } from "./options";
|
|
|
12
12
|
import type { Resolver } from "../resolver";
|
|
13
13
|
import { hasTemplateKey } from "../parser/utils";
|
|
14
14
|
|
|
15
|
+
const templateSymbol = Symbol("template");
|
|
16
|
+
|
|
15
17
|
export interface TemplateItemInfo {
|
|
16
18
|
/** The index of the data for the current iteration of the template */
|
|
17
19
|
index: number;
|
|
@@ -37,7 +39,12 @@ export type TemplateSubstitutionsFunc = (
|
|
|
37
39
|
export default class TemplatePlugin implements ViewPlugin {
|
|
38
40
|
private readonly options: Options;
|
|
39
41
|
|
|
40
|
-
hooks
|
|
42
|
+
hooks: {
|
|
43
|
+
resolveTemplateSubstitutions: SyncWaterfallHook<
|
|
44
|
+
[TemplateSubstitution[], TemplateItemInfo],
|
|
45
|
+
Record<string, any>
|
|
46
|
+
>;
|
|
47
|
+
} = {
|
|
41
48
|
resolveTemplateSubstitutions: new SyncWaterfallHook<
|
|
42
49
|
[TemplateSubstitution[], TemplateItemInfo]
|
|
43
50
|
>(),
|
|
@@ -106,10 +113,15 @@ export default class TemplatePlugin implements ViewPlugin {
|
|
|
106
113
|
values,
|
|
107
114
|
};
|
|
108
115
|
|
|
116
|
+
// Removes undefined Symbol property
|
|
117
|
+
if (node.placement !== undefined) {
|
|
118
|
+
(result as any)[templateSymbol] = node.placement;
|
|
119
|
+
}
|
|
120
|
+
|
|
109
121
|
return result;
|
|
110
122
|
}
|
|
111
123
|
|
|
112
|
-
applyParser(parser: Parser) {
|
|
124
|
+
applyParser(parser: Parser): void {
|
|
113
125
|
parser.hooks.onCreateASTNode.tap("template", (node) => {
|
|
114
126
|
if (node && node.type === NodeType.Template && !node.dynamic) {
|
|
115
127
|
return this.parseTemplate(
|
|
@@ -122,6 +134,55 @@ export default class TemplatePlugin implements ViewPlugin {
|
|
|
122
134
|
return node;
|
|
123
135
|
});
|
|
124
136
|
|
|
137
|
+
parser.hooks.onCreateASTNode.tap("template", (node) => {
|
|
138
|
+
function getTemplateSymbolValue(node: Node.Node): string | undefined {
|
|
139
|
+
if (node.type === NodeType.MultiNode) {
|
|
140
|
+
return (node as any)[templateSymbol];
|
|
141
|
+
} else if (node.type === NodeType.Template) {
|
|
142
|
+
return node.placement;
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (
|
|
148
|
+
node &&
|
|
149
|
+
(node.type === NodeType.View || node.type === NodeType.Asset) &&
|
|
150
|
+
Array.isArray(node.children)
|
|
151
|
+
) {
|
|
152
|
+
node.children = node.children.sort((a, b) => {
|
|
153
|
+
// compare template output with static values
|
|
154
|
+
const aPath = a.path.join();
|
|
155
|
+
const bPath = b.path.join();
|
|
156
|
+
|
|
157
|
+
const pathsEqual = aPath === bPath;
|
|
158
|
+
|
|
159
|
+
if (pathsEqual) {
|
|
160
|
+
const aPlacement = getTemplateSymbolValue(a.value);
|
|
161
|
+
const bPlacement = getTemplateSymbolValue(b.value);
|
|
162
|
+
|
|
163
|
+
if (aPlacement !== undefined && bPlacement === undefined) {
|
|
164
|
+
return aPlacement === "prepend" ? -1 : 1;
|
|
165
|
+
} else if (bPlacement !== undefined && aPlacement === undefined) {
|
|
166
|
+
return bPlacement === "prepend" ? 1 : -1;
|
|
167
|
+
} else if (aPlacement !== undefined && bPlacement !== undefined) {
|
|
168
|
+
// Both have placement values
|
|
169
|
+
if (aPlacement === bPlacement) {
|
|
170
|
+
return 0; // Same placement, no preference
|
|
171
|
+
}
|
|
172
|
+
// "prepend" should come before "append"
|
|
173
|
+
return aPlacement === "prepend" ? -1 : 1;
|
|
174
|
+
}
|
|
175
|
+
return 0;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Trigger more sorting for nested assets
|
|
179
|
+
return aPath > bPath ? 1 : -1;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return node;
|
|
184
|
+
});
|
|
185
|
+
|
|
125
186
|
parser.hooks.parseNode.tap(
|
|
126
187
|
"template",
|
|
127
188
|
(
|
|
@@ -140,6 +201,7 @@ export default class TemplatePlugin implements ViewPlugin {
|
|
|
140
201
|
data: template.data,
|
|
141
202
|
template: template.value,
|
|
142
203
|
dynamic: template.dynamic ?? false,
|
|
204
|
+
placement: template.placement,
|
|
143
205
|
},
|
|
144
206
|
template,
|
|
145
207
|
);
|
|
@@ -163,7 +225,8 @@ export default class TemplatePlugin implements ViewPlugin {
|
|
|
163
225
|
);
|
|
164
226
|
}
|
|
165
227
|
|
|
166
|
-
applyResolverHooks(resolver: Resolver) {
|
|
228
|
+
applyResolverHooks(resolver: Resolver): void {
|
|
229
|
+
// Transform dynamic templates into MultiNodes
|
|
167
230
|
resolver.hooks.beforeResolve.tap("template", (node, options) => {
|
|
168
231
|
if (node && node.type === NodeType.Template && node.dynamic) {
|
|
169
232
|
return this.parseTemplate(options.parseNode, node, options);
|
|
@@ -173,7 +236,7 @@ export default class TemplatePlugin implements ViewPlugin {
|
|
|
173
236
|
});
|
|
174
237
|
}
|
|
175
238
|
|
|
176
|
-
apply(view: ViewInstance) {
|
|
239
|
+
apply(view: ViewInstance): void {
|
|
177
240
|
view.hooks.parser.tap("template", this.applyParser.bind(this));
|
|
178
241
|
view.hooks.resolver.tap("template", this.applyResolverHooks.bind(this));
|
|
179
242
|
}
|
|
@@ -38,5 +38,13 @@ export declare class Builder {
|
|
|
38
38
|
* @param child - The child node
|
|
39
39
|
*/
|
|
40
40
|
static addChild<N extends Node.BaseWithChildren<NT>, NT extends NodeType>(node: N, path: Node.PathSegment | Node.PathSegment[], child: Node.Node): N;
|
|
41
|
+
/**
|
|
42
|
+
* Updates children of a node of the same path and preserves order
|
|
43
|
+
*
|
|
44
|
+
* @param node - The node to update children for
|
|
45
|
+
* @param pathToMatch - The path to match against child paths
|
|
46
|
+
* @param mapFn - Function to transform matching children
|
|
47
|
+
*/
|
|
48
|
+
static updateChildrenByPath<T extends Node.ViewOrAsset | Node.Value>(node: T, pathToMatch: Node.PathSegment[], updateFn: (child: Node.Child) => Node.Node): T;
|
|
41
49
|
}
|
|
42
50
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -54,8 +54,10 @@ export declare namespace Node {
|
|
|
54
54
|
template: unknown;
|
|
55
55
|
/** The number of nested templates so far */
|
|
56
56
|
depth: number;
|
|
57
|
-
/**
|
|
57
|
+
/** Should the template recompute when data changes */
|
|
58
58
|
dynamic?: boolean;
|
|
59
|
+
/** Specifies the template placement in relation to existing elements*/
|
|
60
|
+
placement?: "prepend" | "append";
|
|
59
61
|
}
|
|
60
62
|
interface Value extends BaseWithChildren<NodeType.Value>, PluginOptions {
|
|
61
63
|
/** A simple node representing a value */
|
|
@@ -22,7 +22,10 @@ export type TemplateSubstitutionsFunc = (baseSubstitutions: TemplateSubstitution
|
|
|
22
22
|
export default class TemplatePlugin implements ViewPlugin {
|
|
23
23
|
private readonly options;
|
|
24
24
|
hooks: {
|
|
25
|
-
resolveTemplateSubstitutions: SyncWaterfallHook<[
|
|
25
|
+
resolveTemplateSubstitutions: SyncWaterfallHook<[
|
|
26
|
+
TemplateSubstitution[],
|
|
27
|
+
TemplateItemInfo
|
|
28
|
+
], Record<string, any>>;
|
|
26
29
|
};
|
|
27
30
|
constructor(options: Options);
|
|
28
31
|
private parseTemplate;
|