@elementor/editor-canvas 3.33.0-220 → 3.33.0-222
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.js +65 -13
- package/dist/index.mjs +68 -13
- package/package.json +13 -13
- package/src/components/__tests__/style-renderer.test.tsx +2 -2
- package/src/components/element-overlay.tsx +4 -1
- package/src/hooks/__tests__/use-has-overlapping.test.ts +187 -0
- package/src/hooks/use-floating-on-element.ts +11 -8
- package/src/hooks/use-has-overlapping.ts +21 -0
- package/src/hooks/use-style-items.ts +34 -7
- package/src/renderers/__tests__/__snapshots__/create-styles-renderer.test.ts.snap +2 -0
- package/src/renderers/__tests__/create-styles-renderer.test.ts +25 -0
- package/src/renderers/create-styles-renderer.ts +19 -3
- package/src/renderers/errors.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -137,6 +137,7 @@ var import_react3 = require("react");
|
|
|
137
137
|
var import_react4 = require("@floating-ui/react");
|
|
138
138
|
function useFloatingOnElement({ element, isSelected }) {
|
|
139
139
|
const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
|
|
140
|
+
const sizeModifier = 2;
|
|
140
141
|
const { refs, floatingStyles, context } = (0, import_react4.useFloating)({
|
|
141
142
|
// Must be controlled for interactions (like hover) to work.
|
|
142
143
|
open: isOpen || isSelected,
|
|
@@ -144,13 +145,15 @@ function useFloatingOnElement({ element, isSelected }) {
|
|
|
144
145
|
whileElementsMounted: import_react4.autoUpdate,
|
|
145
146
|
middleware: [
|
|
146
147
|
// Match the floating element's size to the reference element.
|
|
147
|
-
(0, import_react4.size)({
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
(0, import_react4.size)(() => {
|
|
149
|
+
return {
|
|
150
|
+
apply({ elements, rects }) {
|
|
151
|
+
Object.assign(elements.floating.style, {
|
|
152
|
+
width: `${rects.reference.width + sizeModifier}px`,
|
|
153
|
+
height: `${rects.reference.height + sizeModifier}px`
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
};
|
|
154
157
|
}),
|
|
155
158
|
// Center the floating element on the reference element.
|
|
156
159
|
(0, import_react4.offset)(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
|
|
@@ -170,6 +173,23 @@ function useFloatingOnElement({ element, isSelected }) {
|
|
|
170
173
|
};
|
|
171
174
|
}
|
|
172
175
|
|
|
176
|
+
// src/hooks/use-has-overlapping.ts
|
|
177
|
+
var possibleOverlappingSelectors = [".e-off-canvas"];
|
|
178
|
+
var useHasOverlapping = () => {
|
|
179
|
+
const preview = window.elementor?.$preview?.[0];
|
|
180
|
+
if (!preview) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
const hasOverlapping = possibleOverlappingSelectors.map((selector) => Array.from(preview?.contentWindow?.document.body.querySelectorAll(selector) ?? [])).flat().some(
|
|
184
|
+
(elem) => elem.checkVisibility({
|
|
185
|
+
opacityProperty: true,
|
|
186
|
+
visibilityProperty: true,
|
|
187
|
+
contentVisibilityAuto: true
|
|
188
|
+
})
|
|
189
|
+
);
|
|
190
|
+
return hasOverlapping;
|
|
191
|
+
};
|
|
192
|
+
|
|
173
193
|
// src/components/element-overlay.tsx
|
|
174
194
|
var CANVAS_WRAPPER_ID = "elementor-preview-responsive-wrapper";
|
|
175
195
|
var OverlayBox = (0, import_ui.styled)(import_ui.Box, {
|
|
@@ -182,9 +202,10 @@ var OverlayBox = (0, import_ui.styled)(import_ui.Box, {
|
|
|
182
202
|
function ElementOverlay({ element, isSelected, id }) {
|
|
183
203
|
const { context, floating, isVisible } = useFloatingOnElement({ element, isSelected });
|
|
184
204
|
const { getFloatingProps, getReferenceProps } = (0, import_react5.useInteractions)([(0, import_react5.useHover)(context)]);
|
|
205
|
+
const hasOverlapping = useHasOverlapping();
|
|
185
206
|
useBindReactPropsToElement(element, getReferenceProps);
|
|
186
207
|
const isSmallerOffset = element.offsetHeight <= 1;
|
|
187
|
-
return isVisible && /* @__PURE__ */ React.createElement(import_react5.FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
|
|
208
|
+
return isVisible && !hasOverlapping && /* @__PURE__ */ React.createElement(import_react5.FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
|
|
188
209
|
OverlayBox,
|
|
189
210
|
{
|
|
190
211
|
ref: floating.setRef,
|
|
@@ -281,6 +302,7 @@ function getLinkAttrs(el) {
|
|
|
281
302
|
// src/hooks/use-style-items.ts
|
|
282
303
|
var import_react9 = require("react");
|
|
283
304
|
var import_editor_responsive2 = require("@elementor/editor-responsive");
|
|
305
|
+
var import_editor_styles3 = require("@elementor/editor-styles");
|
|
284
306
|
var import_editor_styles_repository2 = require("@elementor/editor-styles-repository");
|
|
285
307
|
var import_editor_v1_adapters3 = require("@elementor/editor-v1-adapters");
|
|
286
308
|
|
|
@@ -469,6 +491,7 @@ var import_react8 = require("react");
|
|
|
469
491
|
var import_editor_responsive = require("@elementor/editor-responsive");
|
|
470
492
|
|
|
471
493
|
// src/renderers/create-styles-renderer.ts
|
|
494
|
+
var import_editor_styles2 = require("@elementor/editor-styles");
|
|
472
495
|
var import_utils3 = require("@elementor/utils");
|
|
473
496
|
|
|
474
497
|
// src/renderers/errors.ts
|
|
@@ -477,6 +500,10 @@ var UnknownStyleTypeError = (0, import_utils2.createError)({
|
|
|
477
500
|
code: "unknown_style_type",
|
|
478
501
|
message: "Unknown style type"
|
|
479
502
|
});
|
|
503
|
+
var UnknownStyleStateError = (0, import_utils2.createError)({
|
|
504
|
+
code: "unknown_style_state",
|
|
505
|
+
message: "Unknown style state"
|
|
506
|
+
});
|
|
480
507
|
|
|
481
508
|
// src/renderers/create-styles-renderer.ts
|
|
482
509
|
var SELECTORS_MAP = {
|
|
@@ -494,7 +521,8 @@ function createStylesRenderer({ resolve, breakpoints, selectorPrefix = "" }) {
|
|
|
494
521
|
return {
|
|
495
522
|
id: style.id,
|
|
496
523
|
breakpoint: style?.variants[0]?.meta?.breakpoint || "desktop",
|
|
497
|
-
value: variantsCss.join("")
|
|
524
|
+
value: variantsCss.join(""),
|
|
525
|
+
state: style?.variants[0]?.meta?.state || null
|
|
498
526
|
};
|
|
499
527
|
});
|
|
500
528
|
return await Promise.all(stylesCssPromises);
|
|
@@ -510,7 +538,18 @@ function createStyleWrapper(value = "", wrapper) {
|
|
|
510
538
|
return createStyleWrapper(`${value}${symbol}${cssName}`, wrapper);
|
|
511
539
|
},
|
|
512
540
|
withPrefix: (prefix) => createStyleWrapper([prefix, value].filter(Boolean).join(" "), wrapper),
|
|
513
|
-
withState: (state) =>
|
|
541
|
+
withState: (state) => {
|
|
542
|
+
if (!state) {
|
|
543
|
+
return createStyleWrapper(value, wrapper);
|
|
544
|
+
}
|
|
545
|
+
if ((0, import_editor_styles2.isClassState)(state)) {
|
|
546
|
+
return createStyleWrapper(`${value}.${state}`, wrapper);
|
|
547
|
+
}
|
|
548
|
+
if ((0, import_editor_styles2.isPseudoState)(state)) {
|
|
549
|
+
return createStyleWrapper(`${value}:${state}`, wrapper);
|
|
550
|
+
}
|
|
551
|
+
throw new UnknownStyleStateError({ context: { state } });
|
|
552
|
+
},
|
|
514
553
|
withMediaQuery: (breakpoint) => {
|
|
515
554
|
if (!breakpoint?.type) {
|
|
516
555
|
return createStyleWrapper(value, wrapper);
|
|
@@ -591,14 +630,27 @@ function useStyleItems() {
|
|
|
591
630
|
});
|
|
592
631
|
const breakpointsOrder = (0, import_editor_responsive2.getBreakpoints)().map((breakpoint) => breakpoint.id);
|
|
593
632
|
return (0, import_react9.useMemo)(
|
|
594
|
-
() => Object.values(styleItems).sort(
|
|
595
|
-
return breakpointsOrder.indexOf(breakpointA) - breakpointsOrder.indexOf(breakpointB);
|
|
596
|
-
}),
|
|
633
|
+
() => Object.values(styleItems).sort(sortByProviderPriority).flatMap(({ items }) => items).sort(sortByStateType).sort(sortByBreakpoint(breakpointsOrder)),
|
|
597
634
|
// eslint-disable-next-line
|
|
598
635
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
599
636
|
[styleItems, breakpointsOrder.join("-")]
|
|
600
637
|
);
|
|
601
638
|
}
|
|
639
|
+
function sortByProviderPriority({ provider: providerA }, { provider: providerB }) {
|
|
640
|
+
return providerA.priority - providerB.priority;
|
|
641
|
+
}
|
|
642
|
+
function sortByBreakpoint(breakpointsOrder) {
|
|
643
|
+
return ({ breakpoint: breakpointA }, { breakpoint: breakpointB }) => breakpointsOrder.indexOf(breakpointA) - breakpointsOrder.indexOf(breakpointB);
|
|
644
|
+
}
|
|
645
|
+
function sortByStateType({ state: stateA }, { state: stateB }) {
|
|
646
|
+
if ((0, import_editor_styles3.isClassState)(stateA) && !(0, import_editor_styles3.isClassState)(stateB)) {
|
|
647
|
+
return -1;
|
|
648
|
+
}
|
|
649
|
+
if (!(0, import_editor_styles3.isClassState)(stateA) && (0, import_editor_styles3.isClassState)(stateB)) {
|
|
650
|
+
return 1;
|
|
651
|
+
}
|
|
652
|
+
return 0;
|
|
653
|
+
}
|
|
602
654
|
function createProviderSubscriber({ provider, renderStyles, setStyleItems }) {
|
|
603
655
|
return abortPreviousRuns(
|
|
604
656
|
(abortController) => signalizedProcess(abortController.signal).then((_, signal) => {
|
package/dist/index.mjs
CHANGED
|
@@ -97,6 +97,7 @@ import { useEffect as useEffect3, useState } from "react";
|
|
|
97
97
|
import { autoUpdate, offset, size, useFloating } from "@floating-ui/react";
|
|
98
98
|
function useFloatingOnElement({ element, isSelected }) {
|
|
99
99
|
const [isOpen, setIsOpen] = useState(false);
|
|
100
|
+
const sizeModifier = 2;
|
|
100
101
|
const { refs, floatingStyles, context } = useFloating({
|
|
101
102
|
// Must be controlled for interactions (like hover) to work.
|
|
102
103
|
open: isOpen || isSelected,
|
|
@@ -104,13 +105,15 @@ function useFloatingOnElement({ element, isSelected }) {
|
|
|
104
105
|
whileElementsMounted: autoUpdate,
|
|
105
106
|
middleware: [
|
|
106
107
|
// Match the floating element's size to the reference element.
|
|
107
|
-
size({
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
size(() => {
|
|
109
|
+
return {
|
|
110
|
+
apply({ elements, rects }) {
|
|
111
|
+
Object.assign(elements.floating.style, {
|
|
112
|
+
width: `${rects.reference.width + sizeModifier}px`,
|
|
113
|
+
height: `${rects.reference.height + sizeModifier}px`
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
};
|
|
114
117
|
}),
|
|
115
118
|
// Center the floating element on the reference element.
|
|
116
119
|
offset(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
|
|
@@ -130,6 +133,23 @@ function useFloatingOnElement({ element, isSelected }) {
|
|
|
130
133
|
};
|
|
131
134
|
}
|
|
132
135
|
|
|
136
|
+
// src/hooks/use-has-overlapping.ts
|
|
137
|
+
var possibleOverlappingSelectors = [".e-off-canvas"];
|
|
138
|
+
var useHasOverlapping = () => {
|
|
139
|
+
const preview = window.elementor?.$preview?.[0];
|
|
140
|
+
if (!preview) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const hasOverlapping = possibleOverlappingSelectors.map((selector) => Array.from(preview?.contentWindow?.document.body.querySelectorAll(selector) ?? [])).flat().some(
|
|
144
|
+
(elem) => elem.checkVisibility({
|
|
145
|
+
opacityProperty: true,
|
|
146
|
+
visibilityProperty: true,
|
|
147
|
+
contentVisibilityAuto: true
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
return hasOverlapping;
|
|
151
|
+
};
|
|
152
|
+
|
|
133
153
|
// src/components/element-overlay.tsx
|
|
134
154
|
var CANVAS_WRAPPER_ID = "elementor-preview-responsive-wrapper";
|
|
135
155
|
var OverlayBox = styled(Box, {
|
|
@@ -142,9 +162,10 @@ var OverlayBox = styled(Box, {
|
|
|
142
162
|
function ElementOverlay({ element, isSelected, id }) {
|
|
143
163
|
const { context, floating, isVisible } = useFloatingOnElement({ element, isSelected });
|
|
144
164
|
const { getFloatingProps, getReferenceProps } = useInteractions([useHover(context)]);
|
|
165
|
+
const hasOverlapping = useHasOverlapping();
|
|
145
166
|
useBindReactPropsToElement(element, getReferenceProps);
|
|
146
167
|
const isSmallerOffset = element.offsetHeight <= 1;
|
|
147
|
-
return isVisible && /* @__PURE__ */ React.createElement(FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
|
|
168
|
+
return isVisible && !hasOverlapping && /* @__PURE__ */ React.createElement(FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
|
|
148
169
|
OverlayBox,
|
|
149
170
|
{
|
|
150
171
|
ref: floating.setRef,
|
|
@@ -241,6 +262,7 @@ function getLinkAttrs(el) {
|
|
|
241
262
|
// src/hooks/use-style-items.ts
|
|
242
263
|
import { useEffect as useEffect5, useMemo as useMemo3, useState as useState2 } from "react";
|
|
243
264
|
import { getBreakpoints } from "@elementor/editor-responsive";
|
|
265
|
+
import { isClassState as isClassState2 } from "@elementor/editor-styles";
|
|
244
266
|
import { stylesRepository as stylesRepository2 } from "@elementor/editor-styles-repository";
|
|
245
267
|
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
246
268
|
|
|
@@ -431,6 +453,10 @@ import { useMemo as useMemo2 } from "react";
|
|
|
431
453
|
import { useBreakpointsMap } from "@elementor/editor-responsive";
|
|
432
454
|
|
|
433
455
|
// src/renderers/create-styles-renderer.ts
|
|
456
|
+
import {
|
|
457
|
+
isClassState,
|
|
458
|
+
isPseudoState
|
|
459
|
+
} from "@elementor/editor-styles";
|
|
434
460
|
import { decodeString } from "@elementor/utils";
|
|
435
461
|
|
|
436
462
|
// src/renderers/errors.ts
|
|
@@ -439,6 +465,10 @@ var UnknownStyleTypeError = createError({
|
|
|
439
465
|
code: "unknown_style_type",
|
|
440
466
|
message: "Unknown style type"
|
|
441
467
|
});
|
|
468
|
+
var UnknownStyleStateError = createError({
|
|
469
|
+
code: "unknown_style_state",
|
|
470
|
+
message: "Unknown style state"
|
|
471
|
+
});
|
|
442
472
|
|
|
443
473
|
// src/renderers/create-styles-renderer.ts
|
|
444
474
|
var SELECTORS_MAP = {
|
|
@@ -456,7 +486,8 @@ function createStylesRenderer({ resolve, breakpoints, selectorPrefix = "" }) {
|
|
|
456
486
|
return {
|
|
457
487
|
id: style.id,
|
|
458
488
|
breakpoint: style?.variants[0]?.meta?.breakpoint || "desktop",
|
|
459
|
-
value: variantsCss.join("")
|
|
489
|
+
value: variantsCss.join(""),
|
|
490
|
+
state: style?.variants[0]?.meta?.state || null
|
|
460
491
|
};
|
|
461
492
|
});
|
|
462
493
|
return await Promise.all(stylesCssPromises);
|
|
@@ -472,7 +503,18 @@ function createStyleWrapper(value = "", wrapper) {
|
|
|
472
503
|
return createStyleWrapper(`${value}${symbol}${cssName}`, wrapper);
|
|
473
504
|
},
|
|
474
505
|
withPrefix: (prefix) => createStyleWrapper([prefix, value].filter(Boolean).join(" "), wrapper),
|
|
475
|
-
withState: (state) =>
|
|
506
|
+
withState: (state) => {
|
|
507
|
+
if (!state) {
|
|
508
|
+
return createStyleWrapper(value, wrapper);
|
|
509
|
+
}
|
|
510
|
+
if (isClassState(state)) {
|
|
511
|
+
return createStyleWrapper(`${value}.${state}`, wrapper);
|
|
512
|
+
}
|
|
513
|
+
if (isPseudoState(state)) {
|
|
514
|
+
return createStyleWrapper(`${value}:${state}`, wrapper);
|
|
515
|
+
}
|
|
516
|
+
throw new UnknownStyleStateError({ context: { state } });
|
|
517
|
+
},
|
|
476
518
|
withMediaQuery: (breakpoint) => {
|
|
477
519
|
if (!breakpoint?.type) {
|
|
478
520
|
return createStyleWrapper(value, wrapper);
|
|
@@ -553,14 +595,27 @@ function useStyleItems() {
|
|
|
553
595
|
});
|
|
554
596
|
const breakpointsOrder = getBreakpoints().map((breakpoint) => breakpoint.id);
|
|
555
597
|
return useMemo3(
|
|
556
|
-
() => Object.values(styleItems).sort(
|
|
557
|
-
return breakpointsOrder.indexOf(breakpointA) - breakpointsOrder.indexOf(breakpointB);
|
|
558
|
-
}),
|
|
598
|
+
() => Object.values(styleItems).sort(sortByProviderPriority).flatMap(({ items }) => items).sort(sortByStateType).sort(sortByBreakpoint(breakpointsOrder)),
|
|
559
599
|
// eslint-disable-next-line
|
|
560
600
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
561
601
|
[styleItems, breakpointsOrder.join("-")]
|
|
562
602
|
);
|
|
563
603
|
}
|
|
604
|
+
function sortByProviderPriority({ provider: providerA }, { provider: providerB }) {
|
|
605
|
+
return providerA.priority - providerB.priority;
|
|
606
|
+
}
|
|
607
|
+
function sortByBreakpoint(breakpointsOrder) {
|
|
608
|
+
return ({ breakpoint: breakpointA }, { breakpoint: breakpointB }) => breakpointsOrder.indexOf(breakpointA) - breakpointsOrder.indexOf(breakpointB);
|
|
609
|
+
}
|
|
610
|
+
function sortByStateType({ state: stateA }, { state: stateB }) {
|
|
611
|
+
if (isClassState2(stateA) && !isClassState2(stateB)) {
|
|
612
|
+
return -1;
|
|
613
|
+
}
|
|
614
|
+
if (!isClassState2(stateA) && isClassState2(stateB)) {
|
|
615
|
+
return 1;
|
|
616
|
+
}
|
|
617
|
+
return 0;
|
|
618
|
+
}
|
|
564
619
|
function createProviderSubscriber({ provider, renderStyles, setStyleItems }) {
|
|
565
620
|
return abortPreviousRuns(
|
|
566
621
|
(abortController) => signalizedProcess(abortController.signal).then((_, signal) => {
|
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.33.0-
|
|
4
|
+
"version": "3.33.0-222",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,19 +37,19 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "3.33.0-
|
|
41
|
-
"@elementor/editor-notifications": "3.33.0-
|
|
42
|
-
"@elementor/editor-documents": "3.33.0-
|
|
43
|
-
"@elementor/editor-elements": "3.33.0-
|
|
44
|
-
"@elementor/editor-props": "3.33.0-
|
|
45
|
-
"@elementor/editor-responsive": "3.33.0-
|
|
46
|
-
"@elementor/editor-styles": "3.33.0-
|
|
47
|
-
"@elementor/editor-styles-repository": "3.33.0-
|
|
48
|
-
"@elementor/editor-v1-adapters": "3.33.0-
|
|
49
|
-
"@elementor/twing": "3.33.0-
|
|
40
|
+
"@elementor/editor": "3.33.0-222",
|
|
41
|
+
"@elementor/editor-notifications": "3.33.0-222",
|
|
42
|
+
"@elementor/editor-documents": "3.33.0-222",
|
|
43
|
+
"@elementor/editor-elements": "3.33.0-222",
|
|
44
|
+
"@elementor/editor-props": "3.33.0-222",
|
|
45
|
+
"@elementor/editor-responsive": "3.33.0-222",
|
|
46
|
+
"@elementor/editor-styles": "3.33.0-222",
|
|
47
|
+
"@elementor/editor-styles-repository": "3.33.0-222",
|
|
48
|
+
"@elementor/editor-v1-adapters": "3.33.0-222",
|
|
49
|
+
"@elementor/twing": "3.33.0-222",
|
|
50
50
|
"@elementor/ui": "1.36.12",
|
|
51
|
-
"@elementor/utils": "3.33.0-
|
|
52
|
-
"@elementor/wp-media": "3.33.0-
|
|
51
|
+
"@elementor/utils": "3.33.0-222",
|
|
52
|
+
"@elementor/wp-media": "3.33.0-222",
|
|
53
53
|
"@floating-ui/react": "^0.27.5",
|
|
54
54
|
"@wordpress/i18n": "^5.13.0"
|
|
55
55
|
},
|
|
@@ -46,8 +46,8 @@ describe( '<StyleRenderer />', () => {
|
|
|
46
46
|
const mockContainer = document.createElement( 'div' );
|
|
47
47
|
|
|
48
48
|
const mockCssItems = [
|
|
49
|
-
{ id: 'style1', value: '.test { color: red; }', breakpoint: 'desktop' },
|
|
50
|
-
{ id: 'style2', value: '.test2 { color: blue; }', breakpoint: 'desktop' },
|
|
49
|
+
{ id: 'style1', value: '.test { color: red; }', breakpoint: 'desktop', state: null },
|
|
50
|
+
{ id: 'style2', value: '.test2 { color: blue; }', breakpoint: 'desktop', state: null },
|
|
51
51
|
];
|
|
52
52
|
|
|
53
53
|
const mockLinkAttrs = [
|
|
@@ -4,6 +4,7 @@ import { FloatingPortal, useHover, useInteractions } from '@floating-ui/react';
|
|
|
4
4
|
|
|
5
5
|
import { useBindReactPropsToElement } from '../hooks/use-bind-react-props-to-element';
|
|
6
6
|
import { useFloatingOnElement } from '../hooks/use-floating-on-element';
|
|
7
|
+
import { useHasOverlapping } from '../hooks/use-has-overlapping';
|
|
7
8
|
|
|
8
9
|
export const CANVAS_WRAPPER_ID = 'elementor-preview-responsive-wrapper';
|
|
9
10
|
|
|
@@ -25,12 +26,14 @@ const OverlayBox = styled( Box, {
|
|
|
25
26
|
export function ElementOverlay( { element, isSelected, id }: Props ) {
|
|
26
27
|
const { context, floating, isVisible } = useFloatingOnElement( { element, isSelected } );
|
|
27
28
|
const { getFloatingProps, getReferenceProps } = useInteractions( [ useHover( context ) ] );
|
|
29
|
+
const hasOverlapping = useHasOverlapping();
|
|
28
30
|
|
|
29
31
|
useBindReactPropsToElement( element, getReferenceProps );
|
|
30
32
|
const isSmallerOffset = element.offsetHeight <= 1;
|
|
31
33
|
|
|
32
34
|
return (
|
|
33
|
-
isVisible &&
|
|
35
|
+
isVisible &&
|
|
36
|
+
! hasOverlapping && (
|
|
34
37
|
<FloatingPortal id={ CANVAS_WRAPPER_ID }>
|
|
35
38
|
<OverlayBox
|
|
36
39
|
ref={ floating.setRef }
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { createDOMElement } from 'test-utils';
|
|
2
|
+
import { renderHook } from '@testing-library/react';
|
|
3
|
+
|
|
4
|
+
import { type CanvasExtendedWindow } from '../../sync/types';
|
|
5
|
+
import { useHasOverlapping } from '../use-has-overlapping';
|
|
6
|
+
|
|
7
|
+
const OFF_CANVAS_CLASS = 'e-off-canvas';
|
|
8
|
+
|
|
9
|
+
describe( 'useHasOverlapping', () => {
|
|
10
|
+
let mockPreviewFrame: HTMLIFrameElement;
|
|
11
|
+
let mockDocument: Document;
|
|
12
|
+
|
|
13
|
+
const setupPreviewFrame = ( hasOffCanvas: boolean, isVisible: boolean = true ) => {
|
|
14
|
+
// Arrange - Create mock iframe and document
|
|
15
|
+
mockPreviewFrame = createDOMElement( { tag: 'iframe' } ) as HTMLIFrameElement;
|
|
16
|
+
mockDocument = document.implementation.createHTMLDocument( 'Preview' );
|
|
17
|
+
|
|
18
|
+
if ( hasOffCanvas ) {
|
|
19
|
+
const offCanvasElement = createDOMElement( {
|
|
20
|
+
tag: 'div',
|
|
21
|
+
attrs: { class: OFF_CANVAS_CLASS },
|
|
22
|
+
} );
|
|
23
|
+
|
|
24
|
+
// Mock checkVisibility method
|
|
25
|
+
offCanvasElement.checkVisibility = jest.fn().mockReturnValue( isVisible );
|
|
26
|
+
|
|
27
|
+
mockDocument.body.appendChild( offCanvasElement );
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Setup the content window with the mock document
|
|
31
|
+
Object.defineProperty( mockPreviewFrame, 'contentWindow', {
|
|
32
|
+
value: {
|
|
33
|
+
document: mockDocument,
|
|
34
|
+
},
|
|
35
|
+
writable: true,
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
// Setup window.elementor.$preview
|
|
39
|
+
( window as unknown as CanvasExtendedWindow ).elementor = {
|
|
40
|
+
$preview: [ mockPreviewFrame ],
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const cleanupPreviewFrame = () => {
|
|
45
|
+
delete ( window as unknown as CanvasExtendedWindow ).elementor;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
afterEach( () => {
|
|
49
|
+
cleanupPreviewFrame();
|
|
50
|
+
} );
|
|
51
|
+
|
|
52
|
+
it( 'should return false when preview frame is not available', () => {
|
|
53
|
+
// Arrange - No preview frame setup
|
|
54
|
+
|
|
55
|
+
// Act
|
|
56
|
+
const { result } = renderHook( () => useHasOverlapping() );
|
|
57
|
+
|
|
58
|
+
// Assert
|
|
59
|
+
expect( result.current ).toBe( false );
|
|
60
|
+
} );
|
|
61
|
+
|
|
62
|
+
it( 'should return false when off-canvas element does not exist', () => {
|
|
63
|
+
// Arrange
|
|
64
|
+
setupPreviewFrame( false );
|
|
65
|
+
|
|
66
|
+
// Act
|
|
67
|
+
const { result } = renderHook( () => useHasOverlapping() );
|
|
68
|
+
|
|
69
|
+
// Assert
|
|
70
|
+
expect( result.current ).toBe( false );
|
|
71
|
+
} );
|
|
72
|
+
|
|
73
|
+
it( 'should return true when off-canvas element exists and is visible', () => {
|
|
74
|
+
// Arrange
|
|
75
|
+
setupPreviewFrame( true, true );
|
|
76
|
+
|
|
77
|
+
// Act
|
|
78
|
+
const { result } = renderHook( () => useHasOverlapping() );
|
|
79
|
+
|
|
80
|
+
// Assert
|
|
81
|
+
expect( result.current ).toBe( true );
|
|
82
|
+
} );
|
|
83
|
+
|
|
84
|
+
it( 'should return false when off-canvas element exists but is not visible', () => {
|
|
85
|
+
// Arrange
|
|
86
|
+
setupPreviewFrame( true, false );
|
|
87
|
+
|
|
88
|
+
// Act
|
|
89
|
+
const { result } = renderHook( () => useHasOverlapping() );
|
|
90
|
+
|
|
91
|
+
// Assert
|
|
92
|
+
expect( result.current ).toBe( false );
|
|
93
|
+
} );
|
|
94
|
+
|
|
95
|
+
it( 'should check visibility with correct options', () => {
|
|
96
|
+
// Arrange
|
|
97
|
+
setupPreviewFrame( true, true );
|
|
98
|
+
|
|
99
|
+
// Act
|
|
100
|
+
renderHook( () => useHasOverlapping() );
|
|
101
|
+
|
|
102
|
+
// Assert
|
|
103
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
104
|
+
const offCanvasElement = mockDocument.querySelector( `.${ OFF_CANVAS_CLASS }` );
|
|
105
|
+
expect( offCanvasElement?.checkVisibility ).toHaveBeenCalledWith( {
|
|
106
|
+
opacityProperty: true,
|
|
107
|
+
visibilityProperty: true,
|
|
108
|
+
contentVisibilityAuto: true,
|
|
109
|
+
} );
|
|
110
|
+
} );
|
|
111
|
+
|
|
112
|
+
it( 'should return true when multiple off-canvas elements exist and at least one is visible', () => {
|
|
113
|
+
// Arrange
|
|
114
|
+
mockPreviewFrame = createDOMElement( { tag: 'iframe' } ) as HTMLIFrameElement;
|
|
115
|
+
mockDocument = document.implementation.createHTMLDocument( 'Preview' );
|
|
116
|
+
|
|
117
|
+
const offCanvasElement1 = createDOMElement( {
|
|
118
|
+
tag: 'div',
|
|
119
|
+
attrs: { class: OFF_CANVAS_CLASS },
|
|
120
|
+
} );
|
|
121
|
+
offCanvasElement1.checkVisibility = jest.fn().mockReturnValue( false );
|
|
122
|
+
|
|
123
|
+
const offCanvasElement2 = createDOMElement( {
|
|
124
|
+
tag: 'div',
|
|
125
|
+
attrs: { class: OFF_CANVAS_CLASS },
|
|
126
|
+
} );
|
|
127
|
+
offCanvasElement2.checkVisibility = jest.fn().mockReturnValue( true );
|
|
128
|
+
|
|
129
|
+
mockDocument.body.appendChild( offCanvasElement1 );
|
|
130
|
+
mockDocument.body.appendChild( offCanvasElement2 );
|
|
131
|
+
|
|
132
|
+
Object.defineProperty( mockPreviewFrame, 'contentWindow', {
|
|
133
|
+
value: {
|
|
134
|
+
document: mockDocument,
|
|
135
|
+
},
|
|
136
|
+
writable: true,
|
|
137
|
+
} );
|
|
138
|
+
|
|
139
|
+
( window as unknown as CanvasExtendedWindow ).elementor = {
|
|
140
|
+
$preview: [ mockPreviewFrame ],
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// Act
|
|
144
|
+
const { result } = renderHook( () => useHasOverlapping() );
|
|
145
|
+
|
|
146
|
+
// Assert
|
|
147
|
+
expect( result.current ).toBe( true );
|
|
148
|
+
} );
|
|
149
|
+
|
|
150
|
+
it( 'should return false when multiple off-canvas elements exist but none are visible', () => {
|
|
151
|
+
// Arrange
|
|
152
|
+
mockPreviewFrame = createDOMElement( { tag: 'iframe' } ) as HTMLIFrameElement;
|
|
153
|
+
mockDocument = document.implementation.createHTMLDocument( 'Preview' );
|
|
154
|
+
|
|
155
|
+
const offCanvasElement1 = createDOMElement( {
|
|
156
|
+
tag: 'div',
|
|
157
|
+
attrs: { class: OFF_CANVAS_CLASS },
|
|
158
|
+
} );
|
|
159
|
+
offCanvasElement1.checkVisibility = jest.fn().mockReturnValue( false );
|
|
160
|
+
|
|
161
|
+
const offCanvasElement2 = createDOMElement( {
|
|
162
|
+
tag: 'div',
|
|
163
|
+
attrs: { class: OFF_CANVAS_CLASS },
|
|
164
|
+
} );
|
|
165
|
+
offCanvasElement2.checkVisibility = jest.fn().mockReturnValue( false );
|
|
166
|
+
|
|
167
|
+
mockDocument.body.appendChild( offCanvasElement1 );
|
|
168
|
+
mockDocument.body.appendChild( offCanvasElement2 );
|
|
169
|
+
|
|
170
|
+
Object.defineProperty( mockPreviewFrame, 'contentWindow', {
|
|
171
|
+
value: {
|
|
172
|
+
document: mockDocument,
|
|
173
|
+
},
|
|
174
|
+
writable: true,
|
|
175
|
+
} );
|
|
176
|
+
|
|
177
|
+
( window as unknown as CanvasExtendedWindow ).elementor = {
|
|
178
|
+
$preview: [ mockPreviewFrame ],
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Act
|
|
182
|
+
const { result } = renderHook( () => useHasOverlapping() );
|
|
183
|
+
|
|
184
|
+
// Assert
|
|
185
|
+
expect( result.current ).toBe( false );
|
|
186
|
+
} );
|
|
187
|
+
} );
|
|
@@ -8,6 +8,7 @@ type Options = {
|
|
|
8
8
|
|
|
9
9
|
export function useFloatingOnElement( { element, isSelected }: Options ) {
|
|
10
10
|
const [ isOpen, setIsOpen ] = useState( false );
|
|
11
|
+
const sizeModifier = 2;
|
|
11
12
|
|
|
12
13
|
const { refs, floatingStyles, context } = useFloating( {
|
|
13
14
|
// Must be controlled for interactions (like hover) to work.
|
|
@@ -18,15 +19,17 @@ export function useFloatingOnElement( { element, isSelected }: Options ) {
|
|
|
18
19
|
|
|
19
20
|
middleware: [
|
|
20
21
|
// Match the floating element's size to the reference element.
|
|
21
|
-
size( {
|
|
22
|
-
apply( { elements, rects } ) {
|
|
23
|
-
Object.assign( elements.floating.style, {
|
|
24
|
-
width: `${ rects.reference.width + 2 }px`,
|
|
25
|
-
height: `${ rects.reference.height + 2 }px`,
|
|
26
|
-
} );
|
|
27
|
-
},
|
|
28
|
-
} ),
|
|
29
22
|
|
|
23
|
+
size( () => {
|
|
24
|
+
return {
|
|
25
|
+
apply( { elements, rects } ) {
|
|
26
|
+
Object.assign( elements.floating.style, {
|
|
27
|
+
width: `${ rects.reference.width + sizeModifier }px`,
|
|
28
|
+
height: `${ rects.reference.height + sizeModifier }px`,
|
|
29
|
+
} );
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
} ),
|
|
30
33
|
// Center the floating element on the reference element.
|
|
31
34
|
offset( ( { rects } ) => -rects.reference.height / 2 - rects.floating.height / 2 ),
|
|
32
35
|
],
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type CanvasExtendedWindow } from '../sync/types';
|
|
2
|
+
|
|
3
|
+
const possibleOverlappingSelectors = [ '.e-off-canvas' ]; // can add more selectors here if needed, make sure to loop through them to check classList
|
|
4
|
+
|
|
5
|
+
export const useHasOverlapping = () => {
|
|
6
|
+
const preview = ( window as unknown as CanvasExtendedWindow ).elementor?.$preview?.[ 0 ];
|
|
7
|
+
if ( ! preview ) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const hasOverlapping = possibleOverlappingSelectors
|
|
11
|
+
.map( ( selector ) => Array.from( preview?.contentWindow?.document.body.querySelectorAll( selector ) ?? [] ) )
|
|
12
|
+
.flat()
|
|
13
|
+
.some( ( elem ) =>
|
|
14
|
+
elem.checkVisibility( {
|
|
15
|
+
opacityProperty: true,
|
|
16
|
+
visibilityProperty: true,
|
|
17
|
+
contentVisibilityAuto: true,
|
|
18
|
+
} )
|
|
19
|
+
);
|
|
20
|
+
return hasOverlapping;
|
|
21
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Dispatch, type SetStateAction, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { type BreakpointId, getBreakpoints } from '@elementor/editor-responsive';
|
|
3
|
+
import { isClassState, type StyleDefinitionClassState } from '@elementor/editor-styles';
|
|
3
4
|
import { type StylesProvider, stylesRepository } from '@elementor/editor-styles-repository';
|
|
4
5
|
import { registerDataHook } from '@elementor/editor-v1-adapters';
|
|
5
6
|
|
|
@@ -58,19 +59,45 @@ export function useStyleItems() {
|
|
|
58
59
|
return useMemo(
|
|
59
60
|
() =>
|
|
60
61
|
Object.values( styleItems )
|
|
61
|
-
.sort(
|
|
62
|
+
.sort( sortByProviderPriority )
|
|
62
63
|
.flatMap( ( { items } ) => items )
|
|
63
|
-
.sort(
|
|
64
|
-
|
|
65
|
-
breakpointsOrder.indexOf( breakpointA as BreakpointId ) -
|
|
66
|
-
breakpointsOrder.indexOf( breakpointB as BreakpointId )
|
|
67
|
-
);
|
|
68
|
-
} ),
|
|
64
|
+
.sort( sortByStateType )
|
|
65
|
+
.sort( sortByBreakpoint( breakpointsOrder ) ),
|
|
69
66
|
// eslint-disable-next-line
|
|
70
67
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
71
68
|
[ styleItems, breakpointsOrder.join( '-' ) ]
|
|
72
69
|
);
|
|
73
70
|
}
|
|
71
|
+
function sortByProviderPriority(
|
|
72
|
+
{ provider: providerA }: ProviderAndStyleItems,
|
|
73
|
+
{ provider: providerB }: ProviderAndStyleItems
|
|
74
|
+
) {
|
|
75
|
+
return providerA.priority - providerB.priority;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function sortByBreakpoint( breakpointsOrder: BreakpointId[] ) {
|
|
79
|
+
return ( { breakpoint: breakpointA }: StyleItem, { breakpoint: breakpointB }: StyleItem ) =>
|
|
80
|
+
breakpointsOrder.indexOf( breakpointA as BreakpointId ) -
|
|
81
|
+
breakpointsOrder.indexOf( breakpointB as BreakpointId );
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function sortByStateType( { state: stateA }: StyleItem, { state: stateB }: StyleItem ) {
|
|
85
|
+
if (
|
|
86
|
+
isClassState( stateA as StyleDefinitionClassState ) &&
|
|
87
|
+
! isClassState( stateB as StyleDefinitionClassState )
|
|
88
|
+
) {
|
|
89
|
+
return -1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (
|
|
93
|
+
! isClassState( stateA as StyleDefinitionClassState ) &&
|
|
94
|
+
isClassState( stateB as StyleDefinitionClassState )
|
|
95
|
+
) {
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
74
101
|
|
|
75
102
|
type CreateProviderSubscriberArgs = {
|
|
76
103
|
provider: StylesProvider;
|
|
@@ -5,11 +5,13 @@ exports[`renderStyles should render styles 1`] = `
|
|
|
5
5
|
{
|
|
6
6
|
"breakpoint": "desktop",
|
|
7
7
|
"id": "test",
|
|
8
|
+
"state": null,
|
|
8
9
|
"value": ".test{font-size:10px;}.test:hover{font-size:20px;}@media(max-width:992px){.test{font-size:30px;}}@media(max-width:768px){.test:focus{font-size:40px;}}",
|
|
9
10
|
},
|
|
10
11
|
{
|
|
11
12
|
"breakpoint": "desktop",
|
|
12
13
|
"id": "test-2",
|
|
14
|
+
"state": null,
|
|
13
15
|
"value": ".custom-name{font-size:50px;}",
|
|
14
16
|
},
|
|
15
17
|
]
|
|
@@ -112,6 +112,7 @@ describe( 'renderStyles', () => {
|
|
|
112
112
|
breakpoint: 'desktop',
|
|
113
113
|
id: 'test',
|
|
114
114
|
value: '.elementor-prefix .test{font-size:24px;}',
|
|
115
|
+
state: null,
|
|
115
116
|
},
|
|
116
117
|
] );
|
|
117
118
|
} );
|
|
@@ -200,4 +201,28 @@ describe( 'custom_css rendering', () => {
|
|
|
200
201
|
// Assert.
|
|
201
202
|
expect( result[ 0 ].value ).toContain( css );
|
|
202
203
|
} );
|
|
204
|
+
|
|
205
|
+
it( 'should render class state with selector', async () => {
|
|
206
|
+
// Arrange.
|
|
207
|
+
const styleDef: RendererStyleDefinition = {
|
|
208
|
+
id: 'test',
|
|
209
|
+
type: 'class',
|
|
210
|
+
cssName: 'test',
|
|
211
|
+
label: 'Test',
|
|
212
|
+
variants: [
|
|
213
|
+
{
|
|
214
|
+
meta: { breakpoint: null, state: 'e--selected' },
|
|
215
|
+
props: {},
|
|
216
|
+
custom_css: null,
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// Act.
|
|
222
|
+
const renderStyles = createStylesRenderer( { breakpoints: {} as BreakpointsMap, resolve: async () => ( {} ) } );
|
|
223
|
+
const result = await renderStyles( { styles: [ styleDef ] } );
|
|
224
|
+
|
|
225
|
+
// Assert.
|
|
226
|
+
expect( result[ 0 ].value ).toContain( '.test.e--selected{}' );
|
|
227
|
+
} );
|
|
203
228
|
} );
|
|
@@ -2,6 +2,8 @@ import type { Props } from '@elementor/editor-props';
|
|
|
2
2
|
import { type Breakpoint, type BreakpointsMap } from '@elementor/editor-responsive';
|
|
3
3
|
import {
|
|
4
4
|
type CustomCss,
|
|
5
|
+
isClassState,
|
|
6
|
+
isPseudoState,
|
|
5
7
|
type StyleDefinition,
|
|
6
8
|
type StyleDefinitionState,
|
|
7
9
|
type StyleDefinitionType,
|
|
@@ -9,12 +11,13 @@ import {
|
|
|
9
11
|
import { decodeString } from '@elementor/utils';
|
|
10
12
|
|
|
11
13
|
import { type PropsResolver } from './create-props-resolver';
|
|
12
|
-
import { UnknownStyleTypeError } from './errors';
|
|
14
|
+
import { UnknownStyleStateError, UnknownStyleTypeError } from './errors';
|
|
13
15
|
|
|
14
16
|
export type StyleItem = {
|
|
15
17
|
id: string;
|
|
16
18
|
value: string;
|
|
17
19
|
breakpoint: string;
|
|
20
|
+
state: StyleDefinitionState | null;
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
export type StyleRenderer = ReturnType< typeof createStylesRenderer >;
|
|
@@ -65,6 +68,7 @@ export function createStylesRenderer( { resolve, breakpoints, selectorPrefix = '
|
|
|
65
68
|
id: style.id,
|
|
66
69
|
breakpoint: style?.variants[ 0 ]?.meta?.breakpoint || 'desktop',
|
|
67
70
|
value: variantsCss.join( '' ),
|
|
71
|
+
state: style?.variants[ 0 ]?.meta?.state || null,
|
|
68
72
|
};
|
|
69
73
|
} );
|
|
70
74
|
|
|
@@ -87,9 +91,21 @@ function createStyleWrapper( value: string = '', wrapper?: ( css: string ) => st
|
|
|
87
91
|
withPrefix: ( prefix: string ) =>
|
|
88
92
|
createStyleWrapper( [ prefix, value ].filter( Boolean ).join( ' ' ), wrapper ),
|
|
89
93
|
|
|
90
|
-
withState: ( state: StyleDefinitionState ) =>
|
|
91
|
-
|
|
94
|
+
withState: ( state: StyleDefinitionState ) => {
|
|
95
|
+
if ( ! state ) {
|
|
96
|
+
return createStyleWrapper( value, wrapper );
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if ( isClassState( state ) ) {
|
|
100
|
+
return createStyleWrapper( `${ value }.${ state }`, wrapper );
|
|
101
|
+
}
|
|
92
102
|
|
|
103
|
+
if ( isPseudoState( state ) ) {
|
|
104
|
+
return createStyleWrapper( `${ value }:${ state }`, wrapper );
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
throw new UnknownStyleStateError( { context: { state } } );
|
|
108
|
+
},
|
|
93
109
|
withMediaQuery: ( breakpoint: Breakpoint | null ) => {
|
|
94
110
|
if ( ! breakpoint?.type ) {
|
|
95
111
|
return createStyleWrapper( value, wrapper );
|
package/src/renderers/errors.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import { type StyleDefinitionState } from '@elementor/editor-styles';
|
|
1
2
|
import { createError } from '@elementor/utils';
|
|
2
3
|
|
|
3
4
|
export const UnknownStyleTypeError = createError< { type: string } >( {
|
|
4
5
|
code: 'unknown_style_type',
|
|
5
6
|
message: 'Unknown style type',
|
|
6
7
|
} );
|
|
8
|
+
|
|
9
|
+
export const UnknownStyleStateError = createError< { state: StyleDefinitionState } >( {
|
|
10
|
+
code: 'unknown_style_state',
|
|
11
|
+
message: 'Unknown style state',
|
|
12
|
+
} );
|