@elementor/editor-canvas 0.15.4 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +38 -0
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +448 -281
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +437 -267
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
- package/src/__tests__/styles-prop-resolver.test.ts +1 -0
- package/src/components/__tests__/style-renderer.test.tsx +65 -0
- package/src/components/style-renderer.tsx +32 -0
- package/src/hooks/__tests__/use-style-items.test.ts +136 -0
- package/src/hooks/__tests__/use-style-prop-resolver.test.ts +51 -0
- package/src/hooks/use-on-mount.ts +13 -0
- package/src/hooks/use-style-items.ts +78 -0
- package/src/hooks/use-style-prop-resolver.ts +22 -0
- package/src/hooks/use-style-renderer.ts +19 -0
- package/src/index.ts +1 -0
- package/src/init.tsx +9 -2
- package/src/legacy/create-element-type.ts +14 -0
- package/src/legacy/create-templated-element-type.ts +1 -1
- package/src/legacy/types.ts +9 -0
- package/src/prevent-link-in-link-commands.ts +132 -0
- package/src/renderers/__tests__/{render-styles.test.ts → create-styles-renderer.test.ts} +35 -19
- package/src/renderers/{render-styles.ts → create-styles-renderer.ts} +35 -32
- package/src/sync/{get-canvas-iframe-body.ts → get-canvas-iframe-head.ts} +2 -2
- package/src/sync/types.ts +7 -0
- package/src/utils/abort-previous-runs.ts +16 -0
- package/src/__tests__/init-styles-renderer.test.ts +0 -112
- package/src/init-styles-renderer.ts +0 -84
- /package/src/{legacy → utils}/__tests__/signalized-process.test.ts +0 -0
- /package/src/{legacy → utils}/signalized-process.ts +0 -0
package/dist/index.mjs
CHANGED
|
@@ -132,6 +132,151 @@ function useElementsDom() {
|
|
|
132
132
|
);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
// src/components/style-renderer.tsx
|
|
136
|
+
import * as React3 from "react";
|
|
137
|
+
import { __privateUseListenTo as useListenTo2, commandEndEvent } from "@elementor/editor-v1-adapters";
|
|
138
|
+
import { Portal } from "@elementor/ui";
|
|
139
|
+
|
|
140
|
+
// src/hooks/use-style-items.ts
|
|
141
|
+
import { useEffect as useEffect4, useMemo as useMemo3, useState as useState2 } from "react";
|
|
142
|
+
import { stylesRepository } from "@elementor/editor-styles-repository";
|
|
143
|
+
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
144
|
+
|
|
145
|
+
// src/utils/abort-previous-runs.ts
|
|
146
|
+
function abortPreviousRuns(cb) {
|
|
147
|
+
let abortController = null;
|
|
148
|
+
return (...args) => {
|
|
149
|
+
if (abortController) {
|
|
150
|
+
abortController.abort();
|
|
151
|
+
}
|
|
152
|
+
abortController = new AbortController();
|
|
153
|
+
return cb(abortController, ...args);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/utils/signalized-process.ts
|
|
158
|
+
function signalizedProcess(signal, steps = []) {
|
|
159
|
+
return {
|
|
160
|
+
then: (cb) => {
|
|
161
|
+
steps.push(cb);
|
|
162
|
+
return signalizedProcess(signal, steps);
|
|
163
|
+
},
|
|
164
|
+
execute: async () => {
|
|
165
|
+
let lastResult;
|
|
166
|
+
for (const step of steps) {
|
|
167
|
+
if (signal.aborted) {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
lastResult = await step(lastResult, signal);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/hooks/use-on-mount.ts
|
|
177
|
+
import { useEffect as useEffect3, useRef } from "react";
|
|
178
|
+
function useOnMount(cb) {
|
|
179
|
+
const mounted = useRef(false);
|
|
180
|
+
useEffect3(() => {
|
|
181
|
+
if (!mounted.current) {
|
|
182
|
+
mounted.current = true;
|
|
183
|
+
cb();
|
|
184
|
+
}
|
|
185
|
+
}, []);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/hooks/use-style-prop-resolver.ts
|
|
189
|
+
import { useMemo } from "react";
|
|
190
|
+
import { getStylesSchema } from "@elementor/editor-styles";
|
|
191
|
+
|
|
192
|
+
// src/renderers/create-props-resolver.ts
|
|
193
|
+
import {
|
|
194
|
+
isTransformable
|
|
195
|
+
} from "@elementor/editor-props";
|
|
196
|
+
|
|
197
|
+
// src/renderers/multi-props.ts
|
|
198
|
+
var isMultiProps = (propValue) => {
|
|
199
|
+
return !!propValue && typeof propValue === "object" && "$$multi-props" in propValue && propValue["$$multi-props"] === true;
|
|
200
|
+
};
|
|
201
|
+
var createMultiPropsValue = (props) => {
|
|
202
|
+
return {
|
|
203
|
+
"$$multi-props": true,
|
|
204
|
+
value: props
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
var getMultiPropsValue = (multiProps) => {
|
|
208
|
+
return multiProps.value;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/renderers/create-props-resolver.ts
|
|
212
|
+
var TRANSFORM_DEPTH_LIMIT = 3;
|
|
213
|
+
function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
|
|
214
|
+
async function resolve({ props, schema, signal }) {
|
|
215
|
+
schema = schema ?? initialSchema;
|
|
216
|
+
const promises = Promise.all(
|
|
217
|
+
Object.entries(schema).map(async ([key, type]) => {
|
|
218
|
+
const value = props[key] ?? type.default;
|
|
219
|
+
const transformed = await transform({ value, key, type, signal });
|
|
220
|
+
onPropResolve?.({ key, value: transformed });
|
|
221
|
+
if (isMultiProps(transformed)) {
|
|
222
|
+
return getMultiPropsValue(transformed);
|
|
223
|
+
}
|
|
224
|
+
return { [key]: transformed };
|
|
225
|
+
})
|
|
226
|
+
);
|
|
227
|
+
return Object.assign({}, ...(await promises).filter(Boolean));
|
|
228
|
+
}
|
|
229
|
+
async function transform({ value, key, type, signal, depth = 0 }) {
|
|
230
|
+
if (value === null || value === void 0) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
if (!isTransformable(value)) {
|
|
234
|
+
return value;
|
|
235
|
+
}
|
|
236
|
+
if (depth > TRANSFORM_DEPTH_LIMIT) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
if (value.disabled === true) {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
if (type.kind === "union") {
|
|
243
|
+
type = type.prop_types[value.$$type];
|
|
244
|
+
if (!type) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (value.$$type !== type.key) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
let resolvedValue = value.value;
|
|
252
|
+
if (type.kind === "object") {
|
|
253
|
+
resolvedValue = await resolve({
|
|
254
|
+
props: resolvedValue,
|
|
255
|
+
schema: type.shape,
|
|
256
|
+
signal
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
if (type.kind === "array") {
|
|
260
|
+
resolvedValue = await Promise.all(
|
|
261
|
+
resolvedValue.map(
|
|
262
|
+
(item) => transform({ value: item, key, type: type.item_prop_type, depth, signal })
|
|
263
|
+
)
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
const transformer = transformers.get(value.$$type);
|
|
267
|
+
if (!transformer) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
const transformed = await transformer(resolvedValue, { key, signal });
|
|
272
|
+
return transform({ value: transformed, key, type, signal, depth: depth + 1 });
|
|
273
|
+
} catch {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return resolve;
|
|
278
|
+
}
|
|
279
|
+
|
|
135
280
|
// src/transformers/create-transformers-registry.ts
|
|
136
281
|
function createTransformersRegistry() {
|
|
137
282
|
const transformers = {};
|
|
@@ -151,6 +296,176 @@ function createTransformersRegistry() {
|
|
|
151
296
|
};
|
|
152
297
|
}
|
|
153
298
|
|
|
299
|
+
// src/style-transformers-registry.ts
|
|
300
|
+
var styleTransformersRegistry = createTransformersRegistry();
|
|
301
|
+
|
|
302
|
+
// src/sync/enqueue-font.ts
|
|
303
|
+
var enqueueFont = (fontFamily, context = "preview") => {
|
|
304
|
+
const extendedWindow = window;
|
|
305
|
+
return extendedWindow.elementor?.helpers?.enqueueFont?.(fontFamily, context) ?? null;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// src/hooks/use-style-prop-resolver.ts
|
|
309
|
+
function useStylePropResolver() {
|
|
310
|
+
return useMemo(() => {
|
|
311
|
+
return createPropsResolver({
|
|
312
|
+
transformers: styleTransformersRegistry,
|
|
313
|
+
schema: getStylesSchema(),
|
|
314
|
+
onPropResolve: ({ key, value }) => {
|
|
315
|
+
if (key !== "font-family" || typeof value !== "string") {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
enqueueFont(value);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}, []);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/hooks/use-style-renderer.ts
|
|
325
|
+
import { useMemo as useMemo2 } from "react";
|
|
326
|
+
import { useBreakpointsMap } from "@elementor/editor-responsive";
|
|
327
|
+
|
|
328
|
+
// src/renderers/errors.ts
|
|
329
|
+
import { createError } from "@elementor/utils";
|
|
330
|
+
var UnknownStyleTypeError = createError({
|
|
331
|
+
code: "unknown_style_type",
|
|
332
|
+
message: "Unknown style type"
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// src/renderers/create-styles-renderer.ts
|
|
336
|
+
var SELECTORS_MAP = {
|
|
337
|
+
class: "."
|
|
338
|
+
};
|
|
339
|
+
function createStylesRenderer({ resolve, breakpoints, selectorPrefix = "" }) {
|
|
340
|
+
return async ({ styles, signal }) => {
|
|
341
|
+
const stylesCssPromises = styles.map(async (style) => {
|
|
342
|
+
const variantCssPromises = Object.values(style.variants).map(async (variant) => {
|
|
343
|
+
const css = await propsToCss({ props: variant.props, resolve, signal });
|
|
344
|
+
return createStyleWrapper().forStyle(style).withPrefix(selectorPrefix).withState(variant.meta.state).withMediaQuery(variant.meta.breakpoint ? breakpoints[variant.meta.breakpoint] : null).wrap(css);
|
|
345
|
+
});
|
|
346
|
+
const variantsCss = await Promise.all(variantCssPromises);
|
|
347
|
+
return {
|
|
348
|
+
id: style.id,
|
|
349
|
+
value: variantsCss.join("")
|
|
350
|
+
};
|
|
351
|
+
});
|
|
352
|
+
return await Promise.all(stylesCssPromises);
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
function createStyleWrapper(value = "", wrapper) {
|
|
356
|
+
return {
|
|
357
|
+
forStyle: ({ id, type }) => {
|
|
358
|
+
const symbol = SELECTORS_MAP[type];
|
|
359
|
+
if (!symbol) {
|
|
360
|
+
throw new UnknownStyleTypeError({ context: { type } });
|
|
361
|
+
}
|
|
362
|
+
return createStyleWrapper(`${value}${symbol}${id}`, wrapper);
|
|
363
|
+
},
|
|
364
|
+
withPrefix: (prefix) => createStyleWrapper([prefix, value].filter(Boolean).join(" "), wrapper),
|
|
365
|
+
withState: (state) => createStyleWrapper(state ? `${value}:${state}` : value, wrapper),
|
|
366
|
+
withMediaQuery: (breakpoint) => {
|
|
367
|
+
if (!breakpoint?.type) {
|
|
368
|
+
return createStyleWrapper(value, wrapper);
|
|
369
|
+
}
|
|
370
|
+
const size2 = `${breakpoint.type}:${breakpoint.width}px`;
|
|
371
|
+
return createStyleWrapper(value, (css) => `@media(${size2}){${css}}`);
|
|
372
|
+
},
|
|
373
|
+
wrap: (css) => {
|
|
374
|
+
const res = `${value}{${css}}`;
|
|
375
|
+
if (!wrapper) {
|
|
376
|
+
return res;
|
|
377
|
+
}
|
|
378
|
+
return wrapper(res);
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
async function propsToCss({ props, resolve, signal }) {
|
|
383
|
+
const transformed = await resolve({ props, signal });
|
|
384
|
+
return Object.entries(transformed).reduce((acc, [propName, propValue]) => {
|
|
385
|
+
if (propValue === null) {
|
|
386
|
+
return acc;
|
|
387
|
+
}
|
|
388
|
+
acc.push(propName + ":" + propValue + ";");
|
|
389
|
+
return acc;
|
|
390
|
+
}, []).join("");
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// src/hooks/use-style-renderer.ts
|
|
394
|
+
var SELECTOR_PREFIX = ".elementor";
|
|
395
|
+
function useStyleRenderer(resolve) {
|
|
396
|
+
const breakpoints = useBreakpointsMap();
|
|
397
|
+
return useMemo2(() => {
|
|
398
|
+
return createStylesRenderer({
|
|
399
|
+
selectorPrefix: SELECTOR_PREFIX,
|
|
400
|
+
breakpoints,
|
|
401
|
+
resolve
|
|
402
|
+
});
|
|
403
|
+
}, [resolve, breakpoints]);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/hooks/use-style-items.ts
|
|
407
|
+
function useStyleItems() {
|
|
408
|
+
const resolve = useStylePropResolver();
|
|
409
|
+
const renderStyles = useStyleRenderer(resolve);
|
|
410
|
+
const [styleItems, setStyleItems] = useState2({});
|
|
411
|
+
const providerAndSubscribers = useMemo3(() => {
|
|
412
|
+
return stylesRepository.getProviders().map((provider) => {
|
|
413
|
+
return {
|
|
414
|
+
provider,
|
|
415
|
+
subscriber: createProviderSubscriber({
|
|
416
|
+
provider,
|
|
417
|
+
renderStyles,
|
|
418
|
+
setStyleItems
|
|
419
|
+
})
|
|
420
|
+
};
|
|
421
|
+
});
|
|
422
|
+
}, [renderStyles]);
|
|
423
|
+
useEffect4(() => {
|
|
424
|
+
const unsubscribes = providerAndSubscribers.map(
|
|
425
|
+
({ provider, subscriber }) => provider.subscribe(subscriber)
|
|
426
|
+
);
|
|
427
|
+
return () => {
|
|
428
|
+
unsubscribes.forEach((unsubscribe) => unsubscribe());
|
|
429
|
+
};
|
|
430
|
+
}, [providerAndSubscribers]);
|
|
431
|
+
useOnMount(() => {
|
|
432
|
+
registerDataHook("after", "editor/documents/attach-preview", async () => {
|
|
433
|
+
const promises = providerAndSubscribers.map(async ({ subscriber }) => subscriber());
|
|
434
|
+
await Promise.all(promises);
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
return Object.values(styleItems).sort(({ provider: providerA }, { provider: providerB }) => providerA.priority - providerB.priority).flatMap(({ items }) => items);
|
|
438
|
+
}
|
|
439
|
+
function createProviderSubscriber({ provider, renderStyles, setStyleItems }) {
|
|
440
|
+
return abortPreviousRuns(
|
|
441
|
+
(abortController) => signalizedProcess(abortController.signal).then((_, signal) => renderStyles({ styles: provider.actions.get(), signal })).then((items) => {
|
|
442
|
+
setStyleItems((prev) => ({
|
|
443
|
+
...prev,
|
|
444
|
+
[provider.key]: { provider, items }
|
|
445
|
+
}));
|
|
446
|
+
}).execute()
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// src/sync/get-canvas-iframe-head.ts
|
|
451
|
+
function getCanvasIframeHead() {
|
|
452
|
+
const extendedWindow = window;
|
|
453
|
+
return extendedWindow.elementor?.$preview?.[0]?.contentDocument?.head;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// src/components/style-renderer.tsx
|
|
457
|
+
function StyleRenderer() {
|
|
458
|
+
const container = usePortalContainer();
|
|
459
|
+
const styleItems = useStyleItems();
|
|
460
|
+
if (!container) {
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
return /* @__PURE__ */ React3.createElement(Portal, { container }, /* @__PURE__ */ React3.createElement(React3.Fragment, null, styleItems.map((item) => /* @__PURE__ */ React3.createElement("style", { "data-e-style-id": item.id, key: item.id }, item.value))));
|
|
464
|
+
}
|
|
465
|
+
function usePortalContainer() {
|
|
466
|
+
return useListenTo2(commandEndEvent("editor/documents/attach-preview"), () => getCanvasIframeHead());
|
|
467
|
+
}
|
|
468
|
+
|
|
154
469
|
// src/settings-transformers-registry.ts
|
|
155
470
|
var settingsTransformersRegistry = createTransformersRegistry();
|
|
156
471
|
|
|
@@ -215,9 +530,6 @@ function initSettingsTransformers() {
|
|
|
215
530
|
settingsTransformersRegistry.register("classes", arrayTransformer).register("link", linkTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).registerFallback(plainTransformer);
|
|
216
531
|
}
|
|
217
532
|
|
|
218
|
-
// src/style-transformers-registry.ts
|
|
219
|
-
var styleTransformersRegistry = createTransformersRegistry();
|
|
220
|
-
|
|
221
533
|
// src/transformers/styles/background-color-overlay-transformer.ts
|
|
222
534
|
var backgroundColorOverlayTransformer = createTransformer((value) => {
|
|
223
535
|
const { color = null } = value;
|
|
@@ -279,20 +591,6 @@ var createCombineArrayTransformer = (delimiter) => {
|
|
|
279
591
|
return createTransformer((value) => value.filter(Boolean).join(delimiter));
|
|
280
592
|
};
|
|
281
593
|
|
|
282
|
-
// src/renderers/multi-props.ts
|
|
283
|
-
var isMultiProps = (propValue) => {
|
|
284
|
-
return !!propValue && typeof propValue === "object" && "$$multi-props" in propValue && propValue["$$multi-props"] === true;
|
|
285
|
-
};
|
|
286
|
-
var createMultiPropsValue = (props) => {
|
|
287
|
-
return {
|
|
288
|
-
"$$multi-props": true,
|
|
289
|
-
value: props
|
|
290
|
-
};
|
|
291
|
-
};
|
|
292
|
-
var getMultiPropsValue = (multiProps) => {
|
|
293
|
-
return multiProps.value;
|
|
294
|
-
};
|
|
295
|
-
|
|
296
594
|
// src/transformers/styles/create-multi-props-transformer.ts
|
|
297
595
|
var createMultiPropsTransformer = (keys, keyGenerator) => {
|
|
298
596
|
return createTransformer((value, { key: propKey }) => {
|
|
@@ -347,223 +645,9 @@ function initStyleTransformers() {
|
|
|
347
645
|
).registerFallback(plainTransformer);
|
|
348
646
|
}
|
|
349
647
|
|
|
350
|
-
// src/init-styles-renderer.ts
|
|
351
|
-
import { getBreakpointsMap } from "@elementor/editor-responsive";
|
|
352
|
-
import { getStylesSchema } from "@elementor/editor-styles";
|
|
353
|
-
import { stylesRepository } from "@elementor/editor-styles-repository";
|
|
354
|
-
import { __privateListenTo as listenTo, registerDataHook, v1ReadyEvent } from "@elementor/editor-v1-adapters";
|
|
355
|
-
|
|
356
|
-
// src/renderers/create-props-resolver.ts
|
|
357
|
-
import {
|
|
358
|
-
isTransformable
|
|
359
|
-
} from "@elementor/editor-props";
|
|
360
|
-
var TRANSFORM_DEPTH_LIMIT = 3;
|
|
361
|
-
function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
|
|
362
|
-
async function resolve({ props, schema, signal }) {
|
|
363
|
-
schema = schema ?? initialSchema;
|
|
364
|
-
const promises = Promise.all(
|
|
365
|
-
Object.entries(schema).map(async ([key, type]) => {
|
|
366
|
-
const value = props[key] ?? type.default;
|
|
367
|
-
const transformed = await transform({ value, key, type, signal });
|
|
368
|
-
onPropResolve?.({ key, value: transformed });
|
|
369
|
-
if (isMultiProps(transformed)) {
|
|
370
|
-
return getMultiPropsValue(transformed);
|
|
371
|
-
}
|
|
372
|
-
return { [key]: transformed };
|
|
373
|
-
})
|
|
374
|
-
);
|
|
375
|
-
return Object.assign({}, ...(await promises).filter(Boolean));
|
|
376
|
-
}
|
|
377
|
-
async function transform({ value, key, type, signal, depth = 0 }) {
|
|
378
|
-
if (value === null || value === void 0) {
|
|
379
|
-
return null;
|
|
380
|
-
}
|
|
381
|
-
if (!isTransformable(value)) {
|
|
382
|
-
return value;
|
|
383
|
-
}
|
|
384
|
-
if (depth > TRANSFORM_DEPTH_LIMIT) {
|
|
385
|
-
return null;
|
|
386
|
-
}
|
|
387
|
-
if (value.disabled === true) {
|
|
388
|
-
return null;
|
|
389
|
-
}
|
|
390
|
-
if (type.kind === "union") {
|
|
391
|
-
type = type.prop_types[value.$$type];
|
|
392
|
-
if (!type) {
|
|
393
|
-
return null;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
if (value.$$type !== type.key) {
|
|
397
|
-
return null;
|
|
398
|
-
}
|
|
399
|
-
let resolvedValue = value.value;
|
|
400
|
-
if (type.kind === "object") {
|
|
401
|
-
resolvedValue = await resolve({
|
|
402
|
-
props: resolvedValue,
|
|
403
|
-
schema: type.shape,
|
|
404
|
-
signal
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
if (type.kind === "array") {
|
|
408
|
-
resolvedValue = await Promise.all(
|
|
409
|
-
resolvedValue.map(
|
|
410
|
-
(item) => transform({ value: item, key, type: type.item_prop_type, depth, signal })
|
|
411
|
-
)
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
const transformer = transformers.get(value.$$type);
|
|
415
|
-
if (!transformer) {
|
|
416
|
-
return null;
|
|
417
|
-
}
|
|
418
|
-
try {
|
|
419
|
-
const transformed = await transformer(resolvedValue, { key, signal });
|
|
420
|
-
return transform({ value: transformed, key, type, signal, depth: depth + 1 });
|
|
421
|
-
} catch {
|
|
422
|
-
return null;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
return resolve;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// src/renderers/errors.ts
|
|
429
|
-
import { createError } from "@elementor/utils";
|
|
430
|
-
var UnknownStyleTypeError = createError({
|
|
431
|
-
code: "unknown_style_type",
|
|
432
|
-
message: "Unknown style type"
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
// src/renderers/render-styles.ts
|
|
436
|
-
var SELECTORS_MAP = {
|
|
437
|
-
class: "."
|
|
438
|
-
};
|
|
439
|
-
async function renderStyles({
|
|
440
|
-
resolve,
|
|
441
|
-
styles,
|
|
442
|
-
breakpoints,
|
|
443
|
-
selectorPrefix = "",
|
|
444
|
-
signal
|
|
445
|
-
}) {
|
|
446
|
-
const stylesCssPromises = styles.map(async (style) => {
|
|
447
|
-
const variantCssPromises = Object.values(style.variants).map(async (variant) => {
|
|
448
|
-
const css = await propsToCss({ props: variant.props, resolve, signal });
|
|
449
|
-
return createStyleWrapper().forStyle(style).withPrefix(selectorPrefix).withState(variant.meta.state).withMediaQuery(variant.meta.breakpoint ? breakpoints[variant.meta.breakpoint] : null).wrap(css);
|
|
450
|
-
});
|
|
451
|
-
const variantsCss = await Promise.all(variantCssPromises);
|
|
452
|
-
return wrapCssWithStyleElement(style.id, variantsCss.join(""));
|
|
453
|
-
});
|
|
454
|
-
const stylesCss = await Promise.all(stylesCssPromises);
|
|
455
|
-
return stylesCss.join("");
|
|
456
|
-
}
|
|
457
|
-
function createStyleWrapper(value = "", wrapper) {
|
|
458
|
-
return {
|
|
459
|
-
forStyle: ({ id, type }) => {
|
|
460
|
-
const symbol = SELECTORS_MAP[type];
|
|
461
|
-
if (!symbol) {
|
|
462
|
-
throw new UnknownStyleTypeError({ context: { type } });
|
|
463
|
-
}
|
|
464
|
-
return createStyleWrapper(`${value}${symbol}${id}`, wrapper);
|
|
465
|
-
},
|
|
466
|
-
withPrefix: (prefix) => createStyleWrapper([prefix, value].filter(Boolean).join(" "), wrapper),
|
|
467
|
-
withState: (state) => createStyleWrapper(state ? `${value}:${state}` : value, wrapper),
|
|
468
|
-
withMediaQuery: (breakpoint) => {
|
|
469
|
-
if (!breakpoint?.type) {
|
|
470
|
-
return createStyleWrapper(value, wrapper);
|
|
471
|
-
}
|
|
472
|
-
const size2 = `${breakpoint.type}:${breakpoint.width}px`;
|
|
473
|
-
return createStyleWrapper(value, (css) => `@media(${size2}){${css}}`);
|
|
474
|
-
},
|
|
475
|
-
wrap: (css) => {
|
|
476
|
-
const res = `${value}{${css}}`;
|
|
477
|
-
if (!wrapper) {
|
|
478
|
-
return res;
|
|
479
|
-
}
|
|
480
|
-
return wrapper(res);
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
async function propsToCss({ props, resolve, signal }) {
|
|
485
|
-
const transformed = await resolve({ props, signal });
|
|
486
|
-
return Object.entries(transformed).reduce((acc, [propName, propValue]) => {
|
|
487
|
-
if (propValue === null) {
|
|
488
|
-
return acc;
|
|
489
|
-
}
|
|
490
|
-
acc.push(propName + ":" + propValue + ";");
|
|
491
|
-
return acc;
|
|
492
|
-
}, []).join("");
|
|
493
|
-
}
|
|
494
|
-
function wrapCssWithStyleElement(id, css) {
|
|
495
|
-
return `<style data-style-id="${id}">${css}</style>`;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// src/sync/enqueue-font.ts
|
|
499
|
-
var enqueueFont = (fontFamily, context = "preview") => {
|
|
500
|
-
const extendedWindow = window;
|
|
501
|
-
return extendedWindow.elementor?.helpers?.enqueueFont?.(fontFamily, context) ?? null;
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
// src/sync/get-canvas-iframe-body.ts
|
|
505
|
-
function getCanvasIframeBody() {
|
|
506
|
-
const extendedWindow = window;
|
|
507
|
-
return extendedWindow.elementor?.$preview?.[0]?.contentDocument?.body;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// src/init-styles-renderer.ts
|
|
511
|
-
var WRAPPER_DATA_ATTR = "data-styles-container";
|
|
512
|
-
var SELECTOR_PREFIX = ".elementor";
|
|
513
|
-
function initStylesRenderer() {
|
|
514
|
-
listenTo(v1ReadyEvent(), () => {
|
|
515
|
-
let abortController = null;
|
|
516
|
-
const resolve = createPropsResolver({
|
|
517
|
-
transformers: styleTransformersRegistry,
|
|
518
|
-
schema: getStylesSchema(),
|
|
519
|
-
onPropResolve: enqueueUsedFonts
|
|
520
|
-
});
|
|
521
|
-
const injectStyleElements = async () => {
|
|
522
|
-
const styleContainer = getStylesContainer();
|
|
523
|
-
const styles = stylesRepository.all().reverse();
|
|
524
|
-
const breakpoints = getBreakpointsMap();
|
|
525
|
-
if (abortController) {
|
|
526
|
-
abortController.abort();
|
|
527
|
-
}
|
|
528
|
-
abortController = new AbortController();
|
|
529
|
-
styleContainer.innerHTML = await renderStyles({
|
|
530
|
-
styles,
|
|
531
|
-
resolve,
|
|
532
|
-
breakpoints,
|
|
533
|
-
selectorPrefix: SELECTOR_PREFIX,
|
|
534
|
-
signal: abortController.signal
|
|
535
|
-
});
|
|
536
|
-
};
|
|
537
|
-
stylesRepository.subscribe(injectStyleElements);
|
|
538
|
-
registerDataHook("after", "editor/documents/attach-preview", injectStyleElements);
|
|
539
|
-
});
|
|
540
|
-
}
|
|
541
|
-
function getStylesContainer() {
|
|
542
|
-
const preview = getCanvasIframeBody();
|
|
543
|
-
const stylesContainer = preview?.querySelector(`[${WRAPPER_DATA_ATTR}]`);
|
|
544
|
-
if (stylesContainer) {
|
|
545
|
-
return stylesContainer;
|
|
546
|
-
}
|
|
547
|
-
const el = createStylesContainer();
|
|
548
|
-
preview?.prepend(el);
|
|
549
|
-
return el;
|
|
550
|
-
}
|
|
551
|
-
function createStylesContainer() {
|
|
552
|
-
const el = document.createElement("div");
|
|
553
|
-
el.style.display = "none";
|
|
554
|
-
el.setAttribute(WRAPPER_DATA_ATTR, "");
|
|
555
|
-
return el;
|
|
556
|
-
}
|
|
557
|
-
function enqueueUsedFonts({ key, value }) {
|
|
558
|
-
if (key !== "font-family" || typeof value !== "string") {
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
enqueueFont(value);
|
|
562
|
-
}
|
|
563
|
-
|
|
564
648
|
// src/legacy/init-legacy-views.ts
|
|
565
649
|
import { getWidgetsCache } from "@elementor/editor-elements";
|
|
566
|
-
import { __privateListenTo, v1ReadyEvent
|
|
650
|
+
import { __privateListenTo, v1ReadyEvent } from "@elementor/editor-v1-adapters";
|
|
567
651
|
|
|
568
652
|
// src/renderers/create-dom-renderer.ts
|
|
569
653
|
import { createArrayLoader, createEnvironment } from "@elementor/twing";
|
|
@@ -629,11 +713,13 @@ function createElementViewClassDeclaration() {
|
|
|
629
713
|
onRender(...args) {
|
|
630
714
|
super.onRender(...args);
|
|
631
715
|
this.#dispatchEvent("elementor/preview/atomic-widget/render");
|
|
716
|
+
this.#dispatchPreviewEvent("elementor/element/render");
|
|
632
717
|
}
|
|
633
718
|
// Dispatch `destroy` event so the overlay layer will be updated
|
|
634
719
|
onDestroy(...args) {
|
|
635
720
|
super.onDestroy(...args);
|
|
636
721
|
this.#dispatchEvent("elementor/preview/atomic-widget/destroy");
|
|
722
|
+
this.#dispatchPreviewEvent("elementor/element/destroy");
|
|
637
723
|
}
|
|
638
724
|
attributes() {
|
|
639
725
|
return {
|
|
@@ -667,31 +753,23 @@ function createElementViewClassDeclaration() {
|
|
|
667
753
|
})
|
|
668
754
|
);
|
|
669
755
|
}
|
|
756
|
+
#dispatchPreviewEvent(eventType) {
|
|
757
|
+
legacyWindow.elementor?.$preview?.[0]?.contentWindow.dispatchEvent(
|
|
758
|
+
new CustomEvent(eventType, {
|
|
759
|
+
detail: {
|
|
760
|
+
id: this.model.get("id"),
|
|
761
|
+
type: this.model.get("widgetType"),
|
|
762
|
+
element: this.getDomElement().get(0)
|
|
763
|
+
}
|
|
764
|
+
})
|
|
765
|
+
);
|
|
766
|
+
}
|
|
670
767
|
getContextMenuGroups() {
|
|
671
768
|
return super.getContextMenuGroups().filter((group) => group.name !== "save");
|
|
672
769
|
}
|
|
673
770
|
};
|
|
674
771
|
}
|
|
675
772
|
|
|
676
|
-
// src/legacy/signalized-process.ts
|
|
677
|
-
function signalizedProcess(signal, steps = []) {
|
|
678
|
-
return {
|
|
679
|
-
then: (cb) => {
|
|
680
|
-
steps.push(cb);
|
|
681
|
-
return signalizedProcess(signal, steps);
|
|
682
|
-
},
|
|
683
|
-
execute: async () => {
|
|
684
|
-
let lastResult;
|
|
685
|
-
for (const step of steps) {
|
|
686
|
-
if (signal.aborted) {
|
|
687
|
-
break;
|
|
688
|
-
}
|
|
689
|
-
lastResult = await step(lastResult, signal);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
};
|
|
693
|
-
}
|
|
694
|
-
|
|
695
773
|
// src/legacy/create-templated-element-type.ts
|
|
696
774
|
function createTemplatedElementType({ type, renderer, element }) {
|
|
697
775
|
const legacyWindow = window;
|
|
@@ -772,7 +850,7 @@ function createTemplatedElementViewClassDeclaration({
|
|
|
772
850
|
|
|
773
851
|
// src/legacy/init-legacy-views.ts
|
|
774
852
|
function initLegacyViews() {
|
|
775
|
-
__privateListenTo(
|
|
853
|
+
__privateListenTo(v1ReadyEvent(), () => {
|
|
776
854
|
const config = getWidgetsCache() ?? {};
|
|
777
855
|
const legacyWindow = window;
|
|
778
856
|
const renderer = createDomRenderer();
|
|
@@ -786,10 +864,97 @@ function initLegacyViews() {
|
|
|
786
864
|
});
|
|
787
865
|
}
|
|
788
866
|
|
|
867
|
+
// src/prevent-link-in-link-commands.ts
|
|
868
|
+
import {
|
|
869
|
+
getAnchoredAncestorId,
|
|
870
|
+
getAnchoredDescendantId,
|
|
871
|
+
isElementAnchored
|
|
872
|
+
} from "@elementor/editor-elements";
|
|
873
|
+
import { notify } from "@elementor/editor-notifications";
|
|
874
|
+
import { blockCommand } from "@elementor/editor-v1-adapters";
|
|
875
|
+
import { __ } from "@wordpress/i18n";
|
|
876
|
+
function initLinkInLinkPrevention() {
|
|
877
|
+
blockCommand({
|
|
878
|
+
command: "document/elements/paste",
|
|
879
|
+
condition: blockLinkInLinkPaste
|
|
880
|
+
});
|
|
881
|
+
blockCommand({
|
|
882
|
+
command: "document/elements/move",
|
|
883
|
+
condition: blockLinkInLinkMove
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
var learnMoreActionProps = {
|
|
887
|
+
href: "https://go.elementor.com/element-link-inside-link-infotip",
|
|
888
|
+
target: "_blank",
|
|
889
|
+
color: "inherit",
|
|
890
|
+
variant: "text",
|
|
891
|
+
sx: {
|
|
892
|
+
marginInlineStart: "20px"
|
|
893
|
+
},
|
|
894
|
+
children: "Learn more"
|
|
895
|
+
};
|
|
896
|
+
function blockLinkInLinkPaste(args) {
|
|
897
|
+
const { containers = [args.container], storageType } = args;
|
|
898
|
+
const targetElements = containers;
|
|
899
|
+
if (storageType !== "localstorage") {
|
|
900
|
+
return false;
|
|
901
|
+
}
|
|
902
|
+
const data = window?.elementorCommon?.storage?.get();
|
|
903
|
+
if (!data?.clipboard?.elements) {
|
|
904
|
+
return false;
|
|
905
|
+
}
|
|
906
|
+
const sourceElements = data.clipboard.elements;
|
|
907
|
+
const notification = {
|
|
908
|
+
type: "default",
|
|
909
|
+
message: __(
|
|
910
|
+
"To paste a link to this element, first remove the link from it's parent container.",
|
|
911
|
+
"elementor"
|
|
912
|
+
),
|
|
913
|
+
id: "paste-in-link-blocked",
|
|
914
|
+
additionalActionProps: [learnMoreActionProps]
|
|
915
|
+
};
|
|
916
|
+
const blocked = shouldBlock(sourceElements, targetElements);
|
|
917
|
+
if (blocked) {
|
|
918
|
+
notify(notification);
|
|
919
|
+
}
|
|
920
|
+
return blocked;
|
|
921
|
+
}
|
|
922
|
+
function blockLinkInLinkMove(args) {
|
|
923
|
+
const { containers = [args.container], target } = args;
|
|
924
|
+
const sourceElements = containers;
|
|
925
|
+
const targetElement = target;
|
|
926
|
+
const notification = {
|
|
927
|
+
type: "default",
|
|
928
|
+
message: __("To drag a link to this element, first remove the link from it's parent container.", "elementor"),
|
|
929
|
+
id: "move-in-link-blocked",
|
|
930
|
+
additionalActionProps: [learnMoreActionProps]
|
|
931
|
+
};
|
|
932
|
+
const isBlocked = shouldBlock(sourceElements, [targetElement]);
|
|
933
|
+
if (isBlocked) {
|
|
934
|
+
notify(notification);
|
|
935
|
+
}
|
|
936
|
+
return isBlocked;
|
|
937
|
+
}
|
|
938
|
+
function shouldBlock(sourceElements, targetElements) {
|
|
939
|
+
if (!sourceElements?.length || !targetElements?.length) {
|
|
940
|
+
return false;
|
|
941
|
+
}
|
|
942
|
+
const isSourceContainsAnAnchor = sourceElements.some((src) => {
|
|
943
|
+
return src?.id ? isElementAnchored(src.id) || !!getAnchoredDescendantId(src.id) : false;
|
|
944
|
+
});
|
|
945
|
+
if (!isSourceContainsAnAnchor) {
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
const isTargetContainsAnAnchor = targetElements.some((target) => {
|
|
949
|
+
return target?.id ? isElementAnchored(target.id) || !!getAnchoredAncestorId(target.id) : false;
|
|
950
|
+
});
|
|
951
|
+
return isTargetContainsAnAnchor;
|
|
952
|
+
}
|
|
953
|
+
|
|
789
954
|
// src/style-commands/paste-style.ts
|
|
790
955
|
import {
|
|
791
|
-
__privateListenTo as
|
|
792
|
-
blockCommand,
|
|
956
|
+
__privateListenTo as listenTo,
|
|
957
|
+
blockCommand as blockCommand2,
|
|
793
958
|
commandStartEvent
|
|
794
959
|
} from "@elementor/editor-v1-adapters";
|
|
795
960
|
|
|
@@ -802,12 +967,12 @@ import {
|
|
|
802
967
|
} from "@elementor/editor-elements";
|
|
803
968
|
import { LOCAL_STYLES_RESERVED_LABEL } from "@elementor/editor-styles-repository";
|
|
804
969
|
import { undoable } from "@elementor/editor-v1-adapters";
|
|
805
|
-
import { __ as
|
|
970
|
+
import { __ as __3 } from "@wordpress/i18n";
|
|
806
971
|
|
|
807
972
|
// src/style-commands/utils.ts
|
|
808
973
|
import { getElementLabel, getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
|
|
809
974
|
import { CLASSES_PROP_KEY } from "@elementor/editor-props";
|
|
810
|
-
import { __ } from "@wordpress/i18n";
|
|
975
|
+
import { __ as __2 } from "@wordpress/i18n";
|
|
811
976
|
function hasAtomicWidgets(args) {
|
|
812
977
|
const { containers = [args.container] } = args;
|
|
813
978
|
return containers.some(isAtomicWidget);
|
|
@@ -843,7 +1008,7 @@ function getClipboardElements(storageKey = "clipboard") {
|
|
|
843
1008
|
}
|
|
844
1009
|
}
|
|
845
1010
|
function getTitleForContainers(containers) {
|
|
846
|
-
return containers.length > 1 ?
|
|
1011
|
+
return containers.length > 1 ? __2("Elements", "elementor") : getElementLabel(containers[0].id);
|
|
847
1012
|
}
|
|
848
1013
|
|
|
849
1014
|
// src/style-commands/undoable-actions/paste-element-style.ts
|
|
@@ -915,18 +1080,18 @@ var undoablePasteElementStyle = () => undoable(
|
|
|
915
1080
|
},
|
|
916
1081
|
{
|
|
917
1082
|
title: ({ containers }) => getTitleForContainers(containers),
|
|
918
|
-
subtitle:
|
|
1083
|
+
subtitle: __3("Style Pasted", "elementor")
|
|
919
1084
|
}
|
|
920
1085
|
);
|
|
921
1086
|
|
|
922
1087
|
// src/style-commands/paste-style.ts
|
|
923
1088
|
function initPasteStyleCommand() {
|
|
924
1089
|
const pasteElementStyleCommand = undoablePasteElementStyle();
|
|
925
|
-
|
|
1090
|
+
blockCommand2({
|
|
926
1091
|
command: "document/elements/paste-style",
|
|
927
1092
|
condition: hasAtomicWidgets
|
|
928
1093
|
});
|
|
929
|
-
|
|
1094
|
+
listenTo(
|
|
930
1095
|
commandStartEvent("document/elements/paste-style"),
|
|
931
1096
|
(e) => pasteStyles(e.args, pasteElementStyleCommand)
|
|
932
1097
|
);
|
|
@@ -952,8 +1117,8 @@ function pasteStyles(args, pasteCallback) {
|
|
|
952
1117
|
|
|
953
1118
|
// src/style-commands/reset-style.ts
|
|
954
1119
|
import {
|
|
955
|
-
__privateListenTo as
|
|
956
|
-
blockCommand as
|
|
1120
|
+
__privateListenTo as listenTo2,
|
|
1121
|
+
blockCommand as blockCommand3,
|
|
957
1122
|
commandStartEvent as commandStartEvent2
|
|
958
1123
|
} from "@elementor/editor-v1-adapters";
|
|
959
1124
|
|
|
@@ -961,7 +1126,7 @@ import {
|
|
|
961
1126
|
import { createElementStyle as createElementStyle2, deleteElementStyle as deleteElementStyle2, getElementStyles as getElementStyles2 } from "@elementor/editor-elements";
|
|
962
1127
|
import { LOCAL_STYLES_RESERVED_LABEL as LOCAL_STYLES_RESERVED_LABEL2 } from "@elementor/editor-styles-repository";
|
|
963
1128
|
import { undoable as undoable2 } from "@elementor/editor-v1-adapters";
|
|
964
|
-
import { __ as
|
|
1129
|
+
import { __ as __4 } from "@wordpress/i18n";
|
|
965
1130
|
var undoableResetElementStyle = () => undoable2(
|
|
966
1131
|
{
|
|
967
1132
|
do: ({ containers }) => {
|
|
@@ -999,18 +1164,18 @@ var undoableResetElementStyle = () => undoable2(
|
|
|
999
1164
|
},
|
|
1000
1165
|
{
|
|
1001
1166
|
title: ({ containers }) => getTitleForContainers(containers),
|
|
1002
|
-
subtitle:
|
|
1167
|
+
subtitle: __4("Style Reset", "elementor")
|
|
1003
1168
|
}
|
|
1004
1169
|
);
|
|
1005
1170
|
|
|
1006
1171
|
// src/style-commands/reset-style.ts
|
|
1007
1172
|
function initResetStyleCommand() {
|
|
1008
1173
|
const resetElementStyles = undoableResetElementStyle();
|
|
1009
|
-
|
|
1174
|
+
blockCommand3({
|
|
1010
1175
|
command: "document/elements/reset-style",
|
|
1011
1176
|
condition: hasAtomicWidgets
|
|
1012
1177
|
});
|
|
1013
|
-
|
|
1178
|
+
listenTo2(
|
|
1014
1179
|
commandStartEvent2("document/elements/reset-style"),
|
|
1015
1180
|
(e) => resetStyles(e.args, resetElementStyles)
|
|
1016
1181
|
);
|
|
@@ -1033,19 +1198,24 @@ function initStyleCommands() {
|
|
|
1033
1198
|
// src/init.tsx
|
|
1034
1199
|
function init() {
|
|
1035
1200
|
initStyleTransformers();
|
|
1036
|
-
initStylesRenderer();
|
|
1037
1201
|
initStyleCommands();
|
|
1202
|
+
initLinkInLinkPrevention();
|
|
1038
1203
|
initLegacyViews();
|
|
1039
1204
|
initSettingsTransformers();
|
|
1040
1205
|
injectIntoTop({
|
|
1041
1206
|
id: "elements-overlays",
|
|
1042
1207
|
component: ElementsOverlays
|
|
1043
1208
|
});
|
|
1209
|
+
injectIntoTop({
|
|
1210
|
+
id: "canvas-style-render",
|
|
1211
|
+
component: StyleRenderer
|
|
1212
|
+
});
|
|
1044
1213
|
}
|
|
1045
1214
|
|
|
1046
1215
|
// src/index.ts
|
|
1047
1216
|
init();
|
|
1048
1217
|
export {
|
|
1218
|
+
createTransformer,
|
|
1049
1219
|
settingsTransformersRegistry,
|
|
1050
1220
|
styleTransformersRegistry
|
|
1051
1221
|
};
|