@elementor/editor-canvas 3.35.0-418 → 3.35.0-420
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/index.d.mts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +44 -43
- package/dist/index.mjs +44 -42
- package/package.json +18 -18
- package/src/index.ts +1 -2
- package/src/legacy/create-templated-element-type.ts +46 -6
- package/src/legacy/types.ts +15 -0
- package/src/renderers/__tests__/create-props-resolver.test.ts +149 -0
- package/src/renderers/create-props-resolver.ts +17 -6
- package/src/transformers/types.ts +9 -7
- package/src/renderers/render-context.ts +0 -35
package/dist/index.d.mts
CHANGED
|
@@ -19,6 +19,8 @@ type DomRenderer = {
|
|
|
19
19
|
render: TwingEnvironment['render'];
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
type RenderContext<T = unknown> = Record<string, T>;
|
|
23
|
+
type NamespacedRenderContext<T = RenderContext> = Record<string, T | undefined>;
|
|
22
24
|
type LegacyWindow = Window & {
|
|
23
25
|
elementor: {
|
|
24
26
|
createBackboneElementsCollection: (children: unknown) => BackboneCollection<ElementModel>;
|
|
@@ -61,6 +63,7 @@ declare class ElementView {
|
|
|
61
63
|
children: {
|
|
62
64
|
length: number;
|
|
63
65
|
findByIndex: (index: number) => ElementView;
|
|
66
|
+
each: (callback: (view: ElementView) => void) => void;
|
|
64
67
|
};
|
|
65
68
|
constructor(...args: unknown[]);
|
|
66
69
|
onRender(...args: unknown[]): void;
|
|
@@ -87,11 +90,16 @@ declare class ElementView {
|
|
|
87
90
|
_isRendering: boolean;
|
|
88
91
|
resetChildViewContainer(): void;
|
|
89
92
|
isRendered: boolean;
|
|
93
|
+
_currentRenderPromise?: Promise<void>;
|
|
90
94
|
options?: {
|
|
91
95
|
model: BackboneModel<ElementModel>;
|
|
92
96
|
};
|
|
93
97
|
ui(): Record<string, unknown>;
|
|
94
98
|
events(): Record<string, unknown>;
|
|
99
|
+
_parent?: ElementView;
|
|
100
|
+
getRenderContext(): NamespacedRenderContext | undefined;
|
|
101
|
+
getResolverRenderContext(): RenderContext | undefined;
|
|
102
|
+
getNamespaceKey(): string;
|
|
95
103
|
}
|
|
96
104
|
type JQueryElement = {
|
|
97
105
|
find: (selector: string) => JQueryElement;
|
|
@@ -157,21 +165,12 @@ type ElementLegacyType = {
|
|
|
157
165
|
};
|
|
158
166
|
declare function registerElementType(type: string, elementTypeGenerator: ElementLegacyType[keyof ElementLegacyType]): void;
|
|
159
167
|
|
|
160
|
-
|
|
161
|
-
private key;
|
|
162
|
-
private context;
|
|
163
|
-
constructor(key: string, initialContext: TContext);
|
|
164
|
-
get(): TContext;
|
|
165
|
-
set(context: TContext): void;
|
|
166
|
-
update(updates: TContext): void;
|
|
167
|
-
delete(): void;
|
|
168
|
-
clear(): void;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
type UnbrandedTransformer<TValue> = (value: TValue, options: {
|
|
168
|
+
type TransformerOptions<TContext extends RenderContext = RenderContext> = {
|
|
172
169
|
key: string;
|
|
173
170
|
signal?: AbortSignal;
|
|
174
|
-
|
|
171
|
+
renderContext?: TContext;
|
|
172
|
+
};
|
|
173
|
+
type UnbrandedTransformer<TValue> = (value: TValue, options: TransformerOptions) => unknown;
|
|
175
174
|
type Transformer<TValue> = UnbrandedTransformer<TValue> & {
|
|
176
175
|
__transformer: true;
|
|
177
176
|
};
|
|
@@ -199,10 +198,11 @@ type ResolveArgs = {
|
|
|
199
198
|
props: Props;
|
|
200
199
|
schema?: PropsSchema;
|
|
201
200
|
signal?: AbortSignal;
|
|
201
|
+
renderContext?: RenderContext;
|
|
202
202
|
};
|
|
203
203
|
type ResolvedProps = Record<string, unknown>;
|
|
204
204
|
type PropsResolver = ReturnType<typeof createPropsResolver>;
|
|
205
|
-
declare function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }: CreatePropResolverArgs): ({ props, schema, signal }: ResolveArgs) => Promise<ResolvedProps>;
|
|
205
|
+
declare function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }: CreatePropResolverArgs): ({ props, schema, signal, renderContext }: ResolveArgs) => Promise<ResolvedProps>;
|
|
206
206
|
|
|
207
207
|
declare const settingsTransformersRegistry: {
|
|
208
208
|
register(type: _elementor_editor_props.PropTypeKey, transformer: AnyTransformer): /*elided*/ any;
|
|
@@ -264,4 +264,4 @@ declare const UnknownStyleStateError: {
|
|
|
264
264
|
isError(error: unknown): error is Error;
|
|
265
265
|
};
|
|
266
266
|
|
|
267
|
-
export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type BackboneModelConstructor, type CreateTemplatedElementTypeOptions, DOCUMENT_STRUCTURE_URI, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, RenderContext, type ReplacementSettings, STYLE_SCHEMA_URI, UnknownStyleStateError, UnknownStyleTypeError, WIDGET_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, isAtomicWidget, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
|
|
267
|
+
export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type BackboneModelConstructor, type CreateTemplatedElementTypeOptions, DOCUMENT_STRUCTURE_URI, type ElementModel, ElementType, ElementView, type LegacyWindow, type NamespacedRenderContext, type PropsResolver, type RenderContext, type ReplacementSettings, STYLE_SCHEMA_URI, type TransformerOptions, UnknownStyleStateError, UnknownStyleTypeError, WIDGET_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, isAtomicWidget, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ type DomRenderer = {
|
|
|
19
19
|
render: TwingEnvironment['render'];
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
type RenderContext<T = unknown> = Record<string, T>;
|
|
23
|
+
type NamespacedRenderContext<T = RenderContext> = Record<string, T | undefined>;
|
|
22
24
|
type LegacyWindow = Window & {
|
|
23
25
|
elementor: {
|
|
24
26
|
createBackboneElementsCollection: (children: unknown) => BackboneCollection<ElementModel>;
|
|
@@ -61,6 +63,7 @@ declare class ElementView {
|
|
|
61
63
|
children: {
|
|
62
64
|
length: number;
|
|
63
65
|
findByIndex: (index: number) => ElementView;
|
|
66
|
+
each: (callback: (view: ElementView) => void) => void;
|
|
64
67
|
};
|
|
65
68
|
constructor(...args: unknown[]);
|
|
66
69
|
onRender(...args: unknown[]): void;
|
|
@@ -87,11 +90,16 @@ declare class ElementView {
|
|
|
87
90
|
_isRendering: boolean;
|
|
88
91
|
resetChildViewContainer(): void;
|
|
89
92
|
isRendered: boolean;
|
|
93
|
+
_currentRenderPromise?: Promise<void>;
|
|
90
94
|
options?: {
|
|
91
95
|
model: BackboneModel<ElementModel>;
|
|
92
96
|
};
|
|
93
97
|
ui(): Record<string, unknown>;
|
|
94
98
|
events(): Record<string, unknown>;
|
|
99
|
+
_parent?: ElementView;
|
|
100
|
+
getRenderContext(): NamespacedRenderContext | undefined;
|
|
101
|
+
getResolverRenderContext(): RenderContext | undefined;
|
|
102
|
+
getNamespaceKey(): string;
|
|
95
103
|
}
|
|
96
104
|
type JQueryElement = {
|
|
97
105
|
find: (selector: string) => JQueryElement;
|
|
@@ -157,21 +165,12 @@ type ElementLegacyType = {
|
|
|
157
165
|
};
|
|
158
166
|
declare function registerElementType(type: string, elementTypeGenerator: ElementLegacyType[keyof ElementLegacyType]): void;
|
|
159
167
|
|
|
160
|
-
|
|
161
|
-
private key;
|
|
162
|
-
private context;
|
|
163
|
-
constructor(key: string, initialContext: TContext);
|
|
164
|
-
get(): TContext;
|
|
165
|
-
set(context: TContext): void;
|
|
166
|
-
update(updates: TContext): void;
|
|
167
|
-
delete(): void;
|
|
168
|
-
clear(): void;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
type UnbrandedTransformer<TValue> = (value: TValue, options: {
|
|
168
|
+
type TransformerOptions<TContext extends RenderContext = RenderContext> = {
|
|
172
169
|
key: string;
|
|
173
170
|
signal?: AbortSignal;
|
|
174
|
-
|
|
171
|
+
renderContext?: TContext;
|
|
172
|
+
};
|
|
173
|
+
type UnbrandedTransformer<TValue> = (value: TValue, options: TransformerOptions) => unknown;
|
|
175
174
|
type Transformer<TValue> = UnbrandedTransformer<TValue> & {
|
|
176
175
|
__transformer: true;
|
|
177
176
|
};
|
|
@@ -199,10 +198,11 @@ type ResolveArgs = {
|
|
|
199
198
|
props: Props;
|
|
200
199
|
schema?: PropsSchema;
|
|
201
200
|
signal?: AbortSignal;
|
|
201
|
+
renderContext?: RenderContext;
|
|
202
202
|
};
|
|
203
203
|
type ResolvedProps = Record<string, unknown>;
|
|
204
204
|
type PropsResolver = ReturnType<typeof createPropsResolver>;
|
|
205
|
-
declare function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }: CreatePropResolverArgs): ({ props, schema, signal }: ResolveArgs) => Promise<ResolvedProps>;
|
|
205
|
+
declare function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }: CreatePropResolverArgs): ({ props, schema, signal, renderContext }: ResolveArgs) => Promise<ResolvedProps>;
|
|
206
206
|
|
|
207
207
|
declare const settingsTransformersRegistry: {
|
|
208
208
|
register(type: _elementor_editor_props.PropTypeKey, transformer: AnyTransformer): /*elided*/ any;
|
|
@@ -264,4 +264,4 @@ declare const UnknownStyleStateError: {
|
|
|
264
264
|
isError(error: unknown): error is Error;
|
|
265
265
|
};
|
|
266
266
|
|
|
267
|
-
export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type BackboneModelConstructor, type CreateTemplatedElementTypeOptions, DOCUMENT_STRUCTURE_URI, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, RenderContext, type ReplacementSettings, STYLE_SCHEMA_URI, UnknownStyleStateError, UnknownStyleTypeError, WIDGET_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, isAtomicWidget, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
|
|
267
|
+
export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type BackboneModelConstructor, type CreateTemplatedElementTypeOptions, DOCUMENT_STRUCTURE_URI, type ElementModel, ElementType, ElementView, type LegacyWindow, type NamespacedRenderContext, type PropsResolver, type RenderContext, type ReplacementSettings, STYLE_SCHEMA_URI, type TransformerOptions, UnknownStyleStateError, UnknownStyleTypeError, WIDGET_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, isAtomicWidget, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,6 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
BREAKPOINTS_SCHEMA_URI: () => BREAKPOINTS_SCHEMA_URI,
|
|
34
34
|
DOCUMENT_STRUCTURE_URI: () => DOCUMENT_STRUCTURE_URI,
|
|
35
|
-
RenderContext: () => RenderContext,
|
|
36
35
|
STYLE_SCHEMA_URI: () => STYLE_SCHEMA_URI,
|
|
37
36
|
UnknownStyleStateError: () => UnknownStyleStateError,
|
|
38
37
|
UnknownStyleTypeError: () => UnknownStyleTypeError,
|
|
@@ -673,12 +672,12 @@ var getMultiPropsValue = (multiProps) => {
|
|
|
673
672
|
// src/renderers/create-props-resolver.ts
|
|
674
673
|
var TRANSFORM_DEPTH_LIMIT = 3;
|
|
675
674
|
function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
|
|
676
|
-
async function resolve({ props, schema: schema2, signal }) {
|
|
675
|
+
async function resolve({ props, schema: schema2, signal, renderContext }) {
|
|
677
676
|
schema2 = schema2 ?? initialSchema;
|
|
678
677
|
const promises = Promise.all(
|
|
679
678
|
Object.entries(schema2).map(async ([key, type]) => {
|
|
680
679
|
const value = props[key] ?? type.default;
|
|
681
|
-
const transformed = await transform({ value, key, type, signal });
|
|
680
|
+
const transformed = await transform({ value, key, type, signal, renderContext });
|
|
682
681
|
onPropResolve?.({ key, value: transformed });
|
|
683
682
|
if (isMultiProps(transformed)) {
|
|
684
683
|
return getMultiPropsValue(transformed);
|
|
@@ -688,7 +687,7 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
|
|
|
688
687
|
);
|
|
689
688
|
return Object.assign({}, ...(await promises).filter(Boolean));
|
|
690
689
|
}
|
|
691
|
-
async function transform({ value, key, type, signal, depth = 0 }) {
|
|
690
|
+
async function transform({ value, key, type, signal, depth = 0, renderContext }) {
|
|
692
691
|
if (value === null || value === void 0) {
|
|
693
692
|
return null;
|
|
694
693
|
}
|
|
@@ -721,13 +720,21 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
|
|
|
721
720
|
resolvedValue = await resolve({
|
|
722
721
|
props: resolvedValue,
|
|
723
722
|
schema: transformablePropType.shape,
|
|
724
|
-
signal
|
|
723
|
+
signal,
|
|
724
|
+
renderContext
|
|
725
725
|
});
|
|
726
726
|
}
|
|
727
727
|
if (transformablePropType.kind === "array") {
|
|
728
728
|
resolvedValue = await Promise.all(
|
|
729
729
|
resolvedValue.map(
|
|
730
|
-
(item) => transform({
|
|
730
|
+
(item) => transform({
|
|
731
|
+
value: item,
|
|
732
|
+
key,
|
|
733
|
+
type: transformablePropType.item_prop_type,
|
|
734
|
+
depth,
|
|
735
|
+
signal,
|
|
736
|
+
renderContext
|
|
737
|
+
})
|
|
731
738
|
)
|
|
732
739
|
);
|
|
733
740
|
}
|
|
@@ -736,8 +743,8 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
|
|
|
736
743
|
return null;
|
|
737
744
|
}
|
|
738
745
|
try {
|
|
739
|
-
const transformed = await transformer(resolvedValue, { key, signal });
|
|
740
|
-
return transform({ value: transformed, key, type, signal, depth: depth + 1 });
|
|
746
|
+
const transformed = await transformer(resolvedValue, { key, signal, renderContext });
|
|
747
|
+
return transform({ value: transformed, key, type, signal, depth: depth + 1, renderContext });
|
|
741
748
|
} catch {
|
|
742
749
|
return null;
|
|
743
750
|
}
|
|
@@ -1581,22 +1588,45 @@ function createTemplatedElementView({
|
|
|
1581
1588
|
});
|
|
1582
1589
|
return class extends BaseView {
|
|
1583
1590
|
#abortController = null;
|
|
1591
|
+
#childrenRenderPromises = [];
|
|
1584
1592
|
getTemplateType() {
|
|
1585
1593
|
return "twig";
|
|
1586
1594
|
}
|
|
1595
|
+
getNamespaceKey() {
|
|
1596
|
+
return type;
|
|
1597
|
+
}
|
|
1587
1598
|
renderOnChange() {
|
|
1588
1599
|
this.render();
|
|
1589
1600
|
}
|
|
1601
|
+
getRenderContext() {
|
|
1602
|
+
return this._parent?.getRenderContext?.();
|
|
1603
|
+
}
|
|
1604
|
+
getResolverRenderContext() {
|
|
1605
|
+
return this._parent?.getResolverRenderContext?.();
|
|
1606
|
+
}
|
|
1590
1607
|
// Override `render` function to support async `_renderTemplate`
|
|
1591
1608
|
// Note that `_renderChildren` asynchronity is still NOT supported, so only the parent element rendering can be async
|
|
1592
1609
|
render() {
|
|
1593
1610
|
this.#abortController?.abort();
|
|
1594
1611
|
this.#abortController = new AbortController();
|
|
1595
|
-
const process = signalizedProcess(this.#abortController.signal).then(() => this._beforeRender()).then(() => this._renderTemplate()).then(() =>
|
|
1596
|
-
|
|
1597
|
-
|
|
1612
|
+
const process = signalizedProcess(this.#abortController.signal).then(() => this._beforeRender()).then(() => this._renderTemplate()).then(() => this._renderChildren()).then(() => this._afterRender());
|
|
1613
|
+
this._currentRenderPromise = process.execute();
|
|
1614
|
+
return this._currentRenderPromise;
|
|
1615
|
+
}
|
|
1616
|
+
async _renderChildren() {
|
|
1617
|
+
super._renderChildren();
|
|
1618
|
+
this.#childrenRenderPromises = [];
|
|
1619
|
+
this.children?.each((childView) => {
|
|
1620
|
+
if (childView._currentRenderPromise) {
|
|
1621
|
+
this.#childrenRenderPromises.push(childView._currentRenderPromise);
|
|
1622
|
+
}
|
|
1598
1623
|
});
|
|
1599
|
-
|
|
1624
|
+
await this._waitForChildrenToComplete();
|
|
1625
|
+
}
|
|
1626
|
+
async _waitForChildrenToComplete() {
|
|
1627
|
+
if (this.#childrenRenderPromises.length > 0) {
|
|
1628
|
+
await Promise.all(this.#childrenRenderPromises);
|
|
1629
|
+
}
|
|
1600
1630
|
}
|
|
1601
1631
|
// Overriding Marionette original `_renderTemplate` method to inject our renderer.
|
|
1602
1632
|
async _renderTemplate() {
|
|
@@ -1605,7 +1635,8 @@ function createTemplatedElementView({
|
|
|
1605
1635
|
const settings = this.model.get("settings").toJSON();
|
|
1606
1636
|
return resolveProps({
|
|
1607
1637
|
props: settings,
|
|
1608
|
-
signal
|
|
1638
|
+
signal,
|
|
1639
|
+
renderContext: this.getResolverRenderContext()
|
|
1609
1640
|
});
|
|
1610
1641
|
}).then((settings) => {
|
|
1611
1642
|
return this.afterSettingsResolve(settings);
|
|
@@ -3617,35 +3648,6 @@ function init() {
|
|
|
3617
3648
|
);
|
|
3618
3649
|
}
|
|
3619
3650
|
|
|
3620
|
-
// src/renderers/render-context.ts
|
|
3621
|
-
var RenderContext = class {
|
|
3622
|
-
key;
|
|
3623
|
-
context = /* @__PURE__ */ new Map();
|
|
3624
|
-
constructor(key, initialContext) {
|
|
3625
|
-
this.key = key;
|
|
3626
|
-
this.context.set(this.key, initialContext);
|
|
3627
|
-
}
|
|
3628
|
-
get() {
|
|
3629
|
-
return this.context.get(this.key);
|
|
3630
|
-
}
|
|
3631
|
-
set(context) {
|
|
3632
|
-
this.context.set(this.key, context);
|
|
3633
|
-
}
|
|
3634
|
-
update(updates) {
|
|
3635
|
-
const currentContext = this.context.get(this.key);
|
|
3636
|
-
if (!currentContext) {
|
|
3637
|
-
return this.set(updates);
|
|
3638
|
-
}
|
|
3639
|
-
this.context.set(this.key, { ...currentContext, ...updates });
|
|
3640
|
-
}
|
|
3641
|
-
delete() {
|
|
3642
|
-
this.context.delete(this.key);
|
|
3643
|
-
}
|
|
3644
|
-
clear() {
|
|
3645
|
-
this.context.clear();
|
|
3646
|
-
}
|
|
3647
|
-
};
|
|
3648
|
-
|
|
3649
3651
|
// src/sync/drag-element-from-panel.ts
|
|
3650
3652
|
var DRAG_GROUPS = ["elementor-element"];
|
|
3651
3653
|
var endDragElementFromPanel = () => {
|
|
@@ -3694,7 +3696,6 @@ var getLegacyPanelElementView = ({ settings, ...rest }) => {
|
|
|
3694
3696
|
0 && (module.exports = {
|
|
3695
3697
|
BREAKPOINTS_SCHEMA_URI,
|
|
3696
3698
|
DOCUMENT_STRUCTURE_URI,
|
|
3697
|
-
RenderContext,
|
|
3698
3699
|
STYLE_SCHEMA_URI,
|
|
3699
3700
|
UnknownStyleStateError,
|
|
3700
3701
|
UnknownStyleTypeError,
|
package/dist/index.mjs
CHANGED
|
@@ -629,12 +629,12 @@ var getMultiPropsValue = (multiProps) => {
|
|
|
629
629
|
// src/renderers/create-props-resolver.ts
|
|
630
630
|
var TRANSFORM_DEPTH_LIMIT = 3;
|
|
631
631
|
function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
|
|
632
|
-
async function resolve({ props, schema: schema2, signal }) {
|
|
632
|
+
async function resolve({ props, schema: schema2, signal, renderContext }) {
|
|
633
633
|
schema2 = schema2 ?? initialSchema;
|
|
634
634
|
const promises = Promise.all(
|
|
635
635
|
Object.entries(schema2).map(async ([key, type]) => {
|
|
636
636
|
const value = props[key] ?? type.default;
|
|
637
|
-
const transformed = await transform({ value, key, type, signal });
|
|
637
|
+
const transformed = await transform({ value, key, type, signal, renderContext });
|
|
638
638
|
onPropResolve?.({ key, value: transformed });
|
|
639
639
|
if (isMultiProps(transformed)) {
|
|
640
640
|
return getMultiPropsValue(transformed);
|
|
@@ -644,7 +644,7 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
|
|
|
644
644
|
);
|
|
645
645
|
return Object.assign({}, ...(await promises).filter(Boolean));
|
|
646
646
|
}
|
|
647
|
-
async function transform({ value, key, type, signal, depth = 0 }) {
|
|
647
|
+
async function transform({ value, key, type, signal, depth = 0, renderContext }) {
|
|
648
648
|
if (value === null || value === void 0) {
|
|
649
649
|
return null;
|
|
650
650
|
}
|
|
@@ -677,13 +677,21 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
|
|
|
677
677
|
resolvedValue = await resolve({
|
|
678
678
|
props: resolvedValue,
|
|
679
679
|
schema: transformablePropType.shape,
|
|
680
|
-
signal
|
|
680
|
+
signal,
|
|
681
|
+
renderContext
|
|
681
682
|
});
|
|
682
683
|
}
|
|
683
684
|
if (transformablePropType.kind === "array") {
|
|
684
685
|
resolvedValue = await Promise.all(
|
|
685
686
|
resolvedValue.map(
|
|
686
|
-
(item) => transform({
|
|
687
|
+
(item) => transform({
|
|
688
|
+
value: item,
|
|
689
|
+
key,
|
|
690
|
+
type: transformablePropType.item_prop_type,
|
|
691
|
+
depth,
|
|
692
|
+
signal,
|
|
693
|
+
renderContext
|
|
694
|
+
})
|
|
687
695
|
)
|
|
688
696
|
);
|
|
689
697
|
}
|
|
@@ -692,8 +700,8 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
|
|
|
692
700
|
return null;
|
|
693
701
|
}
|
|
694
702
|
try {
|
|
695
|
-
const transformed = await transformer(resolvedValue, { key, signal });
|
|
696
|
-
return transform({ value: transformed, key, type, signal, depth: depth + 1 });
|
|
703
|
+
const transformed = await transformer(resolvedValue, { key, signal, renderContext });
|
|
704
|
+
return transform({ value: transformed, key, type, signal, depth: depth + 1, renderContext });
|
|
697
705
|
} catch {
|
|
698
706
|
return null;
|
|
699
707
|
}
|
|
@@ -1539,22 +1547,45 @@ function createTemplatedElementView({
|
|
|
1539
1547
|
});
|
|
1540
1548
|
return class extends BaseView {
|
|
1541
1549
|
#abortController = null;
|
|
1550
|
+
#childrenRenderPromises = [];
|
|
1542
1551
|
getTemplateType() {
|
|
1543
1552
|
return "twig";
|
|
1544
1553
|
}
|
|
1554
|
+
getNamespaceKey() {
|
|
1555
|
+
return type;
|
|
1556
|
+
}
|
|
1545
1557
|
renderOnChange() {
|
|
1546
1558
|
this.render();
|
|
1547
1559
|
}
|
|
1560
|
+
getRenderContext() {
|
|
1561
|
+
return this._parent?.getRenderContext?.();
|
|
1562
|
+
}
|
|
1563
|
+
getResolverRenderContext() {
|
|
1564
|
+
return this._parent?.getResolverRenderContext?.();
|
|
1565
|
+
}
|
|
1548
1566
|
// Override `render` function to support async `_renderTemplate`
|
|
1549
1567
|
// Note that `_renderChildren` asynchronity is still NOT supported, so only the parent element rendering can be async
|
|
1550
1568
|
render() {
|
|
1551
1569
|
this.#abortController?.abort();
|
|
1552
1570
|
this.#abortController = new AbortController();
|
|
1553
|
-
const process = signalizedProcess(this.#abortController.signal).then(() => this._beforeRender()).then(() => this._renderTemplate()).then(() =>
|
|
1554
|
-
|
|
1555
|
-
|
|
1571
|
+
const process = signalizedProcess(this.#abortController.signal).then(() => this._beforeRender()).then(() => this._renderTemplate()).then(() => this._renderChildren()).then(() => this._afterRender());
|
|
1572
|
+
this._currentRenderPromise = process.execute();
|
|
1573
|
+
return this._currentRenderPromise;
|
|
1574
|
+
}
|
|
1575
|
+
async _renderChildren() {
|
|
1576
|
+
super._renderChildren();
|
|
1577
|
+
this.#childrenRenderPromises = [];
|
|
1578
|
+
this.children?.each((childView) => {
|
|
1579
|
+
if (childView._currentRenderPromise) {
|
|
1580
|
+
this.#childrenRenderPromises.push(childView._currentRenderPromise);
|
|
1581
|
+
}
|
|
1556
1582
|
});
|
|
1557
|
-
|
|
1583
|
+
await this._waitForChildrenToComplete();
|
|
1584
|
+
}
|
|
1585
|
+
async _waitForChildrenToComplete() {
|
|
1586
|
+
if (this.#childrenRenderPromises.length > 0) {
|
|
1587
|
+
await Promise.all(this.#childrenRenderPromises);
|
|
1588
|
+
}
|
|
1558
1589
|
}
|
|
1559
1590
|
// Overriding Marionette original `_renderTemplate` method to inject our renderer.
|
|
1560
1591
|
async _renderTemplate() {
|
|
@@ -1563,7 +1594,8 @@ function createTemplatedElementView({
|
|
|
1563
1594
|
const settings = this.model.get("settings").toJSON();
|
|
1564
1595
|
return resolveProps({
|
|
1565
1596
|
props: settings,
|
|
1566
|
-
signal
|
|
1597
|
+
signal,
|
|
1598
|
+
renderContext: this.getResolverRenderContext()
|
|
1567
1599
|
});
|
|
1568
1600
|
}).then((settings) => {
|
|
1569
1601
|
return this.afterSettingsResolve(settings);
|
|
@@ -3607,35 +3639,6 @@ function init() {
|
|
|
3607
3639
|
);
|
|
3608
3640
|
}
|
|
3609
3641
|
|
|
3610
|
-
// src/renderers/render-context.ts
|
|
3611
|
-
var RenderContext = class {
|
|
3612
|
-
key;
|
|
3613
|
-
context = /* @__PURE__ */ new Map();
|
|
3614
|
-
constructor(key, initialContext) {
|
|
3615
|
-
this.key = key;
|
|
3616
|
-
this.context.set(this.key, initialContext);
|
|
3617
|
-
}
|
|
3618
|
-
get() {
|
|
3619
|
-
return this.context.get(this.key);
|
|
3620
|
-
}
|
|
3621
|
-
set(context) {
|
|
3622
|
-
this.context.set(this.key, context);
|
|
3623
|
-
}
|
|
3624
|
-
update(updates) {
|
|
3625
|
-
const currentContext = this.context.get(this.key);
|
|
3626
|
-
if (!currentContext) {
|
|
3627
|
-
return this.set(updates);
|
|
3628
|
-
}
|
|
3629
|
-
this.context.set(this.key, { ...currentContext, ...updates });
|
|
3630
|
-
}
|
|
3631
|
-
delete() {
|
|
3632
|
-
this.context.delete(this.key);
|
|
3633
|
-
}
|
|
3634
|
-
clear() {
|
|
3635
|
-
this.context.clear();
|
|
3636
|
-
}
|
|
3637
|
-
};
|
|
3638
|
-
|
|
3639
3642
|
// src/sync/drag-element-from-panel.ts
|
|
3640
3643
|
var DRAG_GROUPS = ["elementor-element"];
|
|
3641
3644
|
var endDragElementFromPanel = () => {
|
|
@@ -3683,7 +3686,6 @@ var getLegacyPanelElementView = ({ settings, ...rest }) => {
|
|
|
3683
3686
|
export {
|
|
3684
3687
|
BREAKPOINTS_SCHEMA_URI,
|
|
3685
3688
|
DOCUMENT_STRUCTURE_URI,
|
|
3686
|
-
RenderContext,
|
|
3687
3689
|
STYLE_SCHEMA_URI,
|
|
3688
3690
|
UnknownStyleStateError,
|
|
3689
3691
|
UnknownStyleTypeError,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "3.35.0-
|
|
4
|
+
"version": "3.35.0-420",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,24 +37,24 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "3.35.0-
|
|
41
|
-
"@elementor/editor-controls": "3.35.0-
|
|
42
|
-
"@elementor/editor-documents": "3.35.0-
|
|
43
|
-
"@elementor/editor-elements": "3.35.0-
|
|
44
|
-
"@elementor/editor-interactions": "3.35.0-
|
|
45
|
-
"@elementor/editor-mcp": "3.35.0-
|
|
46
|
-
"@elementor/editor-notifications": "3.35.0-
|
|
47
|
-
"@elementor/editor-props": "3.35.0-
|
|
48
|
-
"@elementor/editor-responsive": "3.35.0-
|
|
49
|
-
"@elementor/editor-styles": "3.35.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "3.35.0-
|
|
51
|
-
"@elementor/editor-ui": "3.35.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "3.35.0-
|
|
53
|
-
"@elementor/schema": "3.35.0-
|
|
54
|
-
"@elementor/twing": "3.35.0-
|
|
40
|
+
"@elementor/editor": "3.35.0-420",
|
|
41
|
+
"@elementor/editor-controls": "3.35.0-420",
|
|
42
|
+
"@elementor/editor-documents": "3.35.0-420",
|
|
43
|
+
"@elementor/editor-elements": "3.35.0-420",
|
|
44
|
+
"@elementor/editor-interactions": "3.35.0-420",
|
|
45
|
+
"@elementor/editor-mcp": "3.35.0-420",
|
|
46
|
+
"@elementor/editor-notifications": "3.35.0-420",
|
|
47
|
+
"@elementor/editor-props": "3.35.0-420",
|
|
48
|
+
"@elementor/editor-responsive": "3.35.0-420",
|
|
49
|
+
"@elementor/editor-styles": "3.35.0-420",
|
|
50
|
+
"@elementor/editor-styles-repository": "3.35.0-420",
|
|
51
|
+
"@elementor/editor-ui": "3.35.0-420",
|
|
52
|
+
"@elementor/editor-v1-adapters": "3.35.0-420",
|
|
53
|
+
"@elementor/schema": "3.35.0-420",
|
|
54
|
+
"@elementor/twing": "3.35.0-420",
|
|
55
55
|
"@elementor/ui": "1.36.17",
|
|
56
|
-
"@elementor/utils": "3.35.0-
|
|
57
|
-
"@elementor/wp-media": "3.35.0-
|
|
56
|
+
"@elementor/utils": "3.35.0-420",
|
|
57
|
+
"@elementor/wp-media": "3.35.0-420",
|
|
58
58
|
"@floating-ui/react": "^0.27.5",
|
|
59
59
|
"@wordpress/i18n": "^5.13.0"
|
|
60
60
|
},
|
package/src/index.ts
CHANGED
|
@@ -10,7 +10,6 @@ export {
|
|
|
10
10
|
} from './legacy/create-templated-element-type';
|
|
11
11
|
export { registerElementType } from './legacy/init-legacy-views';
|
|
12
12
|
export * from './legacy/types';
|
|
13
|
-
export { RenderContext } from './renderers/render-context';
|
|
14
13
|
export { createPropsResolver, type PropsResolver } from './renderers/create-props-resolver';
|
|
15
14
|
export { settingsTransformersRegistry } from './settings-transformers-registry';
|
|
16
15
|
export { styleTransformersRegistry } from './style-transformers-registry';
|
|
@@ -21,5 +20,5 @@ export { WIDGET_SCHEMA_URI } from './mcp/resources/widgets-schema-resource';
|
|
|
21
20
|
export * from './legacy/types';
|
|
22
21
|
export { createTransformer } from './transformers/create-transformer';
|
|
23
22
|
export { createTransformersRegistry } from './transformers/create-transformers-registry';
|
|
24
|
-
export { type AnyTransformer } from './transformers/types';
|
|
23
|
+
export { type AnyTransformer, type TransformerOptions } from './transformers/types';
|
|
25
24
|
export { UnknownStyleTypeError, UnknownStyleStateError } from './renderers/errors';
|
|
@@ -5,7 +5,13 @@ import { createPropsResolver } from '../renderers/create-props-resolver';
|
|
|
5
5
|
import { settingsTransformersRegistry } from '../settings-transformers-registry';
|
|
6
6
|
import { signalizedProcess } from '../utils/signalized-process';
|
|
7
7
|
import { createElementViewClassDeclaration } from './create-element-type';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
type ElementType,
|
|
10
|
+
type ElementView,
|
|
11
|
+
type LegacyWindow,
|
|
12
|
+
type NamespacedRenderContext,
|
|
13
|
+
type RenderContext,
|
|
14
|
+
} from './types';
|
|
9
15
|
|
|
10
16
|
export type CreateTemplatedElementTypeOptions = {
|
|
11
17
|
type: string;
|
|
@@ -70,15 +76,28 @@ export function createTemplatedElementView( {
|
|
|
70
76
|
|
|
71
77
|
return class extends BaseView {
|
|
72
78
|
#abortController: AbortController | null = null;
|
|
79
|
+
#childrenRenderPromises: Promise< void >[] = [];
|
|
73
80
|
|
|
74
81
|
getTemplateType() {
|
|
75
82
|
return 'twig';
|
|
76
83
|
}
|
|
77
84
|
|
|
85
|
+
getNamespaceKey() {
|
|
86
|
+
return type;
|
|
87
|
+
}
|
|
88
|
+
|
|
78
89
|
renderOnChange() {
|
|
79
90
|
this.render();
|
|
80
91
|
}
|
|
81
92
|
|
|
93
|
+
getRenderContext(): NamespacedRenderContext | undefined {
|
|
94
|
+
return this._parent?.getRenderContext?.();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
getResolverRenderContext(): RenderContext | undefined {
|
|
98
|
+
return this._parent?.getResolverRenderContext?.();
|
|
99
|
+
}
|
|
100
|
+
|
|
82
101
|
// Override `render` function to support async `_renderTemplate`
|
|
83
102
|
// Note that `_renderChildren` asynchronity is still NOT supported, so only the parent element rendering can be async
|
|
84
103
|
render() {
|
|
@@ -88,12 +107,32 @@ export function createTemplatedElementView( {
|
|
|
88
107
|
const process = signalizedProcess( this.#abortController.signal )
|
|
89
108
|
.then( () => this._beforeRender() )
|
|
90
109
|
.then( () => this._renderTemplate() )
|
|
91
|
-
.then( () =>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
110
|
+
.then( () => this._renderChildren() )
|
|
111
|
+
.then( () => this._afterRender() );
|
|
112
|
+
|
|
113
|
+
this._currentRenderPromise = process.execute();
|
|
114
|
+
|
|
115
|
+
return this._currentRenderPromise;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async _renderChildren() {
|
|
119
|
+
super._renderChildren();
|
|
120
|
+
|
|
121
|
+
this.#childrenRenderPromises = [];
|
|
122
|
+
|
|
123
|
+
this.children?.each( ( childView: ElementView ) => {
|
|
124
|
+
if ( childView._currentRenderPromise ) {
|
|
125
|
+
this.#childrenRenderPromises.push( childView._currentRenderPromise );
|
|
126
|
+
}
|
|
127
|
+
} );
|
|
128
|
+
|
|
129
|
+
await this._waitForChildrenToComplete();
|
|
130
|
+
}
|
|
95
131
|
|
|
96
|
-
|
|
132
|
+
async _waitForChildrenToComplete() {
|
|
133
|
+
if ( this.#childrenRenderPromises.length > 0 ) {
|
|
134
|
+
await Promise.all( this.#childrenRenderPromises );
|
|
135
|
+
}
|
|
97
136
|
}
|
|
98
137
|
|
|
99
138
|
// Overriding Marionette original `_renderTemplate` method to inject our renderer.
|
|
@@ -107,6 +146,7 @@ export function createTemplatedElementView( {
|
|
|
107
146
|
return resolveProps( {
|
|
108
147
|
props: settings,
|
|
109
148
|
signal,
|
|
149
|
+
renderContext: this.getResolverRenderContext(),
|
|
110
150
|
} );
|
|
111
151
|
} )
|
|
112
152
|
.then( ( settings ) => {
|
package/src/legacy/types.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { type V1Element } from '@elementor/editor-elements';
|
|
2
2
|
import { type Props, type PropValue } from '@elementor/editor-props';
|
|
3
3
|
|
|
4
|
+
export type RenderContext< T = unknown > = Record< string, T >;
|
|
5
|
+
|
|
6
|
+
export type NamespacedRenderContext< T = RenderContext > = Record< string, T | undefined >;
|
|
7
|
+
|
|
4
8
|
export type LegacyWindow = Window & {
|
|
5
9
|
elementor: {
|
|
6
10
|
createBackboneElementsCollection: ( children: unknown ) => BackboneCollection< ElementModel >;
|
|
@@ -50,6 +54,7 @@ export declare class ElementView {
|
|
|
50
54
|
children: {
|
|
51
55
|
length: number;
|
|
52
56
|
findByIndex: ( index: number ) => ElementView;
|
|
57
|
+
each: ( callback: ( view: ElementView ) => void ) => void;
|
|
53
58
|
};
|
|
54
59
|
|
|
55
60
|
constructor( ...args: unknown[] );
|
|
@@ -99,6 +104,8 @@ export declare class ElementView {
|
|
|
99
104
|
|
|
100
105
|
isRendered: boolean;
|
|
101
106
|
|
|
107
|
+
_currentRenderPromise?: Promise< void >;
|
|
108
|
+
|
|
102
109
|
options?: {
|
|
103
110
|
model: BackboneModel< ElementModel >;
|
|
104
111
|
};
|
|
@@ -106,6 +113,14 @@ export declare class ElementView {
|
|
|
106
113
|
ui(): Record< string, unknown >;
|
|
107
114
|
|
|
108
115
|
events(): Record< string, unknown >;
|
|
116
|
+
|
|
117
|
+
_parent?: ElementView;
|
|
118
|
+
|
|
119
|
+
getRenderContext(): NamespacedRenderContext | undefined;
|
|
120
|
+
|
|
121
|
+
getResolverRenderContext(): RenderContext | undefined;
|
|
122
|
+
|
|
123
|
+
getNamespaceKey(): string;
|
|
109
124
|
}
|
|
110
125
|
|
|
111
126
|
type JQueryElement = {
|
|
@@ -290,4 +290,153 @@ describe( 'createPropsResolver', () => {
|
|
|
290
290
|
expect( onResolve ).toHaveBeenNthCalledWith( 1, { key: 'int', value: 2 } );
|
|
291
291
|
expect( onResolve ).toHaveBeenNthCalledWith( 2, { key: 'int2', value: 4 } );
|
|
292
292
|
} );
|
|
293
|
+
|
|
294
|
+
it( 'should pass renderContext to transformers', async () => {
|
|
295
|
+
// Arrange.
|
|
296
|
+
const CONTEXT_KEY = 'test-key';
|
|
297
|
+
const CONTEXT_VALUE = 'from-context';
|
|
298
|
+
|
|
299
|
+
const transformers = createTransformersRegistry().register(
|
|
300
|
+
'context-aware',
|
|
301
|
+
createTransformer< { key: string } >( ( value, options ) => {
|
|
302
|
+
return options.renderContext?.[ value.key ] ?? 'fallback';
|
|
303
|
+
} )
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
const resolve = createPropsResolver( {
|
|
307
|
+
transformers,
|
|
308
|
+
schema: {
|
|
309
|
+
text: createMockPropType( { kind: 'plain', key: 'context-aware' } ),
|
|
310
|
+
},
|
|
311
|
+
} );
|
|
312
|
+
|
|
313
|
+
// Act.
|
|
314
|
+
const result = await resolve( {
|
|
315
|
+
props: {
|
|
316
|
+
text: { $$type: 'context-aware', value: { key: CONTEXT_KEY } },
|
|
317
|
+
},
|
|
318
|
+
renderContext: { [ CONTEXT_KEY ]: CONTEXT_VALUE },
|
|
319
|
+
} );
|
|
320
|
+
|
|
321
|
+
// Assert.
|
|
322
|
+
expect( result ).toEqual( { text: CONTEXT_VALUE } );
|
|
323
|
+
} );
|
|
324
|
+
|
|
325
|
+
it( 'should use fallback when renderContext is not provided', async () => {
|
|
326
|
+
// Arrange.
|
|
327
|
+
const transformers = createTransformersRegistry().register(
|
|
328
|
+
'context-aware',
|
|
329
|
+
createTransformer< { key: string } >( ( value, options ) => {
|
|
330
|
+
return options.renderContext?.[ value.key ] ?? 'fallback';
|
|
331
|
+
} )
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
const resolve = createPropsResolver( {
|
|
335
|
+
transformers,
|
|
336
|
+
schema: {
|
|
337
|
+
text: createMockPropType( { kind: 'plain', key: 'context-aware' } ),
|
|
338
|
+
},
|
|
339
|
+
} );
|
|
340
|
+
|
|
341
|
+
// Act.
|
|
342
|
+
const result = await resolve( {
|
|
343
|
+
props: {
|
|
344
|
+
text: { $$type: 'context-aware', value: { key: 'any-key' } },
|
|
345
|
+
},
|
|
346
|
+
} );
|
|
347
|
+
|
|
348
|
+
// Assert.
|
|
349
|
+
expect( result ).toEqual( { text: 'fallback' } );
|
|
350
|
+
} );
|
|
351
|
+
|
|
352
|
+
it( 'should propagate renderContext through nested object props', async () => {
|
|
353
|
+
// Arrange.
|
|
354
|
+
const CONTEXT_KEY = 'nested-key';
|
|
355
|
+
const CONTEXT_VALUE = 'nested-context';
|
|
356
|
+
|
|
357
|
+
const transformers = createTransformersRegistry()
|
|
358
|
+
.register(
|
|
359
|
+
'object',
|
|
360
|
+
createTransformer< unknown >( ( value ) => value )
|
|
361
|
+
)
|
|
362
|
+
.register(
|
|
363
|
+
'context-aware',
|
|
364
|
+
createTransformer< { key: string } >( ( value, options ) => {
|
|
365
|
+
return options.renderContext?.[ value.key ] ?? 'fallback';
|
|
366
|
+
} )
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
const nestedSchema = {
|
|
370
|
+
inner: createMockPropType( { kind: 'plain', key: 'context-aware' } ),
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const resolve = createPropsResolver( {
|
|
374
|
+
transformers,
|
|
375
|
+
schema: {
|
|
376
|
+
outer: createMockPropType( { kind: 'object', key: 'object', shape: nestedSchema } ),
|
|
377
|
+
},
|
|
378
|
+
} );
|
|
379
|
+
|
|
380
|
+
// Act.
|
|
381
|
+
const result = await resolve( {
|
|
382
|
+
props: {
|
|
383
|
+
outer: {
|
|
384
|
+
$$type: 'object',
|
|
385
|
+
value: {
|
|
386
|
+
inner: { $$type: 'context-aware', value: { key: CONTEXT_KEY } },
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
renderContext: { [ CONTEXT_KEY ]: CONTEXT_VALUE },
|
|
391
|
+
} );
|
|
392
|
+
|
|
393
|
+
// Assert.
|
|
394
|
+
expect( result ).toEqual( { outer: { inner: CONTEXT_VALUE } } );
|
|
395
|
+
} );
|
|
396
|
+
|
|
397
|
+
it( 'should propagate renderContext through array props', async () => {
|
|
398
|
+
// Arrange.
|
|
399
|
+
const CONTEXT_KEY = 'array-key';
|
|
400
|
+
const CONTEXT_VALUE = 'array-context';
|
|
401
|
+
|
|
402
|
+
const transformers = createTransformersRegistry()
|
|
403
|
+
.register(
|
|
404
|
+
'array',
|
|
405
|
+
createTransformer< unknown >( ( value ) => value )
|
|
406
|
+
)
|
|
407
|
+
.register(
|
|
408
|
+
'context-aware',
|
|
409
|
+
createTransformer< { key: string } >( ( value, options ) => {
|
|
410
|
+
return options.renderContext?.[ value.key ] ?? 'fallback';
|
|
411
|
+
} )
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
const resolve = createPropsResolver( {
|
|
415
|
+
transformers,
|
|
416
|
+
schema: {
|
|
417
|
+
items: createMockPropType( {
|
|
418
|
+
kind: 'array',
|
|
419
|
+
key: 'array',
|
|
420
|
+
item_prop_type: createMockPropType( { kind: 'plain', key: 'context-aware' } ),
|
|
421
|
+
} ),
|
|
422
|
+
},
|
|
423
|
+
} );
|
|
424
|
+
|
|
425
|
+
// Act.
|
|
426
|
+
const result = await resolve( {
|
|
427
|
+
props: {
|
|
428
|
+
items: {
|
|
429
|
+
$$type: 'array',
|
|
430
|
+
value: [
|
|
431
|
+
{ $$type: 'context-aware', value: { key: CONTEXT_KEY } },
|
|
432
|
+
{ $$type: 'context-aware', value: { key: CONTEXT_KEY } },
|
|
433
|
+
],
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
renderContext: { [ CONTEXT_KEY ]: CONTEXT_VALUE },
|
|
437
|
+
} );
|
|
438
|
+
|
|
439
|
+
// Assert.
|
|
440
|
+
expect( result ).toEqual( { items: [ CONTEXT_VALUE, CONTEXT_VALUE ] } );
|
|
441
|
+
} );
|
|
293
442
|
} );
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type TransformablePropType,
|
|
10
10
|
} from '@elementor/editor-props';
|
|
11
11
|
|
|
12
|
+
import { type RenderContext } from '../legacy/types';
|
|
12
13
|
import { type TransformersRegistry } from '../transformers/create-transformers-registry';
|
|
13
14
|
import { getMultiPropsValue, isMultiProps } from './multi-props';
|
|
14
15
|
|
|
@@ -22,6 +23,7 @@ type ResolveArgs = {
|
|
|
22
23
|
props: Props;
|
|
23
24
|
schema?: PropsSchema;
|
|
24
25
|
signal?: AbortSignal;
|
|
26
|
+
renderContext?: RenderContext;
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
type TransformArgs = {
|
|
@@ -30,6 +32,7 @@ type TransformArgs = {
|
|
|
30
32
|
type: PropType;
|
|
31
33
|
signal?: AbortSignal;
|
|
32
34
|
depth?: number;
|
|
35
|
+
renderContext?: RenderContext;
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
type ResolvedProps = Record< string, unknown >;
|
|
@@ -39,14 +42,14 @@ export type PropsResolver = ReturnType< typeof createPropsResolver >;
|
|
|
39
42
|
const TRANSFORM_DEPTH_LIMIT = 3;
|
|
40
43
|
|
|
41
44
|
export function createPropsResolver( { transformers, schema: initialSchema, onPropResolve }: CreatePropResolverArgs ) {
|
|
42
|
-
async function resolve( { props, schema, signal }: ResolveArgs ): Promise< ResolvedProps > {
|
|
45
|
+
async function resolve( { props, schema, signal, renderContext }: ResolveArgs ): Promise< ResolvedProps > {
|
|
43
46
|
schema = schema ?? initialSchema;
|
|
44
47
|
|
|
45
48
|
const promises = Promise.all(
|
|
46
49
|
Object.entries( schema ).map( async ( [ key, type ] ) => {
|
|
47
50
|
const value = props[ key ] ?? type.default;
|
|
48
51
|
|
|
49
|
-
const transformed = ( await transform( { value, key, type, signal } ) ) as PropValue;
|
|
52
|
+
const transformed = ( await transform( { value, key, type, signal, renderContext } ) ) as PropValue;
|
|
50
53
|
|
|
51
54
|
onPropResolve?.( { key, value: transformed } );
|
|
52
55
|
|
|
@@ -61,7 +64,7 @@ export function createPropsResolver( { transformers, schema: initialSchema, onPr
|
|
|
61
64
|
return Object.assign( {}, ...( await promises ).filter( Boolean ) );
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
async function transform( { value, key, type, signal, depth = 0 }: TransformArgs ) {
|
|
67
|
+
async function transform( { value, key, type, signal, depth = 0, renderContext }: TransformArgs ) {
|
|
65
68
|
if ( value === null || value === undefined ) {
|
|
66
69
|
return null;
|
|
67
70
|
}
|
|
@@ -108,13 +111,21 @@ export function createPropsResolver( { transformers, schema: initialSchema, onPr
|
|
|
108
111
|
props: resolvedValue,
|
|
109
112
|
schema: transformablePropType.shape,
|
|
110
113
|
signal,
|
|
114
|
+
renderContext,
|
|
111
115
|
} );
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
if ( transformablePropType.kind === 'array' ) {
|
|
115
119
|
resolvedValue = await Promise.all(
|
|
116
120
|
resolvedValue.map( ( item: PropValue ) =>
|
|
117
|
-
transform( {
|
|
121
|
+
transform( {
|
|
122
|
+
value: item,
|
|
123
|
+
key,
|
|
124
|
+
type: transformablePropType.item_prop_type,
|
|
125
|
+
depth,
|
|
126
|
+
signal,
|
|
127
|
+
renderContext,
|
|
128
|
+
} )
|
|
118
129
|
)
|
|
119
130
|
);
|
|
120
131
|
}
|
|
@@ -126,9 +137,9 @@ export function createPropsResolver( { transformers, schema: initialSchema, onPr
|
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
try {
|
|
129
|
-
const transformed = await transformer( resolvedValue, { key, signal } );
|
|
140
|
+
const transformed = await transformer( resolvedValue, { key, signal, renderContext } );
|
|
130
141
|
|
|
131
|
-
return transform( { value: transformed, key, type, signal, depth: depth + 1 } );
|
|
142
|
+
return transform( { value: transformed, key, type, signal, depth: depth + 1, renderContext } );
|
|
132
143
|
} catch {
|
|
133
144
|
return null;
|
|
134
145
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { type RenderContext } from '../legacy/types';
|
|
2
|
+
|
|
3
|
+
export type TransformerOptions< TContext extends RenderContext = RenderContext > = {
|
|
4
|
+
key: string;
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
renderContext?: TContext;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type UnbrandedTransformer< TValue > = ( value: TValue, options: TransformerOptions ) => unknown;
|
|
8
10
|
|
|
9
11
|
export type Transformer< TValue > = UnbrandedTransformer< TValue > & {
|
|
10
12
|
__transformer: true;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export class RenderContext< TContext extends Record< string, unknown > > {
|
|
2
|
-
private key: string;
|
|
3
|
-
private context = new Map< string, TContext >();
|
|
4
|
-
|
|
5
|
-
public constructor( key: string, initialContext: TContext ) {
|
|
6
|
-
this.key = key;
|
|
7
|
-
this.context.set( this.key, initialContext );
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
public get(): TContext {
|
|
11
|
-
return this.context.get( this.key ) as TContext;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public set( context: TContext ) {
|
|
15
|
-
this.context.set( this.key, context );
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
public update( updates: TContext ) {
|
|
19
|
-
const currentContext = this.context.get( this.key );
|
|
20
|
-
|
|
21
|
-
if ( ! currentContext ) {
|
|
22
|
-
return this.set( updates );
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
this.context.set( this.key, { ...currentContext, ...updates } );
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
public delete() {
|
|
29
|
-
this.context.delete( this.key );
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
public clear() {
|
|
33
|
-
this.context.clear();
|
|
34
|
-
}
|
|
35
|
-
}
|