@elementor/editor-components 4.0.0-666 → 4.0.0-667
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 +191 -3870
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +184 -3904
- package/dist/index.mjs.map +1 -1
- package/package.json +23 -23
- package/src/init.ts +0 -13
- package/src/extended/components/component-introduction.tsx +0 -77
- package/src/extended/components/component-panel-header/component-badge.tsx +0 -73
- package/src/extended/components/component-panel-header/component-panel-header.tsx +0 -98
- package/src/extended/components/component-properties-panel/component-properties-panel-content.tsx +0 -176
- package/src/extended/components/component-properties-panel/component-properties-panel.tsx +0 -43
- package/src/extended/components/component-properties-panel/properties-empty-state.tsx +0 -51
- package/src/extended/components/component-properties-panel/properties-group.tsx +0 -196
- package/src/extended/components/component-properties-panel/property-item.tsx +0 -124
- package/src/extended/components/component-properties-panel/sortable.tsx +0 -92
- package/src/extended/components/component-properties-panel/use-current-editable-item.ts +0 -73
- package/src/extended/components/component-properties-panel/utils/generate-unique-label.ts +0 -21
- package/src/extended/components/component-properties-panel/utils/validate-group-label.ts +0 -24
- package/src/extended/components/components-tab/component-item.tsx +0 -180
- package/src/extended/components/components-tab/components.tsx +0 -58
- package/src/extended/components/components-tab/delete-confirmation-dialog.tsx +0 -26
- package/src/extended/components/create-component-form/create-component-form.tsx +0 -281
- package/src/extended/components/create-component-form/hooks/use-form.ts +0 -72
- package/src/extended/components/create-component-form/utils/get-component-event-data.ts +0 -54
- package/src/extended/components/edit-component/component-modal.tsx +0 -133
- package/src/extended/components/edit-component/edit-component.tsx +0 -166
- package/src/extended/components/edit-component/use-canvas-document.ts +0 -9
- package/src/extended/components/edit-component/use-element-rect.ts +0 -81
- package/src/extended/components/instance-editing-panel/instance-editing-panel.tsx +0 -60
- package/src/extended/components/overridable-props/indicator.tsx +0 -83
- package/src/extended/components/overridable-props/overridable-prop-control.tsx +0 -127
- package/src/extended/components/overridable-props/overridable-prop-form.tsx +0 -135
- package/src/extended/components/overridable-props/overridable-prop-indicator.tsx +0 -138
- package/src/extended/components/overridable-props/utils/validate-prop-label.ts +0 -38
- package/src/extended/consts.ts +0 -3
- package/src/extended/hooks/use-navigate-back.ts +0 -24
- package/src/extended/init.ts +0 -108
- package/src/extended/mcp/index.ts +0 -14
- package/src/extended/mcp/save-as-component-tool.ts +0 -436
- package/src/extended/shortcuts/create-component-shortcut.ts +0 -121
- package/src/extended/store/actions/add-overridable-group.ts +0 -53
- package/src/extended/store/actions/archive-component.ts +0 -18
- package/src/extended/store/actions/create-unpublished-component.ts +0 -99
- package/src/extended/store/actions/delete-overridable-group.ts +0 -32
- package/src/extended/store/actions/delete-overridable-prop.ts +0 -64
- package/src/extended/store/actions/rename-component.ts +0 -48
- package/src/extended/store/actions/rename-overridable-group.ts +0 -33
- package/src/extended/store/actions/reorder-group-props.ts +0 -37
- package/src/extended/store/actions/reorder-overridable-groups.ts +0 -24
- package/src/extended/store/actions/reset-sanitized-components.ts +0 -5
- package/src/extended/store/actions/set-overridable-prop.ts +0 -109
- package/src/extended/store/actions/update-component-sanitized-attribute.ts +0 -7
- package/src/extended/store/actions/update-current-component.ts +0 -12
- package/src/extended/store/actions/update-overridable-prop-params.ts +0 -52
- package/src/extended/store/utils/groups-transformers.ts +0 -187
- package/src/extended/sync/before-save.ts +0 -52
- package/src/extended/sync/cleanup-overridable-props-on-delete.ts +0 -78
- package/src/extended/sync/create-components-before-save.ts +0 -111
- package/src/extended/sync/handle-component-edit-mode-container.ts +0 -114
- package/src/extended/sync/prevent-non-atomic-nesting.ts +0 -198
- package/src/extended/sync/revert-overridables-on-copy-or-duplicate.ts +0 -66
- package/src/extended/sync/sanitize-overridable-props.ts +0 -32
- package/src/extended/sync/set-component-overridable-props-settings-before-save.ts +0 -22
- package/src/extended/sync/update-archived-component-before-save.ts +0 -31
- package/src/extended/sync/update-component-title-before-save.ts +0 -18
- package/src/extended/utils/component-form-schema.ts +0 -32
- package/src/extended/utils/component-name-validation.ts +0 -25
- package/src/extended/utils/create-component-model.ts +0 -28
- package/src/extended/utils/get-container-for-new-element.ts +0 -49
- package/src/extended/utils/is-editing-component.ts +0 -5
- package/src/extended/utils/replace-element-with-component.ts +0 -11
- package/src/extended/utils/revert-overridable-settings.ts +0 -207
package/dist/index.mjs
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
// src/init.ts
|
|
2
|
-
import { injectIntoLogic
|
|
2
|
+
import { injectIntoLogic } from "@elementor/editor";
|
|
3
3
|
import {
|
|
4
4
|
registerElementType,
|
|
5
5
|
settingsTransformersRegistry as settingsTransformersRegistry2
|
|
6
6
|
} from "@elementor/editor-canvas";
|
|
7
|
-
import { getV1CurrentDocument
|
|
8
|
-
import { registerEditingPanelReplacement
|
|
7
|
+
import { getV1CurrentDocument } from "@elementor/editor-documents";
|
|
8
|
+
import { registerEditingPanelReplacement } from "@elementor/editor-editing-panel";
|
|
9
9
|
import { injectTab } from "@elementor/editor-elements-panel";
|
|
10
10
|
import { stylesRepository } from "@elementor/editor-styles-repository";
|
|
11
|
-
import { registerDataHook as
|
|
11
|
+
import { registerDataHook as registerDataHook2 } from "@elementor/editor-v1-adapters";
|
|
12
12
|
import { __registerSlice as registerSlice } from "@elementor/store";
|
|
13
|
-
import {
|
|
14
|
-
import { __ as __36 } from "@wordpress/i18n";
|
|
13
|
+
import { __ as __12 } from "@wordpress/i18n";
|
|
15
14
|
|
|
16
15
|
// src/component-instance-transformer.ts
|
|
17
16
|
import { createTransformer } from "@elementor/editor-canvas";
|
|
@@ -31,10 +30,10 @@ import { __createAsyncThunk as createAsyncThunk } from "@elementor/store";
|
|
|
31
30
|
import { ajax } from "@elementor/editor-v1-adapters";
|
|
32
31
|
import { httpService } from "@elementor/http-client";
|
|
33
32
|
var BASE_URL = "elementor/v1/components";
|
|
34
|
-
var getParams = (
|
|
33
|
+
var getParams = (id) => ({
|
|
35
34
|
action: "get_document_config",
|
|
36
|
-
unique_id: `document-config-${
|
|
37
|
-
data: { id
|
|
35
|
+
unique_id: `document-config-${id}`,
|
|
36
|
+
data: { id }
|
|
38
37
|
});
|
|
39
38
|
var apiClient = {
|
|
40
39
|
get: () => httpService().get(`${BASE_URL}`).then((res) => res.data.data),
|
|
@@ -43,8 +42,8 @@ var apiClient = {
|
|
|
43
42
|
ids,
|
|
44
43
|
status
|
|
45
44
|
}),
|
|
46
|
-
getComponentConfig: (
|
|
47
|
-
invalidateComponentConfigCache: (
|
|
45
|
+
getComponentConfig: (id) => ajax.load(getParams(id)),
|
|
46
|
+
invalidateComponentConfigCache: (id) => ajax.invalidateCache(getParams(id)),
|
|
48
47
|
getComponentLockStatus: async (componentId) => await httpService().get(`${BASE_URL}/lock-status`, {
|
|
49
48
|
params: {
|
|
50
49
|
componentId
|
|
@@ -298,10 +297,10 @@ var useIsSanitizedComponent = (componentId, key) => {
|
|
|
298
297
|
|
|
299
298
|
// src/utils/component-document-data.ts
|
|
300
299
|
import { getV1DocumentsManager } from "@elementor/editor-documents";
|
|
301
|
-
var getComponentDocumentData = async (
|
|
300
|
+
var getComponentDocumentData = async (id) => {
|
|
302
301
|
const documentManager = getV1DocumentsManager();
|
|
303
302
|
try {
|
|
304
|
-
return await documentManager.request(
|
|
303
|
+
return await documentManager.request(id);
|
|
305
304
|
} catch {
|
|
306
305
|
return null;
|
|
307
306
|
}
|
|
@@ -310,11 +309,11 @@ var getComponentDocumentData = async (id2) => {
|
|
|
310
309
|
// src/component-instance-transformer.ts
|
|
311
310
|
var componentInstanceTransformer = createTransformer(
|
|
312
311
|
async ({
|
|
313
|
-
component_id:
|
|
312
|
+
component_id: id,
|
|
314
313
|
overrides: overridesValue
|
|
315
314
|
}) => {
|
|
316
315
|
const unpublishedComponents = selectUnpublishedComponents(getState());
|
|
317
|
-
const unpublishedComponent = unpublishedComponents.find(({ uid }) => uid ===
|
|
316
|
+
const unpublishedComponent = unpublishedComponents.find(({ uid }) => uid === id);
|
|
318
317
|
const overrides = overridesValue?.reduce((acc, override) => ({ ...acc, ...override }), {});
|
|
319
318
|
if (unpublishedComponent) {
|
|
320
319
|
return {
|
|
@@ -322,10 +321,10 @@ var componentInstanceTransformer = createTransformer(
|
|
|
322
321
|
overrides
|
|
323
322
|
};
|
|
324
323
|
}
|
|
325
|
-
if (typeof
|
|
326
|
-
throw new Error(`Component ID "${
|
|
324
|
+
if (typeof id !== "number") {
|
|
325
|
+
throw new Error(`Component ID "${id}" not valid.`);
|
|
327
326
|
}
|
|
328
|
-
const data = await getComponentDocumentData(
|
|
327
|
+
const data = await getComponentDocumentData(id);
|
|
329
328
|
return {
|
|
330
329
|
elements: data?.elements ?? [],
|
|
331
330
|
overrides
|
|
@@ -1378,8 +1377,8 @@ var componentsActions = {
|
|
|
1378
1377
|
resetUnpublished() {
|
|
1379
1378
|
dispatch2(slice.actions.resetUnpublished());
|
|
1380
1379
|
},
|
|
1381
|
-
removeStyles(
|
|
1382
|
-
dispatch2(slice.actions.removeStyles({ id
|
|
1380
|
+
removeStyles(id) {
|
|
1381
|
+
dispatch2(slice.actions.removeStyles({ id }));
|
|
1383
1382
|
},
|
|
1384
1383
|
addStyles(styles) {
|
|
1385
1384
|
dispatch2(slice.actions.addStyles(styles));
|
|
@@ -1393,8 +1392,8 @@ var componentsActions = {
|
|
|
1393
1392
|
archive(componentId) {
|
|
1394
1393
|
dispatch2(slice.actions.archive(componentId));
|
|
1395
1394
|
},
|
|
1396
|
-
setCurrentComponentId(
|
|
1397
|
-
safeDispatch()?.(slice.actions.setCurrentComponentId(
|
|
1395
|
+
setCurrentComponentId(id) {
|
|
1396
|
+
safeDispatch()?.(slice.actions.setCurrentComponentId(id));
|
|
1398
1397
|
},
|
|
1399
1398
|
setPath(path) {
|
|
1400
1399
|
safeDispatch()?.(slice.actions.setPath(path));
|
|
@@ -1863,9 +1862,9 @@ function OverridePropsGroup({ group }) {
|
|
|
1863
1862
|
const handleClick = () => {
|
|
1864
1863
|
setIsOpen(!isOpen);
|
|
1865
1864
|
};
|
|
1866
|
-
const
|
|
1867
|
-
const labelId = `label-${
|
|
1868
|
-
const contentId = `content-${
|
|
1865
|
+
const id = useId();
|
|
1866
|
+
const labelId = `label-${id}`;
|
|
1867
|
+
const contentId = `content-${id}`;
|
|
1869
1868
|
const title = group.label;
|
|
1870
1869
|
return /* @__PURE__ */ React17.createElement(Box7, { "aria-label": `${title} section` }, /* @__PURE__ */ React17.createElement(
|
|
1871
1870
|
ListItemButton3,
|
|
@@ -2059,12 +2058,12 @@ async function getComponentIds(elements, cache) {
|
|
|
2059
2058
|
}
|
|
2060
2059
|
async function getDocumentsMap(ids, cache) {
|
|
2061
2060
|
const documents = await Promise.all(
|
|
2062
|
-
ids.map(async (
|
|
2063
|
-
const document = await cache.get(
|
|
2061
|
+
ids.map(async (id) => {
|
|
2062
|
+
const document = await cache.get(id);
|
|
2064
2063
|
if (!document) {
|
|
2065
2064
|
return null;
|
|
2066
2065
|
}
|
|
2067
|
-
return [
|
|
2066
|
+
return [id, document];
|
|
2068
2067
|
})
|
|
2069
2068
|
);
|
|
2070
2069
|
return new Map(documents.filter((document) => document !== null));
|
|
@@ -2102,7 +2101,7 @@ function loadComponentsStyles(documents) {
|
|
|
2102
2101
|
return;
|
|
2103
2102
|
}
|
|
2104
2103
|
const knownComponents = selectStyles(getState7());
|
|
2105
|
-
const unknownDocuments = new Map([...documents.entries()].filter(([
|
|
2104
|
+
const unknownDocuments = new Map([...documents.entries()].filter(([id]) => !knownComponents[id]));
|
|
2106
2105
|
if (!unknownDocuments.size) {
|
|
2107
2106
|
return;
|
|
2108
2107
|
}
|
|
@@ -2110,7 +2109,7 @@ function loadComponentsStyles(documents) {
|
|
|
2110
2109
|
}
|
|
2111
2110
|
function addStyles(documents) {
|
|
2112
2111
|
const styles = Object.fromEntries(
|
|
2113
|
-
[...documents.entries()].map(([
|
|
2112
|
+
[...documents.entries()].map(([id, document]) => [id, extractStylesFromDocument(document)])
|
|
2114
2113
|
);
|
|
2115
2114
|
dispatch4(slice.actions.addStyles(styles));
|
|
2116
2115
|
}
|
|
@@ -2166,10 +2165,10 @@ var ELEMENT_ID_LENGTH = 7;
|
|
|
2166
2165
|
function formatComponentElementsId(elements, path) {
|
|
2167
2166
|
return elements.map((element) => {
|
|
2168
2167
|
const nestingPath = [...path, element.id];
|
|
2169
|
-
const
|
|
2168
|
+
const id = hashString(nestingPath.join("_"), ELEMENT_ID_LENGTH);
|
|
2170
2169
|
return {
|
|
2171
2170
|
...element,
|
|
2172
|
-
id
|
|
2171
|
+
id,
|
|
2173
2172
|
originId: element.id,
|
|
2174
2173
|
elements: element.elements ? formatComponentElementsId(element.elements, nestingPath) : void 0
|
|
2175
2174
|
};
|
|
@@ -2529,3912 +2528,200 @@ function createComponentModel() {
|
|
|
2529
2528
|
});
|
|
2530
2529
|
}
|
|
2531
2530
|
|
|
2532
|
-
// src/
|
|
2533
|
-
import {
|
|
2534
|
-
import {
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
registerFieldIndicator
|
|
2541
|
-
} from "@elementor/editor-editing-panel";
|
|
2542
|
-
import { registerTab } from "@elementor/editor-elements-panel";
|
|
2543
|
-
import { __registerPanel as registerPanel } from "@elementor/editor-panels";
|
|
2544
|
-
import { registerDataHook as registerDataHook4 } from "@elementor/editor-v1-adapters";
|
|
2545
|
-
import { __ as __34 } from "@wordpress/i18n";
|
|
2546
|
-
|
|
2547
|
-
// src/extended/components/component-panel-header/component-panel-header.tsx
|
|
2548
|
-
import * as React29 from "react";
|
|
2549
|
-
import { useSuppressedMessage } from "@elementor/editor-current-user";
|
|
2550
|
-
import { getV1DocumentsManager as getV1DocumentsManager3 } from "@elementor/editor-documents";
|
|
2551
|
-
import { PanelHeader as PanelHeader3 } from "@elementor/editor-panels";
|
|
2552
|
-
import { EllipsisWithTooltip as EllipsisWithTooltip4 } from "@elementor/editor-ui";
|
|
2553
|
-
import { ArrowLeftIcon, ComponentsFilledIcon } from "@elementor/icons";
|
|
2554
|
-
import { __getState as getState9 } from "@elementor/store";
|
|
2555
|
-
import { Box as Box15, Divider as Divider4, IconButton as IconButton5, Tooltip as Tooltip5, Typography as Typography11 } from "@elementor/ui";
|
|
2556
|
-
import { __ as __22 } from "@wordpress/i18n";
|
|
2557
|
-
|
|
2558
|
-
// src/extended/hooks/use-navigate-back.ts
|
|
2559
|
-
import { useCallback } from "react";
|
|
2560
|
-
import { getV1DocumentsManager as getV1DocumentsManager2 } from "@elementor/editor-documents";
|
|
2561
|
-
import { __useSelector as useSelector4 } from "@elementor/store";
|
|
2562
|
-
function useNavigateBack() {
|
|
2563
|
-
const path = useSelector4(selectPath);
|
|
2564
|
-
const documentsManager = getV1DocumentsManager2();
|
|
2565
|
-
return useCallback(() => {
|
|
2566
|
-
const { componentId: prevComponentId, instanceId: prevComponentInstanceId } = path.at(-2) ?? {};
|
|
2567
|
-
if (prevComponentId && prevComponentInstanceId) {
|
|
2568
|
-
switchToComponent(prevComponentId, prevComponentInstanceId);
|
|
2569
|
-
return;
|
|
2570
|
-
}
|
|
2571
|
-
switchToComponent(documentsManager.getInitialId());
|
|
2572
|
-
}, [path, documentsManager]);
|
|
2531
|
+
// src/populate-store.ts
|
|
2532
|
+
import { useEffect as useEffect2 } from "react";
|
|
2533
|
+
import { __dispatch as dispatch5 } from "@elementor/store";
|
|
2534
|
+
function PopulateStore() {
|
|
2535
|
+
useEffect2(() => {
|
|
2536
|
+
dispatch5(loadComponents());
|
|
2537
|
+
}, []);
|
|
2538
|
+
return null;
|
|
2573
2539
|
}
|
|
2574
2540
|
|
|
2575
|
-
// src/
|
|
2576
|
-
import
|
|
2577
|
-
import {
|
|
2578
|
-
import {
|
|
2579
|
-
import {
|
|
2541
|
+
// src/prevent-circular-nesting.ts
|
|
2542
|
+
import { getAllDescendants } from "@elementor/editor-elements";
|
|
2543
|
+
import { notify as notify3 } from "@elementor/editor-notifications";
|
|
2544
|
+
import { blockCommand } from "@elementor/editor-v1-adapters";
|
|
2545
|
+
import { __getState as getState9 } from "@elementor/store";
|
|
2580
2546
|
import { __ as __11 } from "@wordpress/i18n";
|
|
2581
|
-
var
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
if (!anchorRef.current || !shouldShowIntroduction) {
|
|
2587
|
-
return null;
|
|
2588
|
-
}
|
|
2589
|
-
return /* @__PURE__ */ React20.createElement(
|
|
2590
|
-
Popover,
|
|
2591
|
-
{
|
|
2592
|
-
anchorEl: anchorRef.current,
|
|
2593
|
-
open: shouldShowIntroduction,
|
|
2594
|
-
anchorOrigin: {
|
|
2595
|
-
vertical: "top",
|
|
2596
|
-
horizontal: "right"
|
|
2597
|
-
},
|
|
2598
|
-
transformOrigin: {
|
|
2599
|
-
vertical: "top",
|
|
2600
|
-
horizontal: -30
|
|
2601
|
-
},
|
|
2602
|
-
onClose
|
|
2603
|
-
},
|
|
2604
|
-
/* @__PURE__ */ React20.createElement(Box9, { sx: { width: "296px" } }, /* @__PURE__ */ React20.createElement(PopoverHeader, { title: __11("Add your first property", "elementor"), onClose }), /* @__PURE__ */ React20.createElement(
|
|
2605
|
-
Image,
|
|
2606
|
-
{
|
|
2607
|
-
sx: { width: "296px", height: "160px" },
|
|
2608
|
-
src: "https://assets.elementor.com/packages/v1/images/components-properties-intro.png",
|
|
2609
|
-
alt: ""
|
|
2610
|
-
}
|
|
2611
|
-
), /* @__PURE__ */ React20.createElement(PopoverContent, null, /* @__PURE__ */ React20.createElement(Stack12, { sx: { p: 2 } }, /* @__PURE__ */ React20.createElement(Typography6, { variant: "body2" }, __11("Properties make instances flexible.", "elementor")), /* @__PURE__ */ React20.createElement(Typography6, { variant: "body2" }, __11(
|
|
2612
|
-
"Select any Element, then in the General tab, click next to any setting you want users to customize - like text, images, or links.",
|
|
2613
|
-
"elementor"
|
|
2614
|
-
)), /* @__PURE__ */ React20.createElement(Typography6, { variant: "body2", sx: { mt: 2 } }, __11(
|
|
2615
|
-
"Your properties will appear in the Properties panel, where you can organize and manage them anytime.",
|
|
2616
|
-
"elementor"
|
|
2617
|
-
)), /* @__PURE__ */ React20.createElement(
|
|
2618
|
-
Link2,
|
|
2619
|
-
{
|
|
2620
|
-
href: "http://go.elementor.com/components-guide",
|
|
2621
|
-
target: "_blank",
|
|
2622
|
-
sx: { mt: 2 },
|
|
2623
|
-
color: "info.main",
|
|
2624
|
-
variant: "body2"
|
|
2625
|
-
},
|
|
2626
|
-
__11("Learn more", "elementor")
|
|
2627
|
-
), /* @__PURE__ */ React20.createElement(Stack12, { direction: "row", alignItems: "center", justifyContent: "flex-end", sx: { pt: 1 } }, /* @__PURE__ */ React20.createElement(Button3, { size: "medium", variant: "contained", onClick: onClose }, __11("Got it", "elementor"))))))
|
|
2628
|
-
);
|
|
2547
|
+
var COMPONENT_TYPE = "e-component";
|
|
2548
|
+
var COMPONENT_CIRCULAR_NESTING_ALERT = {
|
|
2549
|
+
type: "default",
|
|
2550
|
+
message: __11("Can't add this component - components that contain each other can't be nested.", "elementor"),
|
|
2551
|
+
id: "circular-component-nesting-blocked"
|
|
2629
2552
|
};
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
import { __createPanel as createPanel, Panel } from "@elementor/editor-panels";
|
|
2635
|
-
import { ThemeProvider as ThemeProvider2 } from "@elementor/editor-ui";
|
|
2636
|
-
import { Alert, Box as Box13, ErrorBoundary } from "@elementor/ui";
|
|
2637
|
-
import { __ as __20 } from "@wordpress/i18n";
|
|
2638
|
-
|
|
2639
|
-
// src/extended/components/component-properties-panel/component-properties-panel-content.tsx
|
|
2640
|
-
import * as React26 from "react";
|
|
2641
|
-
import { useMemo, useRef, useState as useState5 } from "react";
|
|
2642
|
-
import { setDocumentModifiedStatus as setDocumentModifiedStatus3 } from "@elementor/editor-documents";
|
|
2643
|
-
import { PanelBody as PanelBody2, PanelHeader as PanelHeader2, PanelHeaderTitle as PanelHeaderTitle2 } from "@elementor/editor-panels";
|
|
2644
|
-
import { ComponentPropListIcon as ComponentPropListIcon3, FolderPlusIcon, XIcon as XIcon2 } from "@elementor/icons";
|
|
2645
|
-
import { Divider as Divider3, IconButton as IconButton4, List as List3, Stack as Stack16, Tooltip as Tooltip3 } from "@elementor/ui";
|
|
2646
|
-
import { generateUniqueId as generateUniqueId2 } from "@elementor/utils";
|
|
2647
|
-
import { __ as __19 } from "@wordpress/i18n";
|
|
2648
|
-
|
|
2649
|
-
// src/extended/store/actions/add-overridable-group.ts
|
|
2650
|
-
function addOverridableGroup({
|
|
2651
|
-
componentId,
|
|
2652
|
-
groupId,
|
|
2653
|
-
label,
|
|
2654
|
-
source
|
|
2655
|
-
}) {
|
|
2656
|
-
const currentComponent = componentsSelectors.getCurrentComponent();
|
|
2657
|
-
const overridableProps = componentsSelectors.getOverridableProps(componentId);
|
|
2658
|
-
if (!overridableProps) {
|
|
2659
|
-
return;
|
|
2660
|
-
}
|
|
2661
|
-
const newGroup = {
|
|
2662
|
-
id: groupId,
|
|
2663
|
-
label,
|
|
2664
|
-
props: []
|
|
2665
|
-
};
|
|
2666
|
-
componentsActions.setOverridableProps(componentId, {
|
|
2667
|
-
...overridableProps,
|
|
2668
|
-
groups: {
|
|
2669
|
-
...overridableProps.groups,
|
|
2670
|
-
items: {
|
|
2671
|
-
...overridableProps.groups.items,
|
|
2672
|
-
[groupId]: newGroup
|
|
2673
|
-
},
|
|
2674
|
-
order: [groupId, ...overridableProps.groups.order]
|
|
2675
|
-
}
|
|
2553
|
+
function initCircularNestingPrevention() {
|
|
2554
|
+
blockCommand({
|
|
2555
|
+
command: "document/elements/create",
|
|
2556
|
+
condition: blockCircularCreate
|
|
2676
2557
|
});
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2558
|
+
blockCommand({
|
|
2559
|
+
command: "document/elements/move",
|
|
2560
|
+
condition: blockCircularMove
|
|
2561
|
+
});
|
|
2562
|
+
blockCommand({
|
|
2563
|
+
command: "document/elements/paste",
|
|
2564
|
+
condition: blockCircularPaste
|
|
2682
2565
|
});
|
|
2683
|
-
return newGroup;
|
|
2684
|
-
}
|
|
2685
|
-
|
|
2686
|
-
// src/extended/store/utils/groups-transformers.ts
|
|
2687
|
-
import { generateUniqueId } from "@elementor/utils";
|
|
2688
|
-
import { __ as __12 } from "@wordpress/i18n";
|
|
2689
|
-
function removePropFromAllGroups(groups, propKey) {
|
|
2690
|
-
const propKeys = Array.isArray(propKey) ? propKey : [propKey];
|
|
2691
|
-
return {
|
|
2692
|
-
...groups,
|
|
2693
|
-
items: Object.fromEntries(
|
|
2694
|
-
Object.entries(groups.items).map(([groupId, group]) => [
|
|
2695
|
-
groupId,
|
|
2696
|
-
{
|
|
2697
|
-
...group,
|
|
2698
|
-
props: group.props.filter((p) => !propKeys.includes(p))
|
|
2699
|
-
}
|
|
2700
|
-
])
|
|
2701
|
-
)
|
|
2702
|
-
};
|
|
2703
2566
|
}
|
|
2704
|
-
function
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
return groups;
|
|
2708
|
-
}
|
|
2709
|
-
if (group.props.includes(propKey)) {
|
|
2710
|
-
return groups;
|
|
2567
|
+
function wouldCreateCircularNesting(componentIdToAdd) {
|
|
2568
|
+
if (componentIdToAdd === void 0) {
|
|
2569
|
+
return false;
|
|
2711
2570
|
}
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
...group,
|
|
2718
|
-
props: [...group.props, propKey]
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
};
|
|
2722
|
-
}
|
|
2723
|
-
function movePropBetweenGroups(groups, propKey, fromGroupId, toGroupId) {
|
|
2724
|
-
if (fromGroupId === toGroupId) {
|
|
2725
|
-
return groups;
|
|
2571
|
+
const state = getState9();
|
|
2572
|
+
const currentComponentId = selectCurrentComponentId(state);
|
|
2573
|
+
const path = selectPath(state);
|
|
2574
|
+
if (currentComponentId === null) {
|
|
2575
|
+
return false;
|
|
2726
2576
|
}
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
}
|
|
2730
|
-
function removePropFromGroup(groups, groupId, propKey) {
|
|
2731
|
-
const group = groups.items[groupId];
|
|
2732
|
-
if (!group) {
|
|
2733
|
-
return groups;
|
|
2577
|
+
if (componentIdToAdd === currentComponentId) {
|
|
2578
|
+
return true;
|
|
2734
2579
|
}
|
|
2735
|
-
return
|
|
2736
|
-
...groups,
|
|
2737
|
-
items: {
|
|
2738
|
-
...groups.items,
|
|
2739
|
-
[groupId]: {
|
|
2740
|
-
...group,
|
|
2741
|
-
props: group.props.filter((p) => p !== propKey)
|
|
2742
|
-
}
|
|
2743
|
-
}
|
|
2744
|
-
};
|
|
2580
|
+
return path.some((item) => item.componentId === componentIdToAdd);
|
|
2745
2581
|
}
|
|
2746
|
-
function
|
|
2747
|
-
if (
|
|
2748
|
-
return
|
|
2582
|
+
function extractComponentIdFromModel(model) {
|
|
2583
|
+
if (!model) {
|
|
2584
|
+
return null;
|
|
2749
2585
|
}
|
|
2750
|
-
|
|
2751
|
-
|
|
2586
|
+
const isComponent = model.widgetType === COMPONENT_TYPE;
|
|
2587
|
+
if (!isComponent) {
|
|
2588
|
+
return null;
|
|
2752
2589
|
}
|
|
2753
|
-
return
|
|
2590
|
+
return model.settings?.component_instance?.value?.component_id?.value ?? null;
|
|
2754
2591
|
}
|
|
2755
|
-
function
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
...groups,
|
|
2761
|
-
items: {
|
|
2762
|
-
...groups.items,
|
|
2763
|
-
[newGroupId]: {
|
|
2764
|
-
id: newGroupId,
|
|
2765
|
-
label: newLabel,
|
|
2766
|
-
props: []
|
|
2767
|
-
}
|
|
2768
|
-
},
|
|
2769
|
-
order: [...groups.order, newGroupId]
|
|
2770
|
-
},
|
|
2771
|
-
groupId: newGroupId
|
|
2772
|
-
};
|
|
2592
|
+
function extractComponentIdFromElement(element) {
|
|
2593
|
+
if (element.widgetType !== COMPONENT_TYPE) {
|
|
2594
|
+
return null;
|
|
2595
|
+
}
|
|
2596
|
+
return element.settings?.component_instance?.value?.component_id?.value ?? null;
|
|
2773
2597
|
}
|
|
2774
|
-
function
|
|
2775
|
-
const
|
|
2776
|
-
const
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
{
|
|
2784
|
-
...group,
|
|
2785
|
-
props: group.props.filter((prop) => !overrideKeysToRemove.includes(prop))
|
|
2786
|
-
}
|
|
2787
|
-
]
|
|
2788
|
-
)
|
|
2789
|
-
);
|
|
2790
|
-
return {
|
|
2791
|
-
props: remainingProps,
|
|
2792
|
-
groups: {
|
|
2793
|
-
items: updatedGroupItems,
|
|
2794
|
-
order: overridableProps.groups.order.filter((groupId) => !overrideKeysToRemove.includes(groupId))
|
|
2598
|
+
function extractComponentIdsFromElements(elements) {
|
|
2599
|
+
const ids = [];
|
|
2600
|
+
for (const element of elements) {
|
|
2601
|
+
const componentId = extractComponentIdFromElement(element);
|
|
2602
|
+
if (componentId !== null) {
|
|
2603
|
+
ids.push(componentId);
|
|
2604
|
+
}
|
|
2605
|
+
if (element.elements?.length) {
|
|
2606
|
+
ids.push(...extractComponentIdsFromElements(element.elements));
|
|
2795
2607
|
}
|
|
2796
|
-
};
|
|
2797
|
-
}
|
|
2798
|
-
function ensureGroupInOrder(groups, groupId) {
|
|
2799
|
-
if (groups.order.includes(groupId)) {
|
|
2800
|
-
return groups;
|
|
2801
2608
|
}
|
|
2802
|
-
return
|
|
2803
|
-
...groups,
|
|
2804
|
-
order: [...groups.order, groupId]
|
|
2805
|
-
};
|
|
2806
|
-
}
|
|
2807
|
-
function deleteGroup(groups, groupId) {
|
|
2808
|
-
const { [groupId]: removed, ...remainingItems } = groups.items;
|
|
2809
|
-
return {
|
|
2810
|
-
items: remainingItems,
|
|
2811
|
-
order: groups.order.filter((id2) => id2 !== groupId)
|
|
2812
|
-
};
|
|
2609
|
+
return ids;
|
|
2813
2610
|
}
|
|
2814
|
-
function
|
|
2815
|
-
const
|
|
2816
|
-
if (
|
|
2817
|
-
return
|
|
2611
|
+
function extractComponentIdFromContainer(container) {
|
|
2612
|
+
const widgetType = container.model?.get?.("widgetType");
|
|
2613
|
+
if (widgetType !== COMPONENT_TYPE) {
|
|
2614
|
+
return null;
|
|
2818
2615
|
}
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
...groups.items,
|
|
2823
|
-
[groupId]: {
|
|
2824
|
-
...group,
|
|
2825
|
-
label: newLabel
|
|
2826
|
-
}
|
|
2827
|
-
}
|
|
2828
|
-
};
|
|
2616
|
+
const settings = container.model?.get?.("settings");
|
|
2617
|
+
const componentInstance = settings?.get?.("component_instance");
|
|
2618
|
+
return componentInstance?.value?.component_id?.value ?? null;
|
|
2829
2619
|
}
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
const overridableProps = componentsSelectors.getOverridableProps(componentId);
|
|
2834
|
-
if (!overridableProps) {
|
|
2620
|
+
function blockCircularCreate(args) {
|
|
2621
|
+
const componentId = extractComponentIdFromModel(args.model);
|
|
2622
|
+
if (componentId === null) {
|
|
2835
2623
|
return false;
|
|
2836
2624
|
}
|
|
2837
|
-
const
|
|
2838
|
-
if (
|
|
2839
|
-
|
|
2625
|
+
const isBlocked = wouldCreateCircularNesting(componentId);
|
|
2626
|
+
if (isBlocked) {
|
|
2627
|
+
notify3(COMPONENT_CIRCULAR_NESTING_ALERT);
|
|
2840
2628
|
}
|
|
2841
|
-
|
|
2842
|
-
componentsActions.setOverridableProps(componentId, {
|
|
2843
|
-
...overridableProps,
|
|
2844
|
-
groups: updatedGroups
|
|
2845
|
-
});
|
|
2846
|
-
return true;
|
|
2629
|
+
return isBlocked;
|
|
2847
2630
|
}
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
revertComponentInstanceOverridableSetting(elementId, overrideKey);
|
|
2863
|
-
return;
|
|
2864
|
-
}
|
|
2865
|
-
updateElementSettings({
|
|
2866
|
-
id: elementId,
|
|
2867
|
-
props: { [settingKey]: originValue ?? null },
|
|
2868
|
-
withHistory: false
|
|
2631
|
+
function blockCircularMove(args) {
|
|
2632
|
+
const { containers = [args.container] } = args;
|
|
2633
|
+
const hasCircularComponent = containers.some((container) => {
|
|
2634
|
+
if (!container) {
|
|
2635
|
+
return false;
|
|
2636
|
+
}
|
|
2637
|
+
const allElements = getAllDescendants(container);
|
|
2638
|
+
return allElements.some((element) => {
|
|
2639
|
+
const componentId = extractComponentIdFromContainer(element);
|
|
2640
|
+
if (componentId === null) {
|
|
2641
|
+
return false;
|
|
2642
|
+
}
|
|
2643
|
+
return wouldCreateCircularNesting(componentId);
|
|
2644
|
+
});
|
|
2869
2645
|
});
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
const setting = getElementSetting(elementId, "component_instance");
|
|
2873
|
-
const componentInstance = componentInstancePropTypeUtil.extract(setting);
|
|
2874
|
-
const overrides = componentInstanceOverridesPropTypeUtil.extract(componentInstance?.overrides);
|
|
2875
|
-
if (!overrides?.length) {
|
|
2876
|
-
return;
|
|
2646
|
+
if (hasCircularComponent) {
|
|
2647
|
+
notify3(COMPONENT_CIRCULAR_NESTING_ALERT);
|
|
2877
2648
|
}
|
|
2878
|
-
|
|
2879
|
-
const updatedSetting = componentInstancePropTypeUtil.create({
|
|
2880
|
-
...componentInstance,
|
|
2881
|
-
overrides: componentInstanceOverridesPropTypeUtil.create(revertedOverrides)
|
|
2882
|
-
});
|
|
2883
|
-
updateElementSettings({
|
|
2884
|
-
id: elementId,
|
|
2885
|
-
props: { component_instance: updatedSetting },
|
|
2886
|
-
withHistory: false
|
|
2887
|
-
});
|
|
2888
|
-
}
|
|
2889
|
-
function revertComponentInstanceOverrides(overrides, filterByKey) {
|
|
2890
|
-
return overrides.map((item) => {
|
|
2891
|
-
if (!componentOverridablePropTypeUtil.isValid(item)) {
|
|
2892
|
-
return item;
|
|
2893
|
-
}
|
|
2894
|
-
if (!componentInstanceOverridePropTypeUtil.isValid(item.value.origin_value)) {
|
|
2895
|
-
return null;
|
|
2896
|
-
}
|
|
2897
|
-
if (filterByKey && item.value.override_key !== filterByKey) {
|
|
2898
|
-
return item;
|
|
2899
|
-
}
|
|
2900
|
-
return item.value.origin_value;
|
|
2901
|
-
}).filter((item) => item !== null);
|
|
2649
|
+
return hasCircularComponent;
|
|
2902
2650
|
}
|
|
2903
|
-
function
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
if (componentOverridablePropTypeUtil.isValid(value)) {
|
|
2908
|
-
revertedSettings[key] = value.value.origin_value;
|
|
2909
|
-
hasChanges = true;
|
|
2910
|
-
} else {
|
|
2911
|
-
revertedSettings[key] = value;
|
|
2912
|
-
}
|
|
2651
|
+
function blockCircularPaste(args) {
|
|
2652
|
+
const { storageType } = args;
|
|
2653
|
+
if (storageType !== "localstorage") {
|
|
2654
|
+
return false;
|
|
2913
2655
|
}
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
const revertedElement = { ...elementData };
|
|
2918
|
-
if (isComponentInstance({ widgetType: elementData.widgetType, elType: elementData.elType })) {
|
|
2919
|
-
revertedElement.settings = revertComponentInstanceSettings(elementData.settings);
|
|
2920
|
-
} else if (revertedElement.settings) {
|
|
2921
|
-
const { settings } = revertOverridablePropsFromSettings(revertedElement.settings);
|
|
2922
|
-
revertedElement.settings = settings;
|
|
2656
|
+
const data = window?.elementorCommon?.storage?.get();
|
|
2657
|
+
if (!data?.clipboard?.elements) {
|
|
2658
|
+
return false;
|
|
2923
2659
|
}
|
|
2924
|
-
|
|
2925
|
-
|
|
2660
|
+
const allComponentIds = extractComponentIdsFromElements(data.clipboard.elements);
|
|
2661
|
+
const hasCircularComponent = allComponentIds.some(wouldCreateCircularNesting);
|
|
2662
|
+
if (hasCircularComponent) {
|
|
2663
|
+
notify3(COMPONENT_CIRCULAR_NESTING_ALERT);
|
|
2926
2664
|
}
|
|
2927
|
-
return
|
|
2665
|
+
return hasCircularComponent;
|
|
2928
2666
|
}
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
if (!overrides?.length) {
|
|
2936
|
-
return settings;
|
|
2937
|
-
}
|
|
2938
|
-
const revertedOverrides = revertComponentInstanceOverrides(overrides);
|
|
2939
|
-
return {
|
|
2940
|
-
...settings,
|
|
2941
|
-
component_instance: componentInstancePropTypeUtil.create({
|
|
2942
|
-
...componentInstance,
|
|
2943
|
-
overrides: componentInstanceOverridesPropTypeUtil.create(revertedOverrides)
|
|
2944
|
-
})
|
|
2945
|
-
};
|
|
2667
|
+
|
|
2668
|
+
// src/store/actions/remove-component-styles.ts
|
|
2669
|
+
import { __dispatch as dispatch6 } from "@elementor/store";
|
|
2670
|
+
function removeComponentStyles(id) {
|
|
2671
|
+
apiClient.invalidateComponentConfigCache(id);
|
|
2672
|
+
dispatch6(slice.actions.removeStyles({ id }));
|
|
2946
2673
|
}
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2674
|
+
|
|
2675
|
+
// src/store/components-styles-provider.ts
|
|
2676
|
+
import { createStylesProvider } from "@elementor/editor-styles-repository";
|
|
2677
|
+
import { __getState as getState10, __subscribeWithSelector as subscribeWithSelector } from "@elementor/store";
|
|
2678
|
+
var componentsStylesProvider = createStylesProvider({
|
|
2679
|
+
key: "components-styles",
|
|
2680
|
+
priority: 100,
|
|
2681
|
+
subscribe: (cb) => subscribeWithSelector(
|
|
2682
|
+
(state) => state[SLICE_NAME],
|
|
2683
|
+
() => {
|
|
2684
|
+
cb();
|
|
2685
|
+
}
|
|
2686
|
+
),
|
|
2687
|
+
actions: {
|
|
2688
|
+
all: () => {
|
|
2689
|
+
return selectFlatStyles(getState10());
|
|
2690
|
+
},
|
|
2691
|
+
get: (id) => {
|
|
2692
|
+
return selectFlatStyles(getState10()).find((style) => style.id === id) ?? null;
|
|
2953
2693
|
}
|
|
2954
|
-
});
|
|
2955
|
-
}
|
|
2956
|
-
function revertComponentInstanceOverridesInElement(element) {
|
|
2957
|
-
const settings = element.settings?.toJSON() ?? {};
|
|
2958
|
-
const componentInstance = componentInstancePropTypeUtil.extract(settings.component_instance);
|
|
2959
|
-
const overrides = componentInstanceOverridesPropTypeUtil.extract(componentInstance?.overrides);
|
|
2960
|
-
if (!overrides?.length) {
|
|
2961
|
-
return;
|
|
2962
|
-
}
|
|
2963
|
-
const revertedOverrides = revertComponentInstanceOverrides(overrides);
|
|
2964
|
-
const updatedSetting = componentInstancePropTypeUtil.create({
|
|
2965
|
-
...componentInstance,
|
|
2966
|
-
overrides: componentInstanceOverridesPropTypeUtil.create(revertedOverrides)
|
|
2967
|
-
});
|
|
2968
|
-
updateElementSettings({
|
|
2969
|
-
id: element.id,
|
|
2970
|
-
props: { component_instance: updatedSetting },
|
|
2971
|
-
withHistory: false
|
|
2972
|
-
});
|
|
2973
|
-
}
|
|
2974
|
-
function revertElementSettings(element) {
|
|
2975
|
-
const settings = element.settings?.toJSON() ?? {};
|
|
2976
|
-
const { hasChanges, settings: revertedSettings } = revertOverridablePropsFromSettings(settings);
|
|
2977
|
-
if (!hasChanges) {
|
|
2978
|
-
return;
|
|
2979
2694
|
}
|
|
2980
|
-
|
|
2981
|
-
id: element.id,
|
|
2982
|
-
props: revertedSettings,
|
|
2983
|
-
withHistory: false
|
|
2984
|
-
});
|
|
2985
|
-
}
|
|
2695
|
+
});
|
|
2986
2696
|
|
|
2987
|
-
// src/
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
if (
|
|
2697
|
+
// src/sync/publish-draft-components-in-page-before-save.ts
|
|
2698
|
+
import { invalidateDocumentData as invalidateDocumentData2, isDocumentDirty as isDocumentDirty2 } from "@elementor/editor-documents";
|
|
2699
|
+
async function publishDraftComponentsInPageBeforeSave({ status, elements }) {
|
|
2700
|
+
if (status !== "publish") {
|
|
2991
2701
|
return;
|
|
2992
2702
|
}
|
|
2993
|
-
const
|
|
2994
|
-
const
|
|
2995
|
-
|
|
2996
|
-
const prop = overridableProps.props[key];
|
|
2997
|
-
if (!prop) {
|
|
2998
|
-
continue;
|
|
2999
|
-
}
|
|
3000
|
-
deletedProps.push(prop);
|
|
3001
|
-
revertElementOverridableSetting(prop.elementId, prop.propKey, prop.originValue, key);
|
|
3002
|
-
}
|
|
3003
|
-
if (deletedProps.length === 0) {
|
|
2703
|
+
const documents = await getComponentDocuments(elements);
|
|
2704
|
+
const draftIds = [...documents.values()].filter(isDocumentDirty2).map((document) => document.id);
|
|
2705
|
+
if (draftIds.length === 0) {
|
|
3004
2706
|
return;
|
|
3005
2707
|
}
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
);
|
|
3009
|
-
const updatedGroups = removePropFromAllGroups(overridableProps.groups, propKey);
|
|
3010
|
-
componentsActions.setOverridableProps(componentId, {
|
|
3011
|
-
...overridableProps,
|
|
3012
|
-
props: remainingProps,
|
|
3013
|
-
groups: updatedGroups
|
|
3014
|
-
});
|
|
3015
|
-
const currentComponent = componentsSelectors.getCurrentComponent();
|
|
3016
|
-
for (const prop of deletedProps) {
|
|
3017
|
-
trackComponentEvent({
|
|
3018
|
-
action: "propertyRemoved",
|
|
3019
|
-
source,
|
|
3020
|
-
component_uid: currentComponent?.uid,
|
|
3021
|
-
property_id: prop.overrideKey,
|
|
3022
|
-
property_path: prop.propKey,
|
|
3023
|
-
property_name: prop.label,
|
|
3024
|
-
element_type: prop.widgetType ?? prop.elType
|
|
3025
|
-
});
|
|
3026
|
-
}
|
|
3027
|
-
}
|
|
3028
|
-
|
|
3029
|
-
// src/extended/store/actions/reorder-group-props.ts
|
|
3030
|
-
function reorderGroupProps({ componentId, groupId, newPropsOrder }) {
|
|
3031
|
-
const overridableProps = componentsSelectors.getOverridableProps(componentId);
|
|
3032
|
-
if (!overridableProps) {
|
|
3033
|
-
return;
|
|
3034
|
-
}
|
|
3035
|
-
const group = overridableProps.groups.items[groupId];
|
|
3036
|
-
if (!group) {
|
|
3037
|
-
return;
|
|
3038
|
-
}
|
|
3039
|
-
componentsActions.setOverridableProps(componentId, {
|
|
3040
|
-
...overridableProps,
|
|
3041
|
-
groups: {
|
|
3042
|
-
...overridableProps.groups,
|
|
3043
|
-
items: {
|
|
3044
|
-
...overridableProps.groups.items,
|
|
3045
|
-
[groupId]: {
|
|
3046
|
-
...group,
|
|
3047
|
-
props: newPropsOrder
|
|
3048
|
-
}
|
|
3049
|
-
}
|
|
3050
|
-
}
|
|
3051
|
-
});
|
|
3052
|
-
}
|
|
3053
|
-
|
|
3054
|
-
// src/extended/store/actions/reorder-overridable-groups.ts
|
|
3055
|
-
function reorderOverridableGroups({ componentId, newOrder }) {
|
|
3056
|
-
const overridableProps = componentsSelectors.getOverridableProps(componentId);
|
|
3057
|
-
if (!overridableProps) {
|
|
3058
|
-
return;
|
|
3059
|
-
}
|
|
3060
|
-
componentsActions.setOverridableProps(componentId, {
|
|
3061
|
-
...overridableProps,
|
|
3062
|
-
groups: {
|
|
3063
|
-
...overridableProps.groups,
|
|
3064
|
-
order: newOrder
|
|
3065
|
-
}
|
|
3066
|
-
});
|
|
3067
|
-
}
|
|
3068
|
-
|
|
3069
|
-
// src/extended/store/actions/update-overridable-prop-params.ts
|
|
3070
|
-
function updateOverridablePropParams({
|
|
3071
|
-
componentId,
|
|
3072
|
-
overrideKey,
|
|
3073
|
-
label,
|
|
3074
|
-
groupId
|
|
3075
|
-
}) {
|
|
3076
|
-
const overridableProps = componentsSelectors.getOverridableProps(componentId);
|
|
3077
|
-
if (!overridableProps) {
|
|
3078
|
-
return;
|
|
3079
|
-
}
|
|
3080
|
-
const prop = overridableProps.props[overrideKey];
|
|
3081
|
-
if (!prop) {
|
|
3082
|
-
return;
|
|
3083
|
-
}
|
|
3084
|
-
const oldGroupId = prop.groupId;
|
|
3085
|
-
const newGroupId = groupId ?? oldGroupId;
|
|
3086
|
-
const updatedProp = {
|
|
3087
|
-
...prop,
|
|
3088
|
-
label,
|
|
3089
|
-
groupId: newGroupId
|
|
3090
|
-
};
|
|
3091
|
-
const updatedGroups = movePropBetweenGroups(overridableProps.groups, overrideKey, oldGroupId, newGroupId);
|
|
3092
|
-
componentsActions.setOverridableProps(componentId, {
|
|
3093
|
-
...overridableProps,
|
|
3094
|
-
props: {
|
|
3095
|
-
...overridableProps.props,
|
|
3096
|
-
[overrideKey]: updatedProp
|
|
3097
|
-
},
|
|
3098
|
-
groups: updatedGroups
|
|
3099
|
-
});
|
|
3100
|
-
return updatedProp;
|
|
3101
|
-
}
|
|
3102
|
-
|
|
3103
|
-
// src/extended/components/component-properties-panel/properties-empty-state.tsx
|
|
3104
|
-
import * as React21 from "react";
|
|
3105
|
-
import { useState as useState2 } from "react";
|
|
3106
|
-
import { ComponentPropListIcon as ComponentPropListIcon2 } from "@elementor/icons";
|
|
3107
|
-
import { Link as Link3, Stack as Stack13, Typography as Typography7 } from "@elementor/ui";
|
|
3108
|
-
import { __ as __13 } from "@wordpress/i18n";
|
|
3109
|
-
function PropertiesEmptyState({ introductionRef }) {
|
|
3110
|
-
const [isOpen, setIsOpen] = useState2(false);
|
|
3111
|
-
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(
|
|
3112
|
-
Stack13,
|
|
3113
|
-
{
|
|
3114
|
-
alignItems: "center",
|
|
3115
|
-
justifyContent: "flex-start",
|
|
3116
|
-
height: "100%",
|
|
3117
|
-
color: "text.secondary",
|
|
3118
|
-
sx: { px: 2.5, pt: 10, pb: 5.5 },
|
|
3119
|
-
gap: 1
|
|
3120
|
-
},
|
|
3121
|
-
/* @__PURE__ */ React21.createElement(ComponentPropListIcon2, { fontSize: "large" }),
|
|
3122
|
-
/* @__PURE__ */ React21.createElement(Typography7, { align: "center", variant: "subtitle2" }, __13("Add your first property", "elementor")),
|
|
3123
|
-
/* @__PURE__ */ React21.createElement(Typography7, { align: "center", variant: "caption" }, __13("Make instances flexible while keeping design synced.", "elementor")),
|
|
3124
|
-
/* @__PURE__ */ React21.createElement(Typography7, { align: "center", variant: "caption" }, __13("Select any element, then click + next to a setting to expose it.", "elementor")),
|
|
3125
|
-
/* @__PURE__ */ React21.createElement(
|
|
3126
|
-
Link3,
|
|
3127
|
-
{
|
|
3128
|
-
variant: "caption",
|
|
3129
|
-
color: "secondary",
|
|
3130
|
-
sx: { textDecorationLine: "underline" },
|
|
3131
|
-
onClick: () => setIsOpen(true)
|
|
3132
|
-
},
|
|
3133
|
-
__13("Learn more", "elementor")
|
|
3134
|
-
)
|
|
3135
|
-
), /* @__PURE__ */ React21.createElement(
|
|
3136
|
-
ComponentIntroduction,
|
|
3137
|
-
{
|
|
3138
|
-
anchorRef: introductionRef,
|
|
3139
|
-
shouldShowIntroduction: isOpen,
|
|
3140
|
-
onClose: () => setIsOpen(false)
|
|
3141
|
-
}
|
|
3142
|
-
));
|
|
3143
|
-
}
|
|
3144
|
-
|
|
3145
|
-
// src/extended/components/component-properties-panel/properties-group.tsx
|
|
3146
|
-
import * as React25 from "react";
|
|
3147
|
-
import { EditableField as EditableField2, EllipsisWithTooltip as EllipsisWithTooltip3, MenuListItem as MenuListItem2 } from "@elementor/editor-ui";
|
|
3148
|
-
import { DotsVerticalIcon } from "@elementor/icons";
|
|
3149
|
-
import {
|
|
3150
|
-
bindMenu,
|
|
3151
|
-
bindTrigger as bindTrigger2,
|
|
3152
|
-
Box as Box12,
|
|
3153
|
-
IconButton as IconButton3,
|
|
3154
|
-
List as List2,
|
|
3155
|
-
Menu,
|
|
3156
|
-
Stack as Stack15,
|
|
3157
|
-
Tooltip as Tooltip2,
|
|
3158
|
-
Typography as Typography10,
|
|
3159
|
-
usePopupState as usePopupState2
|
|
3160
|
-
} from "@elementor/ui";
|
|
3161
|
-
import { __ as __16 } from "@wordpress/i18n";
|
|
3162
|
-
|
|
3163
|
-
// src/extended/components/component-properties-panel/property-item.tsx
|
|
3164
|
-
import * as React24 from "react";
|
|
3165
|
-
import { getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
|
|
3166
|
-
import { XIcon } from "@elementor/icons";
|
|
3167
|
-
import { bindPopover, bindTrigger, Box as Box11, IconButton as IconButton2, Popover as Popover2, Typography as Typography9, usePopupState } from "@elementor/ui";
|
|
3168
|
-
|
|
3169
|
-
// src/extended/components/overridable-props/overridable-prop-form.tsx
|
|
3170
|
-
import * as React22 from "react";
|
|
3171
|
-
import { useState as useState3 } from "react";
|
|
3172
|
-
import { Form, MenuListItem } from "@elementor/editor-ui";
|
|
3173
|
-
import { Button as Button4, FormLabel, Grid, Select, Stack as Stack14, TextField as TextField2, Typography as Typography8 } from "@elementor/ui";
|
|
3174
|
-
import { __ as __15 } from "@wordpress/i18n";
|
|
3175
|
-
|
|
3176
|
-
// src/extended/components/overridable-props/utils/validate-prop-label.ts
|
|
3177
|
-
import { __ as __14 } from "@wordpress/i18n";
|
|
3178
|
-
var ERROR_MESSAGES = {
|
|
3179
|
-
EMPTY_NAME: __14("Property name is required", "elementor"),
|
|
3180
|
-
DUPLICATE_NAME: __14("Property name already exists", "elementor")
|
|
3181
|
-
};
|
|
3182
|
-
function validatePropLabel(label, existingLabels, currentLabel) {
|
|
3183
|
-
const trimmedLabel = label.trim();
|
|
3184
|
-
if (!trimmedLabel) {
|
|
3185
|
-
return { isValid: false, errorMessage: ERROR_MESSAGES.EMPTY_NAME };
|
|
3186
|
-
}
|
|
3187
|
-
const normalizedLabel = trimmedLabel.toLowerCase();
|
|
3188
|
-
const normalizedCurrentLabel = currentLabel?.trim().toLowerCase();
|
|
3189
|
-
const isDuplicate = existingLabels.some((existingLabel) => {
|
|
3190
|
-
const normalizedExisting = existingLabel.trim().toLowerCase();
|
|
3191
|
-
if (normalizedCurrentLabel && normalizedExisting === normalizedCurrentLabel) {
|
|
3192
|
-
return false;
|
|
3193
|
-
}
|
|
3194
|
-
return normalizedExisting === normalizedLabel;
|
|
3195
|
-
});
|
|
3196
|
-
if (isDuplicate) {
|
|
3197
|
-
return { isValid: false, errorMessage: ERROR_MESSAGES.DUPLICATE_NAME };
|
|
3198
|
-
}
|
|
3199
|
-
return { isValid: true, errorMessage: null };
|
|
3200
|
-
}
|
|
3201
|
-
|
|
3202
|
-
// src/extended/components/overridable-props/overridable-prop-form.tsx
|
|
3203
|
-
var SIZE = "tiny";
|
|
3204
|
-
var DEFAULT_GROUP = { value: null, label: __15("Default", "elementor") };
|
|
3205
|
-
function OverridablePropForm({ onSubmit, groups, currentValue, existingLabels = [], sx }) {
|
|
3206
|
-
const selectGroups = groups?.length ? groups : [DEFAULT_GROUP];
|
|
3207
|
-
const [propLabel, setPropLabel] = useState3(currentValue?.label ?? null);
|
|
3208
|
-
const [group, setGroup] = useState3(currentValue?.groupId ?? selectGroups[0]?.value ?? null);
|
|
3209
|
-
const [error, setError] = useState3(null);
|
|
3210
|
-
const name = __15("Name", "elementor");
|
|
3211
|
-
const groupName = __15("Group Name", "elementor");
|
|
3212
|
-
const isCreate = currentValue === void 0;
|
|
3213
|
-
const title = isCreate ? __15("Create new property", "elementor") : __15("Update property", "elementor");
|
|
3214
|
-
const ctaLabel = isCreate ? __15("Create", "elementor") : __15("Update", "elementor");
|
|
3215
|
-
const handleSubmit = () => {
|
|
3216
|
-
const validationResult = validatePropLabel(propLabel ?? "", existingLabels, currentValue?.label);
|
|
3217
|
-
if (!validationResult.isValid) {
|
|
3218
|
-
setError(validationResult.errorMessage);
|
|
3219
|
-
return;
|
|
3220
|
-
}
|
|
3221
|
-
onSubmit({ label: propLabel ?? "", group });
|
|
3222
|
-
};
|
|
3223
|
-
return /* @__PURE__ */ React22.createElement(Form, { onSubmit: handleSubmit, "data-testid": "overridable-prop-form" }, /* @__PURE__ */ React22.createElement(Stack14, { alignItems: "start", sx: { width: "268px", ...sx } }, /* @__PURE__ */ React22.createElement(
|
|
3224
|
-
Stack14,
|
|
3225
|
-
{
|
|
3226
|
-
direction: "row",
|
|
3227
|
-
alignItems: "center",
|
|
3228
|
-
py: 1,
|
|
3229
|
-
px: 1.5,
|
|
3230
|
-
sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%", mb: 1.5 }
|
|
3231
|
-
},
|
|
3232
|
-
/* @__PURE__ */ React22.createElement(Typography8, { variant: "caption", sx: { color: "text.primary", fontWeight: "500", lineHeight: 1 } }, title)
|
|
3233
|
-
), /* @__PURE__ */ React22.createElement(Grid, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React22.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React22.createElement(FormLabel, { size: "tiny" }, name)), /* @__PURE__ */ React22.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React22.createElement(
|
|
3234
|
-
TextField2,
|
|
3235
|
-
{
|
|
3236
|
-
name,
|
|
3237
|
-
size: SIZE,
|
|
3238
|
-
fullWidth: true,
|
|
3239
|
-
placeholder: __15("Enter value", "elementor"),
|
|
3240
|
-
value: propLabel ?? "",
|
|
3241
|
-
onChange: (e) => {
|
|
3242
|
-
const newValue = e.target.value;
|
|
3243
|
-
setPropLabel(newValue);
|
|
3244
|
-
const validationResult = validatePropLabel(
|
|
3245
|
-
newValue,
|
|
3246
|
-
existingLabels,
|
|
3247
|
-
currentValue?.label
|
|
3248
|
-
);
|
|
3249
|
-
setError(validationResult.errorMessage);
|
|
3250
|
-
},
|
|
3251
|
-
error: Boolean(error),
|
|
3252
|
-
helperText: error
|
|
3253
|
-
}
|
|
3254
|
-
))), /* @__PURE__ */ React22.createElement(Grid, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React22.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React22.createElement(FormLabel, { size: "tiny" }, groupName)), /* @__PURE__ */ React22.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React22.createElement(
|
|
3255
|
-
Select,
|
|
3256
|
-
{
|
|
3257
|
-
name: groupName,
|
|
3258
|
-
size: SIZE,
|
|
3259
|
-
fullWidth: true,
|
|
3260
|
-
value: group ?? null,
|
|
3261
|
-
onChange: (e) => setGroup(e.target.value),
|
|
3262
|
-
displayEmpty: true,
|
|
3263
|
-
renderValue: (selectedValue) => {
|
|
3264
|
-
if (!selectedValue) {
|
|
3265
|
-
return selectGroups[0].label;
|
|
3266
|
-
}
|
|
3267
|
-
return selectGroups.find(({ value }) => value === selectedValue)?.label ?? selectedValue;
|
|
3268
|
-
}
|
|
3269
|
-
},
|
|
3270
|
-
selectGroups.map(({ label: groupLabel, ...props }) => /* @__PURE__ */ React22.createElement(MenuListItem, { key: props.value, ...props, value: props.value ?? "" }, groupLabel))
|
|
3271
|
-
))), /* @__PURE__ */ React22.createElement(Stack14, { direction: "row", justifyContent: "flex-end", alignSelf: "end", mt: 1.5, py: 1, px: 1.5 }, /* @__PURE__ */ React22.createElement(
|
|
3272
|
-
Button4,
|
|
3273
|
-
{
|
|
3274
|
-
type: "submit",
|
|
3275
|
-
disabled: !propLabel || Boolean(error),
|
|
3276
|
-
variant: "contained",
|
|
3277
|
-
color: "primary",
|
|
3278
|
-
size: "small"
|
|
3279
|
-
},
|
|
3280
|
-
ctaLabel
|
|
3281
|
-
))));
|
|
3282
|
-
}
|
|
3283
|
-
|
|
3284
|
-
// src/extended/components/component-properties-panel/sortable.tsx
|
|
3285
|
-
import * as React23 from "react";
|
|
3286
|
-
import { GripVerticalIcon } from "@elementor/icons";
|
|
3287
|
-
import {
|
|
3288
|
-
Box as Box10,
|
|
3289
|
-
styled as styled2,
|
|
3290
|
-
UnstableSortableItem,
|
|
3291
|
-
UnstableSortableProvider
|
|
3292
|
-
} from "@elementor/ui";
|
|
3293
|
-
var SortableProvider = (props) => /* @__PURE__ */ React23.createElement(UnstableSortableProvider, { restrictAxis: true, variant: "static", dragPlaceholderStyle: { opacity: "1" }, ...props });
|
|
3294
|
-
var SortableTrigger = ({ triggerClassName, ...props }) => /* @__PURE__ */ React23.createElement(
|
|
3295
|
-
StyledSortableTrigger,
|
|
3296
|
-
{
|
|
3297
|
-
...props,
|
|
3298
|
-
role: "button",
|
|
3299
|
-
className: `sortable-trigger ${triggerClassName ?? ""}`.trim(),
|
|
3300
|
-
"aria-label": "sort"
|
|
3301
|
-
},
|
|
3302
|
-
/* @__PURE__ */ React23.createElement(GripVerticalIcon, { fontSize: "tiny" })
|
|
3303
|
-
);
|
|
3304
|
-
var SortableItem = ({ children, id: id2 }) => /* @__PURE__ */ React23.createElement(
|
|
3305
|
-
UnstableSortableItem,
|
|
3306
|
-
{
|
|
3307
|
-
id: id2,
|
|
3308
|
-
render: ({
|
|
3309
|
-
itemProps,
|
|
3310
|
-
isDragged,
|
|
3311
|
-
triggerProps,
|
|
3312
|
-
itemStyle,
|
|
3313
|
-
triggerStyle,
|
|
3314
|
-
dropIndicationStyle,
|
|
3315
|
-
showDropIndication,
|
|
3316
|
-
isDragOverlay,
|
|
3317
|
-
isDragPlaceholder
|
|
3318
|
-
}) => /* @__PURE__ */ React23.createElement(
|
|
3319
|
-
Box10,
|
|
3320
|
-
{
|
|
3321
|
-
...itemProps,
|
|
3322
|
-
style: itemStyle,
|
|
3323
|
-
component: "div",
|
|
3324
|
-
role: "listitem",
|
|
3325
|
-
sx: {
|
|
3326
|
-
backgroundColor: isDragOverlay ? "background.paper" : void 0
|
|
3327
|
-
}
|
|
3328
|
-
},
|
|
3329
|
-
children({
|
|
3330
|
-
isDragged,
|
|
3331
|
-
isDragPlaceholder,
|
|
3332
|
-
triggerProps,
|
|
3333
|
-
triggerStyle
|
|
3334
|
-
}),
|
|
3335
|
-
showDropIndication && /* @__PURE__ */ React23.createElement(SortableItemIndicator, { style: dropIndicationStyle })
|
|
3336
|
-
)
|
|
3337
|
-
}
|
|
3338
|
-
);
|
|
3339
|
-
var StyledSortableTrigger = styled2("div")(({ theme }) => ({
|
|
3340
|
-
position: "absolute",
|
|
3341
|
-
left: "-2px",
|
|
3342
|
-
top: "50%",
|
|
3343
|
-
transform: `translate( -${theme.spacing(1.5)}, -50% )`,
|
|
3344
|
-
color: theme.palette.action.active,
|
|
3345
|
-
cursor: "grab"
|
|
3346
|
-
}));
|
|
3347
|
-
var SortableItemIndicator = styled2(Box10)`
|
|
3348
|
-
width: 100%;
|
|
3349
|
-
height: 1px;
|
|
3350
|
-
background-color: ${({ theme }) => theme.palette.text.primary};
|
|
3351
|
-
`;
|
|
3352
|
-
|
|
3353
|
-
// src/extended/components/component-properties-panel/property-item.tsx
|
|
3354
|
-
function PropertyItem({
|
|
3355
|
-
prop,
|
|
3356
|
-
sortableTriggerProps,
|
|
3357
|
-
isDragPlaceholder,
|
|
3358
|
-
groups,
|
|
3359
|
-
existingLabels,
|
|
3360
|
-
onDelete,
|
|
3361
|
-
onUpdate
|
|
3362
|
-
}) {
|
|
3363
|
-
const popoverState = usePopupState({
|
|
3364
|
-
variant: "popover"
|
|
3365
|
-
});
|
|
3366
|
-
const icon = getElementIcon(prop);
|
|
3367
|
-
const popoverProps = bindPopover(popoverState);
|
|
3368
|
-
const handleSubmit = (data) => {
|
|
3369
|
-
onUpdate(data);
|
|
3370
|
-
popoverState.close();
|
|
3371
|
-
};
|
|
3372
|
-
const handleDelete = (event) => {
|
|
3373
|
-
event.stopPropagation();
|
|
3374
|
-
onDelete(prop.overrideKey);
|
|
3375
|
-
};
|
|
3376
|
-
return /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement(
|
|
3377
|
-
Box11,
|
|
3378
|
-
{
|
|
3379
|
-
...bindTrigger(popoverState),
|
|
3380
|
-
sx: {
|
|
3381
|
-
position: "relative",
|
|
3382
|
-
pl: 0.5,
|
|
3383
|
-
pr: 1,
|
|
3384
|
-
py: 0.25,
|
|
3385
|
-
minHeight: 28,
|
|
3386
|
-
borderRadius: 1,
|
|
3387
|
-
border: "1px solid",
|
|
3388
|
-
borderColor: "divider",
|
|
3389
|
-
display: "flex",
|
|
3390
|
-
alignItems: "center",
|
|
3391
|
-
gap: 0.5,
|
|
3392
|
-
opacity: isDragPlaceholder ? 0.5 : 1,
|
|
3393
|
-
cursor: "pointer",
|
|
3394
|
-
"&:hover": {
|
|
3395
|
-
backgroundColor: "action.hover"
|
|
3396
|
-
},
|
|
3397
|
-
"&:hover .sortable-trigger": {
|
|
3398
|
-
visibility: "visible"
|
|
3399
|
-
},
|
|
3400
|
-
"& .sortable-trigger": {
|
|
3401
|
-
visibility: "hidden"
|
|
3402
|
-
},
|
|
3403
|
-
"&:hover .delete-button": {
|
|
3404
|
-
visibility: "visible"
|
|
3405
|
-
},
|
|
3406
|
-
"& .delete-button": {
|
|
3407
|
-
visibility: "hidden"
|
|
3408
|
-
}
|
|
3409
|
-
}
|
|
3410
|
-
},
|
|
3411
|
-
/* @__PURE__ */ React24.createElement(SortableTrigger, { ...sortableTriggerProps }),
|
|
3412
|
-
/* @__PURE__ */ React24.createElement(
|
|
3413
|
-
Box11,
|
|
3414
|
-
{
|
|
3415
|
-
sx: { display: "flex", alignItems: "center", color: "text.primary", fontSize: 12, padding: 0.25 }
|
|
3416
|
-
},
|
|
3417
|
-
/* @__PURE__ */ React24.createElement("i", { className: icon })
|
|
3418
|
-
),
|
|
3419
|
-
/* @__PURE__ */ React24.createElement(Typography9, { variant: "caption", sx: { color: "text.primary", flexGrow: 1, fontSize: 10 } }, prop.label),
|
|
3420
|
-
/* @__PURE__ */ React24.createElement(IconButton2, { size: "tiny", onClick: handleDelete, "aria-label": "Delete property", sx: { p: 0.25 } }, /* @__PURE__ */ React24.createElement(XIcon, { fontSize: "tiny" }))
|
|
3421
|
-
), /* @__PURE__ */ React24.createElement(
|
|
3422
|
-
Popover2,
|
|
3423
|
-
{
|
|
3424
|
-
...popoverProps,
|
|
3425
|
-
anchorOrigin: { vertical: "bottom", horizontal: "left" },
|
|
3426
|
-
transformOrigin: { vertical: "top", horizontal: "left" },
|
|
3427
|
-
PaperProps: { sx: { width: popoverState.anchorEl?.getBoundingClientRect().width } }
|
|
3428
|
-
},
|
|
3429
|
-
/* @__PURE__ */ React24.createElement(
|
|
3430
|
-
OverridablePropForm,
|
|
3431
|
-
{
|
|
3432
|
-
onSubmit: handleSubmit,
|
|
3433
|
-
currentValue: prop,
|
|
3434
|
-
groups,
|
|
3435
|
-
existingLabels,
|
|
3436
|
-
sx: { width: "100%" }
|
|
3437
|
-
}
|
|
3438
|
-
)
|
|
3439
|
-
));
|
|
3440
|
-
}
|
|
3441
|
-
function getElementIcon(prop) {
|
|
3442
|
-
const elType = prop.elType === "widget" ? prop.widgetType : prop.elType;
|
|
3443
|
-
const widgetsCache = getWidgetsCache2();
|
|
3444
|
-
if (!widgetsCache) {
|
|
3445
|
-
return "eicon-apps";
|
|
3446
|
-
}
|
|
3447
|
-
const widgetConfig = widgetsCache[elType];
|
|
3448
|
-
return widgetConfig?.icon || "eicon-apps";
|
|
3449
|
-
}
|
|
3450
|
-
|
|
3451
|
-
// src/extended/components/component-properties-panel/properties-group.tsx
|
|
3452
|
-
function PropertiesGroup({
|
|
3453
|
-
group,
|
|
3454
|
-
props,
|
|
3455
|
-
allGroups,
|
|
3456
|
-
sortableTriggerProps,
|
|
3457
|
-
isDragPlaceholder,
|
|
3458
|
-
onPropsReorder,
|
|
3459
|
-
onPropertyDelete,
|
|
3460
|
-
onPropertyUpdate,
|
|
3461
|
-
onGroupDelete,
|
|
3462
|
-
editableLabelProps
|
|
3463
|
-
}) {
|
|
3464
|
-
const groupProps = group.props.map((propId) => props[propId]).filter((prop) => Boolean(prop));
|
|
3465
|
-
const popupState = usePopupState2({
|
|
3466
|
-
variant: "popover",
|
|
3467
|
-
disableAutoFocus: true
|
|
3468
|
-
});
|
|
3469
|
-
const { editableRef, isEditing, error, getEditableProps, setEditingGroupId, editingGroupId } = editableLabelProps;
|
|
3470
|
-
const hasProperties = group.props.length > 0;
|
|
3471
|
-
const isThisGroupEditing = isEditing && editingGroupId === group.id;
|
|
3472
|
-
const handleRenameClick = () => {
|
|
3473
|
-
popupState.close();
|
|
3474
|
-
setEditingGroupId(group.id);
|
|
3475
|
-
};
|
|
3476
|
-
const handleDeleteClick = () => {
|
|
3477
|
-
popupState.close();
|
|
3478
|
-
onGroupDelete(group.id);
|
|
3479
|
-
};
|
|
3480
|
-
return /* @__PURE__ */ React25.createElement(
|
|
3481
|
-
Box12,
|
|
3482
|
-
{
|
|
3483
|
-
sx: {
|
|
3484
|
-
opacity: isDragPlaceholder ? 0.5 : 1
|
|
3485
|
-
}
|
|
3486
|
-
},
|
|
3487
|
-
/* @__PURE__ */ React25.createElement(Stack15, { gap: 1 }, /* @__PURE__ */ React25.createElement(
|
|
3488
|
-
Box12,
|
|
3489
|
-
{
|
|
3490
|
-
className: "group-header",
|
|
3491
|
-
sx: {
|
|
3492
|
-
position: "relative",
|
|
3493
|
-
"&:hover .group-sortable-trigger": {
|
|
3494
|
-
visibility: "visible"
|
|
3495
|
-
},
|
|
3496
|
-
"& .group-sortable-trigger": {
|
|
3497
|
-
visibility: "hidden"
|
|
3498
|
-
},
|
|
3499
|
-
"&:hover .group-menu": {
|
|
3500
|
-
visibility: "visible"
|
|
3501
|
-
},
|
|
3502
|
-
"& .group-menu": {
|
|
3503
|
-
visibility: "hidden"
|
|
3504
|
-
}
|
|
3505
|
-
}
|
|
3506
|
-
},
|
|
3507
|
-
/* @__PURE__ */ React25.createElement(SortableTrigger, { triggerClassName: "group-sortable-trigger", ...sortableTriggerProps }),
|
|
3508
|
-
/* @__PURE__ */ React25.createElement(Stack15, { direction: "row", alignItems: "center", justifyContent: "space-between", gap: 2 }, isThisGroupEditing ? /* @__PURE__ */ React25.createElement(
|
|
3509
|
-
Box12,
|
|
3510
|
-
{
|
|
3511
|
-
sx: {
|
|
3512
|
-
height: 28,
|
|
3513
|
-
display: "flex",
|
|
3514
|
-
alignItems: "center",
|
|
3515
|
-
border: 2,
|
|
3516
|
-
borderColor: "text.secondary",
|
|
3517
|
-
borderRadius: 1,
|
|
3518
|
-
pl: 0.5,
|
|
3519
|
-
flexGrow: 1,
|
|
3520
|
-
overflow: "hidden",
|
|
3521
|
-
textOverflow: "ellipsis",
|
|
3522
|
-
whiteSpace: "nowrap",
|
|
3523
|
-
width: "100%"
|
|
3524
|
-
}
|
|
3525
|
-
},
|
|
3526
|
-
/* @__PURE__ */ React25.createElement(
|
|
3527
|
-
EditableField2,
|
|
3528
|
-
{
|
|
3529
|
-
ref: editableRef,
|
|
3530
|
-
as: Typography10,
|
|
3531
|
-
variant: "caption",
|
|
3532
|
-
error: error ?? void 0,
|
|
3533
|
-
sx: { color: "text.primary", fontWeight: 400, lineHeight: 1.66 },
|
|
3534
|
-
...getEditableProps()
|
|
3535
|
-
}
|
|
3536
|
-
)
|
|
3537
|
-
) : /* @__PURE__ */ React25.createElement(
|
|
3538
|
-
EllipsisWithTooltip3,
|
|
3539
|
-
{
|
|
3540
|
-
title: group.label,
|
|
3541
|
-
as: Typography10,
|
|
3542
|
-
variant: "caption",
|
|
3543
|
-
sx: { color: "text.primary", fontWeight: 400, lineHeight: 1.66 }
|
|
3544
|
-
}
|
|
3545
|
-
), /* @__PURE__ */ React25.createElement(
|
|
3546
|
-
IconButton3,
|
|
3547
|
-
{
|
|
3548
|
-
className: "group-menu",
|
|
3549
|
-
size: "tiny",
|
|
3550
|
-
sx: { p: 0.25, visibility: isThisGroupEditing ? "visible" : void 0 },
|
|
3551
|
-
"aria-label": __16("Group actions", "elementor"),
|
|
3552
|
-
...bindTrigger2(popupState)
|
|
3553
|
-
},
|
|
3554
|
-
/* @__PURE__ */ React25.createElement(DotsVerticalIcon, { fontSize: "tiny" })
|
|
3555
|
-
))
|
|
3556
|
-
), /* @__PURE__ */ React25.createElement(List2, { sx: { p: 0, display: "flex", flexDirection: "column", gap: 1 } }, /* @__PURE__ */ React25.createElement(SortableProvider, { value: group.props, onChange: onPropsReorder }, groupProps.map((prop) => /* @__PURE__ */ React25.createElement(SortableItem, { key: prop.overrideKey, id: prop.overrideKey }, ({ triggerProps, triggerStyle, isDragPlaceholder: isItemDragPlaceholder }) => /* @__PURE__ */ React25.createElement(
|
|
3557
|
-
PropertyItem,
|
|
3558
|
-
{
|
|
3559
|
-
prop,
|
|
3560
|
-
sortableTriggerProps: { ...triggerProps, style: triggerStyle },
|
|
3561
|
-
isDragPlaceholder: isItemDragPlaceholder,
|
|
3562
|
-
groups: allGroups,
|
|
3563
|
-
existingLabels: Object.values(props).map((p) => p.label),
|
|
3564
|
-
onDelete: onPropertyDelete,
|
|
3565
|
-
onUpdate: (data) => onPropertyUpdate(prop.overrideKey, data)
|
|
3566
|
-
}
|
|
3567
|
-
)))))),
|
|
3568
|
-
/* @__PURE__ */ React25.createElement(
|
|
3569
|
-
Menu,
|
|
3570
|
-
{
|
|
3571
|
-
...bindMenu(popupState),
|
|
3572
|
-
anchorOrigin: { vertical: "bottom", horizontal: "right" },
|
|
3573
|
-
transformOrigin: { vertical: "top", horizontal: "right" }
|
|
3574
|
-
},
|
|
3575
|
-
/* @__PURE__ */ React25.createElement(MenuListItem2, { sx: { minWidth: "160px" }, onClick: handleRenameClick }, /* @__PURE__ */ React25.createElement(Typography10, { variant: "caption", sx: { color: "text.primary" } }, __16("Rename", "elementor"))),
|
|
3576
|
-
/* @__PURE__ */ React25.createElement(
|
|
3577
|
-
Tooltip2,
|
|
3578
|
-
{
|
|
3579
|
-
title: hasProperties ? __16("To delete the group, first remove all the properties", "elementor") : "",
|
|
3580
|
-
placement: "right"
|
|
3581
|
-
},
|
|
3582
|
-
/* @__PURE__ */ React25.createElement("span", null, /* @__PURE__ */ React25.createElement(MenuListItem2, { onClick: handleDeleteClick, disabled: hasProperties }, /* @__PURE__ */ React25.createElement(
|
|
3583
|
-
Typography10,
|
|
3584
|
-
{
|
|
3585
|
-
variant: "caption",
|
|
3586
|
-
sx: { color: hasProperties ? "text.disabled" : "error.light" }
|
|
3587
|
-
},
|
|
3588
|
-
__16("Delete", "elementor")
|
|
3589
|
-
)))
|
|
3590
|
-
)
|
|
3591
|
-
)
|
|
3592
|
-
);
|
|
3593
|
-
}
|
|
3594
|
-
|
|
3595
|
-
// src/extended/components/component-properties-panel/use-current-editable-item.ts
|
|
3596
|
-
import { useState as useState4 } from "react";
|
|
3597
|
-
import { setDocumentModifiedStatus as setDocumentModifiedStatus2 } from "@elementor/editor-documents";
|
|
3598
|
-
import { useEditable } from "@elementor/editor-ui";
|
|
3599
|
-
import { __ as __18 } from "@wordpress/i18n";
|
|
3600
|
-
|
|
3601
|
-
// src/extended/store/actions/rename-overridable-group.ts
|
|
3602
|
-
function renameOverridableGroup({ componentId, groupId, label }) {
|
|
3603
|
-
const overridableProps = componentsSelectors.getOverridableProps(componentId);
|
|
3604
|
-
if (!overridableProps) {
|
|
3605
|
-
return false;
|
|
3606
|
-
}
|
|
3607
|
-
const group = overridableProps.groups.items[groupId];
|
|
3608
|
-
if (!group) {
|
|
3609
|
-
return false;
|
|
3610
|
-
}
|
|
3611
|
-
const updatedGroups = renameGroup(overridableProps.groups, groupId, label);
|
|
3612
|
-
componentsActions.setOverridableProps(componentId, {
|
|
3613
|
-
...overridableProps,
|
|
3614
|
-
groups: updatedGroups
|
|
3615
|
-
});
|
|
3616
|
-
return true;
|
|
3617
|
-
}
|
|
3618
|
-
|
|
3619
|
-
// src/extended/components/component-properties-panel/utils/validate-group-label.ts
|
|
3620
|
-
import { __ as __17 } from "@wordpress/i18n";
|
|
3621
|
-
var ERROR_MESSAGES2 = {
|
|
3622
|
-
EMPTY_NAME: __17("Group name is required", "elementor"),
|
|
3623
|
-
DUPLICATE_NAME: __17("Group name already exists", "elementor")
|
|
3624
|
-
};
|
|
3625
|
-
function validateGroupLabel(label, existingGroups) {
|
|
3626
|
-
const trimmedLabel = label.trim();
|
|
3627
|
-
if (!trimmedLabel) {
|
|
3628
|
-
return ERROR_MESSAGES2.EMPTY_NAME;
|
|
3629
|
-
}
|
|
3630
|
-
const isDuplicate = Object.values(existingGroups).some((group) => group.label === trimmedLabel);
|
|
3631
|
-
if (isDuplicate) {
|
|
3632
|
-
return ERROR_MESSAGES2.DUPLICATE_NAME;
|
|
3633
|
-
}
|
|
3634
|
-
return "";
|
|
3635
|
-
}
|
|
3636
|
-
|
|
3637
|
-
// src/extended/components/component-properties-panel/use-current-editable-item.ts
|
|
3638
|
-
function useCurrentEditableItem() {
|
|
3639
|
-
const [editingGroupId, setEditingGroupId] = useState4(null);
|
|
3640
|
-
const currentComponentId = useCurrentComponentId();
|
|
3641
|
-
const overridableProps = useOverridableProps(currentComponentId);
|
|
3642
|
-
const allGroupsRecord = overridableProps?.groups?.items ?? {};
|
|
3643
|
-
const currentGroup = editingGroupId ? allGroupsRecord[editingGroupId] : null;
|
|
3644
|
-
const validateLabel = (newLabel) => {
|
|
3645
|
-
const otherGroups = Object.fromEntries(
|
|
3646
|
-
Object.entries(allGroupsRecord).filter(([id2]) => id2 !== editingGroupId)
|
|
3647
|
-
);
|
|
3648
|
-
return validateGroupLabel(newLabel, otherGroups) || null;
|
|
3649
|
-
};
|
|
3650
|
-
const handleSubmit = (newLabel) => {
|
|
3651
|
-
if (!editingGroupId || !currentComponentId) {
|
|
3652
|
-
throw new Error(__18("Group ID or component ID is missing", "elementor"));
|
|
3653
|
-
}
|
|
3654
|
-
renameOverridableGroup({
|
|
3655
|
-
componentId: currentComponentId,
|
|
3656
|
-
groupId: editingGroupId,
|
|
3657
|
-
label: newLabel
|
|
3658
|
-
});
|
|
3659
|
-
setDocumentModifiedStatus2(true);
|
|
3660
|
-
};
|
|
3661
|
-
const {
|
|
3662
|
-
ref: editableRef,
|
|
3663
|
-
openEditMode,
|
|
3664
|
-
isEditing,
|
|
3665
|
-
error,
|
|
3666
|
-
getProps: getEditableProps
|
|
3667
|
-
} = useEditable({
|
|
3668
|
-
value: currentGroup?.label ?? "",
|
|
3669
|
-
onSubmit: handleSubmit,
|
|
3670
|
-
validation: validateLabel
|
|
3671
|
-
});
|
|
3672
|
-
return {
|
|
3673
|
-
editableRef,
|
|
3674
|
-
isEditing,
|
|
3675
|
-
error,
|
|
3676
|
-
getEditableProps,
|
|
3677
|
-
setEditingGroupId: (groupId) => {
|
|
3678
|
-
setEditingGroupId(groupId);
|
|
3679
|
-
openEditMode();
|
|
3680
|
-
},
|
|
3681
|
-
editingGroupId
|
|
3682
|
-
};
|
|
3683
|
-
}
|
|
3684
|
-
|
|
3685
|
-
// src/extended/components/component-properties-panel/utils/generate-unique-label.ts
|
|
3686
|
-
var DEFAULT_NEW_GROUP_LABEL = "New group";
|
|
3687
|
-
function generateUniqueLabel(groups) {
|
|
3688
|
-
const existingLabels = new Set(groups.map((group) => group.label));
|
|
3689
|
-
if (!existingLabels.has(DEFAULT_NEW_GROUP_LABEL)) {
|
|
3690
|
-
return DEFAULT_NEW_GROUP_LABEL;
|
|
3691
|
-
}
|
|
3692
|
-
let index = 1;
|
|
3693
|
-
let newLabel = `${DEFAULT_NEW_GROUP_LABEL}-${index}`;
|
|
3694
|
-
while (existingLabels.has(newLabel)) {
|
|
3695
|
-
index++;
|
|
3696
|
-
newLabel = `${DEFAULT_NEW_GROUP_LABEL}-${index}`;
|
|
3697
|
-
}
|
|
3698
|
-
return newLabel;
|
|
3699
|
-
}
|
|
3700
|
-
|
|
3701
|
-
// src/extended/components/component-properties-panel/component-properties-panel-content.tsx
|
|
3702
|
-
function ComponentPropertiesPanelContent({ onClose }) {
|
|
3703
|
-
const currentComponentId = useCurrentComponentId();
|
|
3704
|
-
const overridableProps = useSanitizeOverridableProps(currentComponentId);
|
|
3705
|
-
const [isAddingGroup, setIsAddingGroup] = useState5(false);
|
|
3706
|
-
const introductionRef = useRef(null);
|
|
3707
|
-
const groupLabelEditable = useCurrentEditableItem();
|
|
3708
|
-
const groups = useMemo(() => {
|
|
3709
|
-
if (!overridableProps) {
|
|
3710
|
-
return [];
|
|
3711
|
-
}
|
|
3712
|
-
return overridableProps.groups.order.map((groupId) => overridableProps.groups.items[groupId] ?? null).filter(Boolean);
|
|
3713
|
-
}, [overridableProps]);
|
|
3714
|
-
const allGroupsForSelect = useMemo(
|
|
3715
|
-
() => groups.map((group) => ({ value: group.id, label: group.label })),
|
|
3716
|
-
[groups]
|
|
3717
|
-
);
|
|
3718
|
-
if (!currentComponentId || !overridableProps) {
|
|
3719
|
-
return null;
|
|
3720
|
-
}
|
|
3721
|
-
const hasGroups = groups.length > 0;
|
|
3722
|
-
const showEmptyState = !hasGroups && !isAddingGroup;
|
|
3723
|
-
const groupIds = overridableProps.groups.order;
|
|
3724
|
-
const handleAddGroupClick = () => {
|
|
3725
|
-
if (isAddingGroup) {
|
|
3726
|
-
return;
|
|
3727
|
-
}
|
|
3728
|
-
const newGroupId = generateUniqueId2("group");
|
|
3729
|
-
const newLabel = generateUniqueLabel(groups);
|
|
3730
|
-
addOverridableGroup({
|
|
3731
|
-
componentId: currentComponentId,
|
|
3732
|
-
groupId: newGroupId,
|
|
3733
|
-
label: newLabel,
|
|
3734
|
-
source: "user"
|
|
3735
|
-
});
|
|
3736
|
-
setDocumentModifiedStatus3(true);
|
|
3737
|
-
setIsAddingGroup(false);
|
|
3738
|
-
groupLabelEditable.setEditingGroupId(newGroupId);
|
|
3739
|
-
};
|
|
3740
|
-
const handleGroupsReorder = (newOrder) => {
|
|
3741
|
-
reorderOverridableGroups({ componentId: currentComponentId, newOrder });
|
|
3742
|
-
setDocumentModifiedStatus3(true);
|
|
3743
|
-
};
|
|
3744
|
-
const handlePropsReorder = (groupId, newPropsOrder) => {
|
|
3745
|
-
reorderGroupProps({ componentId: currentComponentId, groupId, newPropsOrder });
|
|
3746
|
-
setDocumentModifiedStatus3(true);
|
|
3747
|
-
};
|
|
3748
|
-
const handlePropertyDelete = (propKey) => {
|
|
3749
|
-
deleteOverridableProp({ componentId: currentComponentId, propKey, source: "user" });
|
|
3750
|
-
setDocumentModifiedStatus3(true);
|
|
3751
|
-
};
|
|
3752
|
-
const handlePropertyUpdate = (overrideKey, data) => {
|
|
3753
|
-
updateOverridablePropParams({
|
|
3754
|
-
componentId: currentComponentId,
|
|
3755
|
-
overrideKey,
|
|
3756
|
-
label: data.label,
|
|
3757
|
-
groupId: data.group
|
|
3758
|
-
});
|
|
3759
|
-
setDocumentModifiedStatus3(true);
|
|
3760
|
-
};
|
|
3761
|
-
const handleGroupDelete = (groupId) => {
|
|
3762
|
-
deleteOverridableGroup({ componentId: currentComponentId, groupId });
|
|
3763
|
-
setDocumentModifiedStatus3(true);
|
|
3764
|
-
};
|
|
3765
|
-
return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(PanelHeader2, { sx: { justifyContent: "start", pl: 1.5, pr: 1, py: 1 } }, /* @__PURE__ */ React26.createElement(Stack16, { direction: "row", alignItems: "center", gap: 0.5, flexGrow: 1 }, /* @__PURE__ */ React26.createElement(ComponentPropListIcon3, { fontSize: "tiny" }), /* @__PURE__ */ React26.createElement(PanelHeaderTitle2, { variant: "subtitle2" }, __19("Component properties", "elementor"))), !showEmptyState && /* @__PURE__ */ React26.createElement(Tooltip3, { title: __19("Add new group", "elementor") }, /* @__PURE__ */ React26.createElement(
|
|
3766
|
-
IconButton4,
|
|
3767
|
-
{
|
|
3768
|
-
size: "tiny",
|
|
3769
|
-
"aria-label": __19("Add new group", "elementor"),
|
|
3770
|
-
onClick: handleAddGroupClick
|
|
3771
|
-
},
|
|
3772
|
-
/* @__PURE__ */ React26.createElement(FolderPlusIcon, { fontSize: "tiny" })
|
|
3773
|
-
)), /* @__PURE__ */ React26.createElement(Tooltip3, { title: __19("Close panel", "elementor") }, /* @__PURE__ */ React26.createElement(
|
|
3774
|
-
IconButton4,
|
|
3775
|
-
{
|
|
3776
|
-
ref: introductionRef,
|
|
3777
|
-
size: "tiny",
|
|
3778
|
-
"aria-label": __19("Close panel", "elementor"),
|
|
3779
|
-
onClick: onClose
|
|
3780
|
-
},
|
|
3781
|
-
/* @__PURE__ */ React26.createElement(XIcon2, { fontSize: "tiny" })
|
|
3782
|
-
))), /* @__PURE__ */ React26.createElement(Divider3, null), /* @__PURE__ */ React26.createElement(PanelBody2, null, showEmptyState ? /* @__PURE__ */ React26.createElement(PropertiesEmptyState, { introductionRef }) : /* @__PURE__ */ React26.createElement(List3, { sx: { p: 2, display: "flex", flexDirection: "column", gap: 2 } }, /* @__PURE__ */ React26.createElement(SortableProvider, { value: groupIds, onChange: handleGroupsReorder }, groups.map((group) => /* @__PURE__ */ React26.createElement(SortableItem, { key: group.id, id: group.id }, ({ triggerProps, triggerStyle, isDragPlaceholder }) => /* @__PURE__ */ React26.createElement(
|
|
3783
|
-
PropertiesGroup,
|
|
3784
|
-
{
|
|
3785
|
-
group,
|
|
3786
|
-
props: overridableProps.props,
|
|
3787
|
-
allGroups: allGroupsForSelect,
|
|
3788
|
-
allGroupsRecord: overridableProps.groups.items,
|
|
3789
|
-
sortableTriggerProps: { ...triggerProps, style: triggerStyle },
|
|
3790
|
-
isDragPlaceholder,
|
|
3791
|
-
setIsAddingGroup,
|
|
3792
|
-
onPropsReorder: (newOrder) => handlePropsReorder(group.id, newOrder),
|
|
3793
|
-
onPropertyDelete: handlePropertyDelete,
|
|
3794
|
-
onPropertyUpdate: handlePropertyUpdate,
|
|
3795
|
-
editableLabelProps: groupLabelEditable,
|
|
3796
|
-
onGroupDelete: handleGroupDelete
|
|
3797
|
-
}
|
|
3798
|
-
)))))));
|
|
3799
|
-
}
|
|
3800
|
-
|
|
3801
|
-
// src/extended/components/component-properties-panel/component-properties-panel.tsx
|
|
3802
|
-
var id = "component-properties-panel";
|
|
3803
|
-
var { panel, usePanelActions } = createPanel({
|
|
3804
|
-
id,
|
|
3805
|
-
component: ComponentPropertiesPanel
|
|
3806
|
-
});
|
|
3807
|
-
function ComponentPropertiesPanel() {
|
|
3808
|
-
const { close: closePanel } = usePanelActions();
|
|
3809
|
-
const { open: openEditingPanel } = useEditingPanelActions();
|
|
3810
|
-
return /* @__PURE__ */ React27.createElement(ThemeProvider2, null, /* @__PURE__ */ React27.createElement(ErrorBoundary, { fallback: /* @__PURE__ */ React27.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React27.createElement(Panel, null, /* @__PURE__ */ React27.createElement(
|
|
3811
|
-
ComponentPropertiesPanelContent,
|
|
3812
|
-
{
|
|
3813
|
-
onClose: () => {
|
|
3814
|
-
closePanel();
|
|
3815
|
-
openEditingPanel();
|
|
3816
|
-
}
|
|
3817
|
-
}
|
|
3818
|
-
))));
|
|
3819
|
-
}
|
|
3820
|
-
var ErrorBoundaryFallback = () => /* @__PURE__ */ React27.createElement(Box13, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React27.createElement(Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React27.createElement("strong", null, __20("Something went wrong", "elementor"))));
|
|
3821
|
-
|
|
3822
|
-
// src/extended/components/component-panel-header/component-badge.tsx
|
|
3823
|
-
import * as React28 from "react";
|
|
3824
|
-
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
3825
|
-
import { ComponentPropListIcon as ComponentPropListIcon4 } from "@elementor/icons";
|
|
3826
|
-
import { Badge, Box as Box14, keyframes, styled as styled3, ToggleButton, Tooltip as Tooltip4 } from "@elementor/ui";
|
|
3827
|
-
import { __ as __21 } from "@wordpress/i18n";
|
|
3828
|
-
var ComponentsBadge = React28.forwardRef(({ overridablePropsCount, onClick }, ref) => {
|
|
3829
|
-
const prevCount = usePrevious(overridablePropsCount);
|
|
3830
|
-
const isFirstExposedProperty = prevCount === 0 && overridablePropsCount === 1;
|
|
3831
|
-
return /* @__PURE__ */ React28.createElement(
|
|
3832
|
-
StyledBadge,
|
|
3833
|
-
{
|
|
3834
|
-
ref,
|
|
3835
|
-
color: "primary",
|
|
3836
|
-
key: overridablePropsCount,
|
|
3837
|
-
invisible: overridablePropsCount === 0,
|
|
3838
|
-
animate: isFirstExposedProperty,
|
|
3839
|
-
anchorOrigin: { vertical: "top", horizontal: "right" },
|
|
3840
|
-
badgeContent: /* @__PURE__ */ React28.createElement(Box14, { sx: { animation: !isFirstExposedProperty ? `${slideUp} 300ms ease-out` : "none" } }, overridablePropsCount)
|
|
3841
|
-
},
|
|
3842
|
-
/* @__PURE__ */ React28.createElement(Tooltip4, { title: __21("Component properties", "elementor") }, /* @__PURE__ */ React28.createElement(
|
|
3843
|
-
ToggleButton,
|
|
3844
|
-
{
|
|
3845
|
-
value: "exposed properties",
|
|
3846
|
-
size: "tiny",
|
|
3847
|
-
onClick,
|
|
3848
|
-
"aria-label": __21("Component properties", "elementor")
|
|
3849
|
-
},
|
|
3850
|
-
/* @__PURE__ */ React28.createElement(ComponentPropListIcon4, { fontSize: "tiny" })
|
|
3851
|
-
))
|
|
3852
|
-
);
|
|
3853
|
-
});
|
|
3854
|
-
var StyledBadge = styled3(Badge, { shouldForwardProp: (prop) => prop !== "animate" })(
|
|
3855
|
-
({ theme, animate }) => ({
|
|
3856
|
-
"& .MuiBadge-badge": {
|
|
3857
|
-
minWidth: theme.spacing(2),
|
|
3858
|
-
height: theme.spacing(2),
|
|
3859
|
-
minHeight: theme.spacing(2),
|
|
3860
|
-
maxWidth: theme.spacing(2),
|
|
3861
|
-
fontSize: theme.typography.caption.fontSize,
|
|
3862
|
-
animation: animate ? `${bounceIn} 300ms ease-out` : "none"
|
|
3863
|
-
}
|
|
3864
|
-
})
|
|
3865
|
-
);
|
|
3866
|
-
function usePrevious(value) {
|
|
3867
|
-
const ref = useRef2(value);
|
|
3868
|
-
useEffect2(() => {
|
|
3869
|
-
ref.current = value;
|
|
3870
|
-
}, [value]);
|
|
3871
|
-
return ref.current;
|
|
3872
|
-
}
|
|
3873
|
-
var bounceIn = keyframes`
|
|
3874
|
-
0% { transform: scale(0) translate(50%, 50%); opacity: 0; }
|
|
3875
|
-
70% { transform: scale(1.1) translate(50%, -50%); opacity: 1; }
|
|
3876
|
-
100% { transform: scale(1) translate(50%, -50%); opacity: 1; }
|
|
3877
|
-
`;
|
|
3878
|
-
var slideUp = keyframes`
|
|
3879
|
-
from { transform: translateY(100%); opacity: 0; }
|
|
3880
|
-
to { transform: translateY(0); opacity: 1; }
|
|
3881
|
-
`;
|
|
3882
|
-
|
|
3883
|
-
// src/extended/components/component-panel-header/component-panel-header.tsx
|
|
3884
|
-
var MESSAGE_KEY = "components-properties-introduction";
|
|
3885
|
-
var ComponentPanelHeader = () => {
|
|
3886
|
-
const { id: currentComponentId, uid: componentUid } = useCurrentComponent() ?? { id: null, uid: null };
|
|
3887
|
-
const overridableProps = useSanitizeOverridableProps(currentComponentId);
|
|
3888
|
-
const onBack = useNavigateBack();
|
|
3889
|
-
const componentName = getComponentName();
|
|
3890
|
-
const [isMessageSuppressed, suppressMessage] = useSuppressedMessage(MESSAGE_KEY);
|
|
3891
|
-
const [shouldShowIntroduction, setShouldShowIntroduction] = React29.useState(!isMessageSuppressed);
|
|
3892
|
-
const { open: openPropertiesPanel } = usePanelActions();
|
|
3893
|
-
const overridablePropsCount = overridableProps ? Object.keys(overridableProps.props).length : 0;
|
|
3894
|
-
const anchorRef = React29.useRef(null);
|
|
3895
|
-
if (!currentComponentId) {
|
|
3896
|
-
return null;
|
|
3897
|
-
}
|
|
3898
|
-
const handleCloseIntroduction = () => {
|
|
3899
|
-
suppressMessage();
|
|
3900
|
-
setShouldShowIntroduction(false);
|
|
3901
|
-
};
|
|
3902
|
-
const handleOpenPropertiesPanel = () => {
|
|
3903
|
-
openPropertiesPanel();
|
|
3904
|
-
trackComponentEvent({
|
|
3905
|
-
action: "propertiesPanelOpened",
|
|
3906
|
-
source: "user",
|
|
3907
|
-
component_uid: componentUid,
|
|
3908
|
-
properties_count: overridablePropsCount
|
|
3909
|
-
});
|
|
3910
|
-
};
|
|
3911
|
-
return /* @__PURE__ */ React29.createElement(Box15, { "data-testid": "component-panel-header" }, /* @__PURE__ */ React29.createElement(PanelHeader3, { sx: { justifyContent: "start", px: 2 } }, /* @__PURE__ */ React29.createElement(Tooltip5, { title: __22("Back", "elementor") }, /* @__PURE__ */ React29.createElement(IconButton5, { size: "tiny", onClick: onBack, "aria-label": __22("Back", "elementor") }, /* @__PURE__ */ React29.createElement(ArrowLeftIcon, { fontSize: "tiny" }))), /* @__PURE__ */ React29.createElement(ComponentsFilledIcon, { fontSize: "tiny", stroke: "currentColor" }), /* @__PURE__ */ React29.createElement(
|
|
3912
|
-
EllipsisWithTooltip4,
|
|
3913
|
-
{
|
|
3914
|
-
title: componentName,
|
|
3915
|
-
as: Typography11,
|
|
3916
|
-
variant: "caption",
|
|
3917
|
-
sx: { fontWeight: 500, flexGrow: 1 }
|
|
3918
|
-
}
|
|
3919
|
-
), /* @__PURE__ */ React29.createElement(
|
|
3920
|
-
ComponentsBadge,
|
|
3921
|
-
{
|
|
3922
|
-
overridablePropsCount,
|
|
3923
|
-
ref: anchorRef,
|
|
3924
|
-
onClick: handleOpenPropertiesPanel
|
|
3925
|
-
}
|
|
3926
|
-
)), /* @__PURE__ */ React29.createElement(Divider4, null), /* @__PURE__ */ React29.createElement(
|
|
3927
|
-
ComponentIntroduction,
|
|
3928
|
-
{
|
|
3929
|
-
anchorRef,
|
|
3930
|
-
shouldShowIntroduction,
|
|
3931
|
-
onClose: handleCloseIntroduction
|
|
3932
|
-
}
|
|
3933
|
-
));
|
|
3934
|
-
};
|
|
3935
|
-
function getComponentName() {
|
|
3936
|
-
const state = getState9();
|
|
3937
|
-
const path = state[SLICE_NAME].path;
|
|
3938
|
-
const { instanceTitle } = path.at(-1) ?? {};
|
|
3939
|
-
if (instanceTitle) {
|
|
3940
|
-
return instanceTitle;
|
|
3941
|
-
}
|
|
3942
|
-
const documentsManager = getV1DocumentsManager3();
|
|
3943
|
-
const currentDocument = documentsManager.getCurrent();
|
|
3944
|
-
return currentDocument?.container?.settings?.get("post_title") ?? "";
|
|
3945
|
-
}
|
|
3946
|
-
|
|
3947
|
-
// src/extended/components/components-tab/components.tsx
|
|
3948
|
-
import * as React32 from "react";
|
|
3949
|
-
import { ThemeProvider as ThemeProvider3 } from "@elementor/editor-ui";
|
|
3950
|
-
import { List as List4 } from "@elementor/ui";
|
|
3951
|
-
|
|
3952
|
-
// src/extended/components/components-tab/component-item.tsx
|
|
3953
|
-
import * as React31 from "react";
|
|
3954
|
-
import { useRef as useRef4, useState as useState7 } from "react";
|
|
3955
|
-
import { endDragElementFromPanel, startDragElementFromPanel } from "@elementor/editor-canvas";
|
|
3956
|
-
import { dropElement } from "@elementor/editor-elements";
|
|
3957
|
-
import { MenuListItem as MenuListItem3, useEditable as useEditable2, WarningInfotip } from "@elementor/editor-ui";
|
|
3958
|
-
import { DotsVerticalIcon as DotsVerticalIcon2 } from "@elementor/icons";
|
|
3959
|
-
import { bindMenu as bindMenu2, bindTrigger as bindTrigger3, IconButton as IconButton6, Menu as Menu2, Stack as Stack17, usePopupState as usePopupState3 } from "@elementor/ui";
|
|
3960
|
-
import { __ as __26 } from "@wordpress/i18n";
|
|
3961
|
-
|
|
3962
|
-
// src/extended/store/actions/archive-component.ts
|
|
3963
|
-
import { setDocumentModifiedStatus as setDocumentModifiedStatus4 } from "@elementor/editor-documents";
|
|
3964
|
-
import { notify as notify3 } from "@elementor/editor-notifications";
|
|
3965
|
-
import { __ as __23 } from "@wordpress/i18n";
|
|
3966
|
-
var successNotification = (componentId, componentName) => ({
|
|
3967
|
-
type: "success",
|
|
3968
|
-
/* translators: %s: component name */
|
|
3969
|
-
message: __23("Successfully deleted component %s", "elementor").replace("%s", componentName),
|
|
3970
|
-
id: `success-archived-components-notification-${componentId}`
|
|
3971
|
-
});
|
|
3972
|
-
var archiveComponent = (componentId, componentName) => {
|
|
3973
|
-
componentsActions.archive(componentId);
|
|
3974
|
-
setDocumentModifiedStatus4(true);
|
|
3975
|
-
notify3(successNotification(componentId, componentName));
|
|
3976
|
-
};
|
|
3977
|
-
|
|
3978
|
-
// src/extended/store/actions/rename-component.ts
|
|
3979
|
-
import { getV1DocumentsManager as getV1DocumentsManager4, setDocumentModifiedStatus as setDocumentModifiedStatus5 } from "@elementor/editor-documents";
|
|
3980
|
-
import { getAllDescendants as getAllDescendants2 } from "@elementor/editor-elements";
|
|
3981
|
-
var TITLE_EXTERNAL_CHANGE_COMMAND = "title_external_change";
|
|
3982
|
-
var renameComponent = (componentUid, newName) => {
|
|
3983
|
-
componentsActions.rename(componentUid, newName);
|
|
3984
|
-
setDocumentModifiedStatus5(true);
|
|
3985
|
-
refreshComponentInstanceTitles(componentUid);
|
|
3986
|
-
};
|
|
3987
|
-
function refreshComponentInstanceTitles(componentUid) {
|
|
3988
|
-
const documentContainer = getDocumentContainer();
|
|
3989
|
-
if (!documentContainer) {
|
|
3990
|
-
return;
|
|
3991
|
-
}
|
|
3992
|
-
const componentInstances = findComponentInstancesByUid(documentContainer, componentUid);
|
|
3993
|
-
componentInstances.forEach((element) => {
|
|
3994
|
-
element.model.trigger?.(TITLE_EXTERNAL_CHANGE_COMMAND);
|
|
3995
|
-
});
|
|
3996
|
-
}
|
|
3997
|
-
function getDocumentContainer() {
|
|
3998
|
-
const documentsManager = getV1DocumentsManager4();
|
|
3999
|
-
return documentsManager?.getCurrent()?.container;
|
|
4000
|
-
}
|
|
4001
|
-
function findComponentInstancesByUid(documentContainer, componentUid) {
|
|
4002
|
-
const allDescendants = getAllDescendants2(documentContainer);
|
|
4003
|
-
return allDescendants.filter((element) => {
|
|
4004
|
-
const widgetType = element.model.get("widgetType");
|
|
4005
|
-
const editorSettings = element.model.get("editor_settings");
|
|
4006
|
-
const isMatch = widgetType === COMPONENT_WIDGET_TYPE2 && editorSettings?.component_uid === componentUid;
|
|
4007
|
-
return isMatch;
|
|
4008
|
-
});
|
|
4009
|
-
}
|
|
4010
|
-
|
|
4011
|
-
// src/extended/utils/component-form-schema.ts
|
|
4012
|
-
import { z as z5 } from "@elementor/schema";
|
|
4013
|
-
import { __ as __24 } from "@wordpress/i18n";
|
|
4014
|
-
var MIN_NAME_LENGTH = 2;
|
|
4015
|
-
var MAX_NAME_LENGTH = 50;
|
|
4016
|
-
var baseComponentSchema = z5.string().trim().max(MAX_NAME_LENGTH, __24("Component name is too long. Please keep it under 50 characters.", "elementor"));
|
|
4017
|
-
var createBaseComponentSchema = (existingNames) => {
|
|
4018
|
-
return z5.object({
|
|
4019
|
-
componentName: baseComponentSchema.refine((value) => !existingNames.includes(value), {
|
|
4020
|
-
message: __24("Component name already exists", "elementor")
|
|
4021
|
-
})
|
|
4022
|
-
});
|
|
4023
|
-
};
|
|
4024
|
-
var createSubmitComponentSchema = (existingNames) => {
|
|
4025
|
-
const baseSchema = createBaseComponentSchema(existingNames);
|
|
4026
|
-
return baseSchema.extend({
|
|
4027
|
-
componentName: baseSchema.shape.componentName.refine((value) => value.length > 0, {
|
|
4028
|
-
message: __24("Component name is required.", "elementor")
|
|
4029
|
-
}).refine((value) => value.length >= MIN_NAME_LENGTH, {
|
|
4030
|
-
message: __24("Component name is too short. Please enter at least 2 characters.", "elementor")
|
|
4031
|
-
})
|
|
4032
|
-
});
|
|
4033
|
-
};
|
|
4034
|
-
|
|
4035
|
-
// src/extended/utils/component-name-validation.ts
|
|
4036
|
-
function validateComponentName(label) {
|
|
4037
|
-
const existingComponentTitles = componentsSelectors.getComponents()?.map(({ name }) => name) ?? [];
|
|
4038
|
-
const schema = createSubmitComponentSchema(existingComponentTitles);
|
|
4039
|
-
const result = schema.safeParse({ componentName: label.toLowerCase() });
|
|
4040
|
-
if (result.success) {
|
|
4041
|
-
return {
|
|
4042
|
-
isValid: true,
|
|
4043
|
-
errorMessage: null
|
|
4044
|
-
};
|
|
4045
|
-
}
|
|
4046
|
-
const formattedErrors = result.error.format();
|
|
4047
|
-
const errorMessage = formattedErrors.componentName?._errors[0] ?? formattedErrors._errors[0];
|
|
4048
|
-
return {
|
|
4049
|
-
isValid: false,
|
|
4050
|
-
errorMessage
|
|
4051
|
-
};
|
|
4052
|
-
}
|
|
4053
|
-
|
|
4054
|
-
// src/extended/utils/create-component-model.ts
|
|
4055
|
-
var createComponentModel2 = (component) => {
|
|
4056
|
-
return {
|
|
4057
|
-
elType: "widget",
|
|
4058
|
-
widgetType: "e-component",
|
|
4059
|
-
settings: {
|
|
4060
|
-
component_instance: {
|
|
4061
|
-
$$type: "component-instance",
|
|
4062
|
-
value: {
|
|
4063
|
-
component_id: {
|
|
4064
|
-
$$type: "number",
|
|
4065
|
-
value: component.id ?? component.uid
|
|
4066
|
-
}
|
|
4067
|
-
}
|
|
4068
|
-
}
|
|
4069
|
-
},
|
|
4070
|
-
editor_settings: {
|
|
4071
|
-
component_uid: component.uid
|
|
4072
|
-
}
|
|
4073
|
-
};
|
|
4074
|
-
};
|
|
4075
|
-
|
|
4076
|
-
// src/extended/utils/get-container-for-new-element.ts
|
|
4077
|
-
import {
|
|
4078
|
-
getContainer as getContainer4,
|
|
4079
|
-
getCurrentDocumentContainer as getCurrentDocumentContainer2,
|
|
4080
|
-
getSelectedElements
|
|
4081
|
-
} from "@elementor/editor-elements";
|
|
4082
|
-
var getContainerForNewElement = () => {
|
|
4083
|
-
const currentDocumentContainer = getCurrentDocumentContainer2();
|
|
4084
|
-
const selectedElement = getSelectedElementContainer();
|
|
4085
|
-
let container, options;
|
|
4086
|
-
if (selectedElement) {
|
|
4087
|
-
switch (selectedElement.model.get("elType")) {
|
|
4088
|
-
case "widget": {
|
|
4089
|
-
container = selectedElement?.parent;
|
|
4090
|
-
const selectedElIndex = selectedElement.view?._index ?? -1;
|
|
4091
|
-
if (selectedElIndex > -1) {
|
|
4092
|
-
options = { at: selectedElIndex + 1 };
|
|
4093
|
-
}
|
|
4094
|
-
break;
|
|
4095
|
-
}
|
|
4096
|
-
case "section": {
|
|
4097
|
-
container = selectedElement?.children?.[0];
|
|
4098
|
-
break;
|
|
4099
|
-
}
|
|
4100
|
-
default: {
|
|
4101
|
-
container = selectedElement;
|
|
4102
|
-
break;
|
|
4103
|
-
}
|
|
4104
|
-
}
|
|
4105
|
-
}
|
|
4106
|
-
return { container: container ?? currentDocumentContainer, options };
|
|
4107
|
-
};
|
|
4108
|
-
function getSelectedElementContainer() {
|
|
4109
|
-
const selectedElements = getSelectedElements();
|
|
4110
|
-
if (selectedElements.length !== 1) {
|
|
4111
|
-
return void 0;
|
|
4112
|
-
}
|
|
4113
|
-
return getContainer4(selectedElements[0].id);
|
|
4114
|
-
}
|
|
4115
|
-
|
|
4116
|
-
// src/extended/components/components-tab/delete-confirmation-dialog.tsx
|
|
4117
|
-
import * as React30 from "react";
|
|
4118
|
-
import { ConfirmationDialog as ConfirmationDialog2 } from "@elementor/editor-ui";
|
|
4119
|
-
import { __ as __25 } from "@wordpress/i18n";
|
|
4120
|
-
function DeleteConfirmationDialog({ open, onClose, onConfirm }) {
|
|
4121
|
-
return /* @__PURE__ */ React30.createElement(ConfirmationDialog2, { open, onClose }, /* @__PURE__ */ React30.createElement(ConfirmationDialog2.Title, null, __25("Delete this component?", "elementor")), /* @__PURE__ */ React30.createElement(ConfirmationDialog2.Content, null, /* @__PURE__ */ React30.createElement(ConfirmationDialog2.ContentText, null, __25(
|
|
4122
|
-
"Existing instances on your pages will remain functional. You will no longer find this component in your list.",
|
|
4123
|
-
"elementor"
|
|
4124
|
-
))), /* @__PURE__ */ React30.createElement(ConfirmationDialog2.Actions, { onClose, onConfirm }));
|
|
4125
|
-
}
|
|
4126
|
-
|
|
4127
|
-
// src/extended/components/components-tab/component-item.tsx
|
|
4128
|
-
function ComponentItem2({ component }) {
|
|
4129
|
-
const itemRef = useRef4(null);
|
|
4130
|
-
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState7(false);
|
|
4131
|
-
const { canRename, canDelete } = useComponentsPermissions();
|
|
4132
|
-
const shouldShowActions = canRename || canDelete;
|
|
4133
|
-
const {
|
|
4134
|
-
ref: editableRef,
|
|
4135
|
-
isEditing,
|
|
4136
|
-
openEditMode,
|
|
4137
|
-
error,
|
|
4138
|
-
getProps: getEditableProps
|
|
4139
|
-
} = useEditable2({
|
|
4140
|
-
value: component.name,
|
|
4141
|
-
onSubmit: (newName) => renameComponent(component.uid, newName),
|
|
4142
|
-
validation: validateComponentTitle
|
|
4143
|
-
});
|
|
4144
|
-
const componentModel = createComponentModel2(component);
|
|
4145
|
-
const popupState = usePopupState3({
|
|
4146
|
-
variant: "popover",
|
|
4147
|
-
disableAutoFocus: true
|
|
4148
|
-
});
|
|
4149
|
-
const handleClick = () => {
|
|
4150
|
-
addComponentToPage(componentModel);
|
|
4151
|
-
};
|
|
4152
|
-
const handleDragEnd = () => {
|
|
4153
|
-
loadComponentsAssets([componentModel]);
|
|
4154
|
-
endDragElementFromPanel();
|
|
4155
|
-
};
|
|
4156
|
-
const handleDeleteClick = () => {
|
|
4157
|
-
setIsDeleteDialogOpen(true);
|
|
4158
|
-
popupState.close();
|
|
4159
|
-
};
|
|
4160
|
-
const handleDeleteConfirm = () => {
|
|
4161
|
-
if (!component.id) {
|
|
4162
|
-
throw new Error("Component ID is required");
|
|
4163
|
-
}
|
|
4164
|
-
setIsDeleteDialogOpen(false);
|
|
4165
|
-
archiveComponent(component.id, component.name);
|
|
4166
|
-
};
|
|
4167
|
-
const handleDeleteDialogClose = () => {
|
|
4168
|
-
setIsDeleteDialogOpen(false);
|
|
4169
|
-
};
|
|
4170
|
-
return /* @__PURE__ */ React31.createElement(Stack17, null, /* @__PURE__ */ React31.createElement(
|
|
4171
|
-
WarningInfotip,
|
|
4172
|
-
{
|
|
4173
|
-
open: Boolean(error),
|
|
4174
|
-
text: error ?? "",
|
|
4175
|
-
placement: "bottom",
|
|
4176
|
-
width: itemRef.current?.getBoundingClientRect().width,
|
|
4177
|
-
offset: [0, -15]
|
|
4178
|
-
},
|
|
4179
|
-
/* @__PURE__ */ React31.createElement(
|
|
4180
|
-
ComponentItem,
|
|
4181
|
-
{
|
|
4182
|
-
ref: itemRef,
|
|
4183
|
-
component,
|
|
4184
|
-
disabled: false,
|
|
4185
|
-
draggable: true,
|
|
4186
|
-
onDragStart: (event) => startDragElementFromPanel(componentModel, event),
|
|
4187
|
-
onDragEnd: handleDragEnd,
|
|
4188
|
-
onClick: handleClick,
|
|
4189
|
-
isEditing,
|
|
4190
|
-
error,
|
|
4191
|
-
nameSlot: /* @__PURE__ */ React31.createElement(
|
|
4192
|
-
ComponentName,
|
|
4193
|
-
{
|
|
4194
|
-
name: component.name,
|
|
4195
|
-
editable: { ref: editableRef, isEditing, getProps: getEditableProps }
|
|
4196
|
-
}
|
|
4197
|
-
),
|
|
4198
|
-
endSlot: shouldShowActions ? /* @__PURE__ */ React31.createElement(IconButton6, { size: "tiny", ...bindTrigger3(popupState), "aria-label": "More actions" }, /* @__PURE__ */ React31.createElement(DotsVerticalIcon2, { fontSize: "tiny" })) : void 0
|
|
4199
|
-
}
|
|
4200
|
-
)
|
|
4201
|
-
), shouldShowActions && /* @__PURE__ */ React31.createElement(
|
|
4202
|
-
Menu2,
|
|
4203
|
-
{
|
|
4204
|
-
...bindMenu2(popupState),
|
|
4205
|
-
anchorOrigin: {
|
|
4206
|
-
vertical: "bottom",
|
|
4207
|
-
horizontal: "right"
|
|
4208
|
-
},
|
|
4209
|
-
transformOrigin: {
|
|
4210
|
-
vertical: "top",
|
|
4211
|
-
horizontal: "right"
|
|
4212
|
-
}
|
|
4213
|
-
},
|
|
4214
|
-
canRename && /* @__PURE__ */ React31.createElement(
|
|
4215
|
-
MenuListItem3,
|
|
4216
|
-
{
|
|
4217
|
-
sx: { minWidth: "160px" },
|
|
4218
|
-
primaryTypographyProps: { variant: "caption", color: "text.primary" },
|
|
4219
|
-
onClick: () => {
|
|
4220
|
-
popupState.close();
|
|
4221
|
-
openEditMode();
|
|
4222
|
-
}
|
|
4223
|
-
},
|
|
4224
|
-
__26("Rename", "elementor")
|
|
4225
|
-
),
|
|
4226
|
-
canDelete && /* @__PURE__ */ React31.createElement(
|
|
4227
|
-
MenuListItem3,
|
|
4228
|
-
{
|
|
4229
|
-
sx: { minWidth: "160px" },
|
|
4230
|
-
primaryTypographyProps: { variant: "caption", color: "error.light" },
|
|
4231
|
-
onClick: handleDeleteClick
|
|
4232
|
-
},
|
|
4233
|
-
__26("Delete", "elementor")
|
|
4234
|
-
)
|
|
4235
|
-
), /* @__PURE__ */ React31.createElement(
|
|
4236
|
-
DeleteConfirmationDialog,
|
|
4237
|
-
{
|
|
4238
|
-
open: isDeleteDialogOpen,
|
|
4239
|
-
onClose: handleDeleteDialogClose,
|
|
4240
|
-
onConfirm: handleDeleteConfirm
|
|
4241
|
-
}
|
|
4242
|
-
));
|
|
4243
|
-
}
|
|
4244
|
-
var addComponentToPage = (model) => {
|
|
4245
|
-
const { container, options } = getContainerForNewElement();
|
|
4246
|
-
if (!container) {
|
|
4247
|
-
throw new Error(`Can't find container to drop new component instance at`);
|
|
4248
|
-
}
|
|
4249
|
-
loadComponentsAssets([model]);
|
|
4250
|
-
dropElement({
|
|
4251
|
-
containerId: container.id,
|
|
4252
|
-
model,
|
|
4253
|
-
options: { ...options, useHistory: false, scrollIntoView: true }
|
|
4254
|
-
});
|
|
4255
|
-
};
|
|
4256
|
-
var validateComponentTitle = (newTitle) => {
|
|
4257
|
-
const result = validateComponentName(newTitle);
|
|
4258
|
-
if (!result.errorMessage) {
|
|
4259
|
-
return null;
|
|
4260
|
-
}
|
|
4261
|
-
return result.errorMessage;
|
|
4262
|
-
};
|
|
4263
|
-
|
|
4264
|
-
// src/extended/components/components-tab/components.tsx
|
|
4265
|
-
var ExtendedComponentsList = () => {
|
|
4266
|
-
const { components, isLoading, searchValue } = useFilteredComponents();
|
|
4267
|
-
if (isLoading) {
|
|
4268
|
-
return /* @__PURE__ */ React32.createElement(LoadingComponents, null);
|
|
4269
|
-
}
|
|
4270
|
-
const isEmpty = !components?.length;
|
|
4271
|
-
if (isEmpty) {
|
|
4272
|
-
return searchValue.length ? /* @__PURE__ */ React32.createElement(EmptySearchResult, null) : /* @__PURE__ */ React32.createElement(EmptyState, null);
|
|
4273
|
-
}
|
|
4274
|
-
return /* @__PURE__ */ React32.createElement(List4, { sx: { display: "flex", flexDirection: "column", gap: 1, px: 2 } }, components.map((component) => /* @__PURE__ */ React32.createElement(ComponentItem2, { key: component.uid, component })));
|
|
4275
|
-
};
|
|
4276
|
-
var ExtendedComponentsContent = () => {
|
|
4277
|
-
const { components, isLoading } = useComponents();
|
|
4278
|
-
const hasComponents = !isLoading && components.length > 0;
|
|
4279
|
-
return /* @__PURE__ */ React32.createElement(React32.Fragment, null, hasComponents && /* @__PURE__ */ React32.createElement(ComponentSearch, null), /* @__PURE__ */ React32.createElement(ExtendedComponentsList, null));
|
|
4280
|
-
};
|
|
4281
|
-
var ExtendedComponents = () => {
|
|
4282
|
-
return /* @__PURE__ */ React32.createElement(ThemeProvider3, null, /* @__PURE__ */ React32.createElement(SearchProvider, { localStorageKey: "elementor-components-search" }, /* @__PURE__ */ React32.createElement(ExtendedComponentsContent, null)));
|
|
4283
|
-
};
|
|
4284
|
-
|
|
4285
|
-
// src/extended/components/create-component-form/create-component-form.tsx
|
|
4286
|
-
import * as React33 from "react";
|
|
4287
|
-
import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef5, useState as useState9 } from "react";
|
|
4288
|
-
import { getElementLabel } from "@elementor/editor-elements";
|
|
4289
|
-
import { notify as notify5 } from "@elementor/editor-notifications";
|
|
4290
|
-
import { Form as FormElement, ThemeProvider as ThemeProvider4, useTextFieldAutoSelect } from "@elementor/editor-ui";
|
|
4291
|
-
import { ComponentsIcon as ComponentsIcon4 } from "@elementor/icons";
|
|
4292
|
-
import { Button as Button5, FormLabel as FormLabel2, Grid as Grid2, Popover as Popover3, Stack as Stack18, TextField as TextField3, Typography as Typography12 } from "@elementor/ui";
|
|
4293
|
-
import { __ as __29 } from "@wordpress/i18n";
|
|
4294
|
-
|
|
4295
|
-
// src/extended/store/actions/create-unpublished-component.ts
|
|
4296
|
-
import { createElements, deleteElement, getContainer as getContainer5 } from "@elementor/editor-elements";
|
|
4297
|
-
import { __privateRunCommand as runCommand2 } from "@elementor/editor-v1-adapters";
|
|
4298
|
-
import { generateUniqueId as generateUniqueId3 } from "@elementor/utils";
|
|
4299
|
-
import { __ as __27 } from "@wordpress/i18n";
|
|
4300
|
-
|
|
4301
|
-
// src/extended/utils/replace-element-with-component.ts
|
|
4302
|
-
import { replaceElement as replaceElement2 } from "@elementor/editor-elements";
|
|
4303
|
-
var replaceElementWithComponent = (element, component) => {
|
|
4304
|
-
return replaceElement2({
|
|
4305
|
-
currentElementId: element.id,
|
|
4306
|
-
newElement: createComponentModel2(component),
|
|
4307
|
-
withHistory: false
|
|
4308
|
-
});
|
|
4309
|
-
};
|
|
4310
|
-
|
|
4311
|
-
// src/extended/store/actions/create-unpublished-component.ts
|
|
4312
|
-
async function createUnpublishedComponent({
|
|
4313
|
-
name,
|
|
4314
|
-
element,
|
|
4315
|
-
eventData,
|
|
4316
|
-
uid,
|
|
4317
|
-
overridableProps,
|
|
4318
|
-
source
|
|
4319
|
-
}) {
|
|
4320
|
-
const generatedUid = uid ?? generateUniqueId3("component");
|
|
4321
|
-
const componentBase = { uid: generatedUid, name };
|
|
4322
|
-
const elementDataWithOverridablesReverted = revertAllOverridablesInElementData(element);
|
|
4323
|
-
const container = getContainer5(element.id);
|
|
4324
|
-
const modelFromContainer = container?.model?.toJSON?.();
|
|
4325
|
-
const originalElement = {
|
|
4326
|
-
model: modelFromContainer ?? element,
|
|
4327
|
-
parentId: container?.parent?.id ?? "",
|
|
4328
|
-
index: container?.view?._index ?? 0
|
|
4329
|
-
};
|
|
4330
|
-
componentsActions.addUnpublished({
|
|
4331
|
-
...componentBase,
|
|
4332
|
-
elements: [elementDataWithOverridablesReverted],
|
|
4333
|
-
overridableProps
|
|
4334
|
-
});
|
|
4335
|
-
componentsActions.addCreatedThisSession(generatedUid);
|
|
4336
|
-
const componentInstance = replaceElementWithComponent(element, componentBase);
|
|
4337
|
-
trackComponentEvent({
|
|
4338
|
-
action: "created",
|
|
4339
|
-
source,
|
|
4340
|
-
component_uid: generatedUid,
|
|
4341
|
-
component_name: name,
|
|
4342
|
-
...eventData
|
|
4343
|
-
});
|
|
4344
|
-
try {
|
|
4345
|
-
await runCommand2("document/save/auto");
|
|
4346
|
-
} catch (error) {
|
|
4347
|
-
restoreOriginalElement(originalElement, componentInstance.id);
|
|
4348
|
-
componentsActions.removeUnpublished(generatedUid);
|
|
4349
|
-
componentsActions.removeCreatedThisSession(generatedUid);
|
|
4350
|
-
throw error;
|
|
4351
|
-
}
|
|
4352
|
-
return { uid: generatedUid, instanceId: componentInstance.id };
|
|
4353
|
-
}
|
|
4354
|
-
function restoreOriginalElement(originalElement, componentInstanceId) {
|
|
4355
|
-
const componentContainer = getContainer5(componentInstanceId);
|
|
4356
|
-
if (componentContainer) {
|
|
4357
|
-
deleteElement({ container: componentContainer, options: { useHistory: false } });
|
|
4358
|
-
}
|
|
4359
|
-
const parentContainer = getContainer5(originalElement.parentId);
|
|
4360
|
-
if (!parentContainer) {
|
|
4361
|
-
return;
|
|
4362
|
-
}
|
|
4363
|
-
const clonedModel = structuredClone(originalElement.model);
|
|
4364
|
-
createElements({
|
|
4365
|
-
title: __27("Restore Element", "elementor"),
|
|
4366
|
-
elements: [
|
|
4367
|
-
{
|
|
4368
|
-
container: parentContainer,
|
|
4369
|
-
model: clonedModel,
|
|
4370
|
-
options: { at: originalElement.index }
|
|
4371
|
-
}
|
|
4372
|
-
]
|
|
4373
|
-
});
|
|
4374
|
-
}
|
|
4375
|
-
|
|
4376
|
-
// src/extended/sync/prevent-non-atomic-nesting.ts
|
|
4377
|
-
import { isAtomicWidget } from "@elementor/editor-canvas";
|
|
4378
|
-
import { getAllDescendants as getAllDescendants3, getElementType as getElementType3 } from "@elementor/editor-elements";
|
|
4379
|
-
import { notify as notify4 } from "@elementor/editor-notifications";
|
|
4380
|
-
import { blockCommand } from "@elementor/editor-v1-adapters";
|
|
4381
|
-
import { __ as __28 } from "@wordpress/i18n";
|
|
4382
|
-
|
|
4383
|
-
// src/extended/utils/is-editing-component.ts
|
|
4384
|
-
function isEditingComponent() {
|
|
4385
|
-
return componentsSelectors.getCurrentComponentId() !== null;
|
|
4386
|
-
}
|
|
4387
|
-
|
|
4388
|
-
// src/extended/sync/prevent-non-atomic-nesting.ts
|
|
4389
|
-
var NON_ATOMIC_ELEMENT_ALERT = {
|
|
4390
|
-
type: "default",
|
|
4391
|
-
message: __28("This widget isn't compatible with components. Use atomic elements instead.", "elementor"),
|
|
4392
|
-
id: "non-atomic-element-blocked"
|
|
4393
|
-
};
|
|
4394
|
-
function initNonAtomicNestingPrevention() {
|
|
4395
|
-
blockCommand({
|
|
4396
|
-
command: "document/elements/create",
|
|
4397
|
-
condition: blockNonAtomicCreate
|
|
4398
|
-
});
|
|
4399
|
-
blockCommand({
|
|
4400
|
-
command: "document/elements/move",
|
|
4401
|
-
condition: blockNonAtomicMove
|
|
4402
|
-
});
|
|
4403
|
-
blockCommand({
|
|
4404
|
-
command: "document/elements/paste",
|
|
4405
|
-
condition: blockNonAtomicPaste
|
|
4406
|
-
});
|
|
4407
|
-
}
|
|
4408
|
-
function isElementAtomic(elementType) {
|
|
4409
|
-
return getElementType3(elementType) !== null;
|
|
4410
|
-
}
|
|
4411
|
-
function blockNonAtomicCreate(args) {
|
|
4412
|
-
if (!isEditingComponent()) {
|
|
4413
|
-
return false;
|
|
4414
|
-
}
|
|
4415
|
-
const { model } = args;
|
|
4416
|
-
const elementType = model?.widgetType || model?.elType;
|
|
4417
|
-
if (!elementType) {
|
|
4418
|
-
return false;
|
|
4419
|
-
}
|
|
4420
|
-
if (isElementAtomic(elementType)) {
|
|
4421
|
-
return false;
|
|
4422
|
-
}
|
|
4423
|
-
notify4(NON_ATOMIC_ELEMENT_ALERT);
|
|
4424
|
-
return true;
|
|
4425
|
-
}
|
|
4426
|
-
function blockNonAtomicMove(args) {
|
|
4427
|
-
if (!isEditingComponent()) {
|
|
4428
|
-
return false;
|
|
4429
|
-
}
|
|
4430
|
-
const { containers = [args.container] } = args;
|
|
4431
|
-
const hasNonAtomicElement = containers.some((container) => {
|
|
4432
|
-
if (!container) {
|
|
4433
|
-
return false;
|
|
4434
|
-
}
|
|
4435
|
-
const allElements = getAllDescendants3(container);
|
|
4436
|
-
return allElements.some((element) => !isAtomicWidget(element));
|
|
4437
|
-
});
|
|
4438
|
-
if (hasNonAtomicElement) {
|
|
4439
|
-
notify4(NON_ATOMIC_ELEMENT_ALERT);
|
|
4440
|
-
}
|
|
4441
|
-
return hasNonAtomicElement;
|
|
4442
|
-
}
|
|
4443
|
-
function blockNonAtomicPaste(args) {
|
|
4444
|
-
if (!isEditingComponent()) {
|
|
4445
|
-
return false;
|
|
4446
|
-
}
|
|
4447
|
-
const { storageType } = args;
|
|
4448
|
-
if (storageType !== "localstorage") {
|
|
4449
|
-
return false;
|
|
4450
|
-
}
|
|
4451
|
-
const data = window?.elementorCommon?.storage?.get();
|
|
4452
|
-
if (!data?.clipboard?.elements) {
|
|
4453
|
-
return false;
|
|
4454
|
-
}
|
|
4455
|
-
const hasNonAtomicElement = hasNonAtomicElementsInTree(data.clipboard.elements);
|
|
4456
|
-
if (hasNonAtomicElement) {
|
|
4457
|
-
notify4(NON_ATOMIC_ELEMENT_ALERT);
|
|
4458
|
-
}
|
|
4459
|
-
return hasNonAtomicElement;
|
|
4460
|
-
}
|
|
4461
|
-
function hasNonAtomicElementsInTree(elements) {
|
|
4462
|
-
for (const element of elements) {
|
|
4463
|
-
const elementType = element.widgetType || element.elType;
|
|
4464
|
-
if (elementType && !isElementAtomic(elementType)) {
|
|
4465
|
-
return true;
|
|
4466
|
-
}
|
|
4467
|
-
if (element.elements?.length) {
|
|
4468
|
-
if (hasNonAtomicElementsInTree(element.elements)) {
|
|
4469
|
-
return true;
|
|
4470
|
-
}
|
|
4471
|
-
}
|
|
4472
|
-
}
|
|
4473
|
-
return false;
|
|
4474
|
-
}
|
|
4475
|
-
function findNonAtomicElementsInElement(element) {
|
|
4476
|
-
const nonAtomicElements = [];
|
|
4477
|
-
const elementType = element.widgetType || element.elType;
|
|
4478
|
-
if (elementType && !isElementAtomic(elementType)) {
|
|
4479
|
-
nonAtomicElements.push(elementType);
|
|
4480
|
-
}
|
|
4481
|
-
if (element.elements?.length) {
|
|
4482
|
-
for (const child of element.elements) {
|
|
4483
|
-
nonAtomicElements.push(...findNonAtomicElementsInElement(child));
|
|
4484
|
-
}
|
|
4485
|
-
}
|
|
4486
|
-
return [...new Set(nonAtomicElements)];
|
|
4487
|
-
}
|
|
4488
|
-
|
|
4489
|
-
// src/extended/components/create-component-form/hooks/use-form.ts
|
|
4490
|
-
import { useMemo as useMemo2, useState as useState8 } from "react";
|
|
4491
|
-
var useForm = (initialValues) => {
|
|
4492
|
-
const [values, setValues] = useState8(initialValues);
|
|
4493
|
-
const [errors, setErrors] = useState8({});
|
|
4494
|
-
const isValid = useMemo2(() => {
|
|
4495
|
-
return !Object.values(errors).some((error) => error);
|
|
4496
|
-
}, [errors]);
|
|
4497
|
-
const handleChange = (e, field, validationSchema) => {
|
|
4498
|
-
const updated = { ...values, [field]: e.target.value };
|
|
4499
|
-
setValues(updated);
|
|
4500
|
-
const { success, errors: validationErrors } = validateForm(updated, validationSchema);
|
|
4501
|
-
if (!success) {
|
|
4502
|
-
setErrors(validationErrors);
|
|
4503
|
-
} else {
|
|
4504
|
-
setErrors({});
|
|
4505
|
-
}
|
|
4506
|
-
};
|
|
4507
|
-
const validate = (validationSchema) => {
|
|
4508
|
-
const { success, errors: validationErrors, parsedValues } = validateForm(values, validationSchema);
|
|
4509
|
-
if (!success) {
|
|
4510
|
-
setErrors(validationErrors);
|
|
4511
|
-
return { success };
|
|
4512
|
-
}
|
|
4513
|
-
setErrors({});
|
|
4514
|
-
return { success, parsedValues };
|
|
4515
|
-
};
|
|
4516
|
-
return {
|
|
4517
|
-
values,
|
|
4518
|
-
errors,
|
|
4519
|
-
isValid,
|
|
4520
|
-
handleChange,
|
|
4521
|
-
validateForm: validate
|
|
4522
|
-
};
|
|
4523
|
-
};
|
|
4524
|
-
var validateForm = (values, schema) => {
|
|
4525
|
-
const result = schema.safeParse(values);
|
|
4526
|
-
if (result.success) {
|
|
4527
|
-
return { success: true, parsedValues: result.data };
|
|
4528
|
-
}
|
|
4529
|
-
const errors = {};
|
|
4530
|
-
Object.entries(result.error.formErrors.fieldErrors).forEach(
|
|
4531
|
-
([field, error]) => {
|
|
4532
|
-
errors[field] = error[0];
|
|
4533
|
-
}
|
|
4534
|
-
);
|
|
4535
|
-
return { success: false, errors };
|
|
4536
|
-
};
|
|
4537
|
-
|
|
4538
|
-
// src/extended/components/create-component-form/utils/get-component-event-data.ts
|
|
4539
|
-
var getComponentEventData = (containerElement, options) => {
|
|
4540
|
-
const { elementsCount, componentsCount } = countNestedElements(containerElement);
|
|
4541
|
-
return {
|
|
4542
|
-
nested_elements_count: elementsCount,
|
|
4543
|
-
nested_components_count: componentsCount,
|
|
4544
|
-
top_element_type: containerElement.elType,
|
|
4545
|
-
location: options?.location,
|
|
4546
|
-
secondary_location: options?.secondaryLocation,
|
|
4547
|
-
trigger: options?.trigger
|
|
4548
|
-
};
|
|
4549
|
-
};
|
|
4550
|
-
function countNestedElements(container) {
|
|
4551
|
-
if (!container.elements || container.elements.length === 0) {
|
|
4552
|
-
return { elementsCount: 0, componentsCount: 0 };
|
|
4553
|
-
}
|
|
4554
|
-
let elementsCount = container.elements.length;
|
|
4555
|
-
let componentsCount = 0;
|
|
4556
|
-
for (const element of container.elements) {
|
|
4557
|
-
if (element.widgetType === "e-component") {
|
|
4558
|
-
componentsCount++;
|
|
4559
|
-
}
|
|
4560
|
-
const { elementsCount: nestedElementsCount, componentsCount: nestedComponentsCount } = countNestedElements(element);
|
|
4561
|
-
elementsCount += nestedElementsCount;
|
|
4562
|
-
componentsCount += nestedComponentsCount;
|
|
4563
|
-
}
|
|
4564
|
-
return { elementsCount, componentsCount };
|
|
4565
|
-
}
|
|
4566
|
-
|
|
4567
|
-
// src/extended/components/create-component-form/create-component-form.tsx
|
|
4568
|
-
var MAX_COMPONENTS = 100;
|
|
4569
|
-
function CreateComponentForm() {
|
|
4570
|
-
const [element, setElement] = useState9(null);
|
|
4571
|
-
const [anchorPosition, setAnchorPosition] = useState9();
|
|
4572
|
-
const { components } = useComponents();
|
|
4573
|
-
const eventData = useRef5(null);
|
|
4574
|
-
useEffect3(() => {
|
|
4575
|
-
const OPEN_SAVE_AS_COMPONENT_FORM_EVENT2 = "elementor/editor/open-save-as-component-form";
|
|
4576
|
-
const openPopup = (event) => {
|
|
4577
|
-
const { shouldOpen, notification } = shouldOpenForm(event.detail.element, components?.length ?? 0);
|
|
4578
|
-
if (!shouldOpen) {
|
|
4579
|
-
notify5(notification);
|
|
4580
|
-
return;
|
|
4581
|
-
}
|
|
4582
|
-
setElement({ element: event.detail.element, elementLabel: getElementLabel(event.detail.element.id) });
|
|
4583
|
-
setAnchorPosition(event.detail.anchorPosition);
|
|
4584
|
-
eventData.current = getComponentEventData(event.detail.element, event.detail.options);
|
|
4585
|
-
trackComponentEvent({
|
|
4586
|
-
action: "createClicked",
|
|
4587
|
-
source: "user",
|
|
4588
|
-
...eventData.current
|
|
4589
|
-
});
|
|
4590
|
-
};
|
|
4591
|
-
window.addEventListener(OPEN_SAVE_AS_COMPONENT_FORM_EVENT2, openPopup);
|
|
4592
|
-
return () => {
|
|
4593
|
-
window.removeEventListener(OPEN_SAVE_AS_COMPONENT_FORM_EVENT2, openPopup);
|
|
4594
|
-
};
|
|
4595
|
-
}, [components?.length]);
|
|
4596
|
-
const handleSave = async (values) => {
|
|
4597
|
-
try {
|
|
4598
|
-
if (!element) {
|
|
4599
|
-
throw new Error(`Can't save element as component: element not found`);
|
|
4600
|
-
}
|
|
4601
|
-
const { uid, instanceId } = await createUnpublishedComponent({
|
|
4602
|
-
name: values.componentName,
|
|
4603
|
-
element: element.element,
|
|
4604
|
-
eventData: eventData.current,
|
|
4605
|
-
source: "user"
|
|
4606
|
-
});
|
|
4607
|
-
const publishedComponentId = componentsSelectors.getComponentByUid(uid)?.id;
|
|
4608
|
-
if (publishedComponentId) {
|
|
4609
|
-
switchToComponent(publishedComponentId, instanceId);
|
|
4610
|
-
} else {
|
|
4611
|
-
throw new Error("Failed to find published component");
|
|
4612
|
-
}
|
|
4613
|
-
notify5({
|
|
4614
|
-
type: "success",
|
|
4615
|
-
message: __29("Component created successfully.", "elementor"),
|
|
4616
|
-
id: `component-saved-successfully-${uid}`
|
|
4617
|
-
});
|
|
4618
|
-
resetAndClosePopup();
|
|
4619
|
-
} catch {
|
|
4620
|
-
const errorMessage = __29("Failed to create component. Please try again.", "elementor");
|
|
4621
|
-
notify5({
|
|
4622
|
-
type: "error",
|
|
4623
|
-
message: errorMessage,
|
|
4624
|
-
id: "component-save-failed"
|
|
4625
|
-
});
|
|
4626
|
-
resetAndClosePopup();
|
|
4627
|
-
}
|
|
4628
|
-
};
|
|
4629
|
-
const resetAndClosePopup = () => {
|
|
4630
|
-
setElement(null);
|
|
4631
|
-
setAnchorPosition(void 0);
|
|
4632
|
-
};
|
|
4633
|
-
const cancelSave = () => {
|
|
4634
|
-
resetAndClosePopup();
|
|
4635
|
-
trackComponentEvent({
|
|
4636
|
-
action: "createCancelled",
|
|
4637
|
-
source: "user",
|
|
4638
|
-
...eventData.current
|
|
4639
|
-
});
|
|
4640
|
-
};
|
|
4641
|
-
return /* @__PURE__ */ React33.createElement(ThemeProvider4, null, /* @__PURE__ */ React33.createElement(
|
|
4642
|
-
Popover3,
|
|
4643
|
-
{
|
|
4644
|
-
open: element !== null,
|
|
4645
|
-
onClose: cancelSave,
|
|
4646
|
-
anchorReference: "anchorPosition",
|
|
4647
|
-
anchorPosition,
|
|
4648
|
-
"data-testid": "create-component-form"
|
|
4649
|
-
},
|
|
4650
|
-
element !== null && /* @__PURE__ */ React33.createElement(
|
|
4651
|
-
Form2,
|
|
4652
|
-
{
|
|
4653
|
-
initialValues: { componentName: element.elementLabel },
|
|
4654
|
-
handleSave,
|
|
4655
|
-
closePopup: cancelSave
|
|
4656
|
-
}
|
|
4657
|
-
)
|
|
4658
|
-
));
|
|
4659
|
-
}
|
|
4660
|
-
function shouldOpenForm(element, componentsCount) {
|
|
4661
|
-
const nonAtomicElements = findNonAtomicElementsInElement(element);
|
|
4662
|
-
if (nonAtomicElements.length > 0) {
|
|
4663
|
-
return {
|
|
4664
|
-
shouldOpen: false,
|
|
4665
|
-
notification: {
|
|
4666
|
-
type: "default",
|
|
4667
|
-
message: __29(
|
|
4668
|
-
"Components require atomic elements only. Remove widgets to create this component.",
|
|
4669
|
-
"elementor"
|
|
4670
|
-
),
|
|
4671
|
-
id: "non-atomic-element-save-blocked"
|
|
4672
|
-
}
|
|
4673
|
-
};
|
|
4674
|
-
}
|
|
4675
|
-
if (componentsCount >= MAX_COMPONENTS) {
|
|
4676
|
-
return {
|
|
4677
|
-
shouldOpen: false,
|
|
4678
|
-
notification: {
|
|
4679
|
-
type: "default",
|
|
4680
|
-
/* translators: %s is the maximum number of components */
|
|
4681
|
-
message: __29(
|
|
4682
|
-
`You've reached the limit of %s components. Please remove an existing one to create a new component.`,
|
|
4683
|
-
"elementor"
|
|
4684
|
-
).replace("%s", MAX_COMPONENTS.toString()),
|
|
4685
|
-
id: "maximum-number-of-components-exceeded"
|
|
4686
|
-
}
|
|
4687
|
-
};
|
|
4688
|
-
}
|
|
4689
|
-
return { shouldOpen: true, notification: null };
|
|
4690
|
-
}
|
|
4691
|
-
var FONT_SIZE = "tiny";
|
|
4692
|
-
var Form2 = ({
|
|
4693
|
-
initialValues,
|
|
4694
|
-
handleSave,
|
|
4695
|
-
closePopup
|
|
4696
|
-
}) => {
|
|
4697
|
-
const { values, errors, isValid, handleChange, validateForm: validateForm2 } = useForm(initialValues);
|
|
4698
|
-
const nameInputRef = useTextFieldAutoSelect();
|
|
4699
|
-
const { components } = useComponents();
|
|
4700
|
-
const existingComponentNames = useMemo3(() => {
|
|
4701
|
-
return components?.map((component) => component.name) ?? [];
|
|
4702
|
-
}, [components]);
|
|
4703
|
-
const changeValidationSchema = useMemo3(
|
|
4704
|
-
() => createBaseComponentSchema(existingComponentNames),
|
|
4705
|
-
[existingComponentNames]
|
|
4706
|
-
);
|
|
4707
|
-
const submitValidationSchema = useMemo3(
|
|
4708
|
-
() => createSubmitComponentSchema(existingComponentNames),
|
|
4709
|
-
[existingComponentNames]
|
|
4710
|
-
);
|
|
4711
|
-
const handleSubmit = () => {
|
|
4712
|
-
const { success, parsedValues } = validateForm2(submitValidationSchema);
|
|
4713
|
-
if (success) {
|
|
4714
|
-
handleSave(parsedValues);
|
|
4715
|
-
}
|
|
4716
|
-
};
|
|
4717
|
-
const texts = {
|
|
4718
|
-
heading: __29("Create component", "elementor"),
|
|
4719
|
-
name: __29("Name", "elementor"),
|
|
4720
|
-
cancel: __29("Cancel", "elementor"),
|
|
4721
|
-
create: __29("Create", "elementor")
|
|
4722
|
-
};
|
|
4723
|
-
const nameInputId = "component-name";
|
|
4724
|
-
return /* @__PURE__ */ React33.createElement(FormElement, { onSubmit: handleSubmit }, /* @__PURE__ */ React33.createElement(Stack18, { alignItems: "start", width: "268px" }, /* @__PURE__ */ React33.createElement(
|
|
4725
|
-
Stack18,
|
|
4726
|
-
{
|
|
4727
|
-
direction: "row",
|
|
4728
|
-
alignItems: "center",
|
|
4729
|
-
py: 1,
|
|
4730
|
-
px: 1.5,
|
|
4731
|
-
sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%" }
|
|
4732
|
-
},
|
|
4733
|
-
/* @__PURE__ */ React33.createElement(ComponentsIcon4, { fontSize: FONT_SIZE }),
|
|
4734
|
-
/* @__PURE__ */ React33.createElement(Typography12, { variant: "caption", sx: { color: "text.primary", fontWeight: "500", lineHeight: 1 } }, texts.heading)
|
|
4735
|
-
), /* @__PURE__ */ React33.createElement(Grid2, { container: true, gap: 0.75, alignItems: "start", p: 1.5 }, /* @__PURE__ */ React33.createElement(Grid2, { item: true, xs: 12 }, /* @__PURE__ */ React33.createElement(FormLabel2, { htmlFor: nameInputId, size: "tiny" }, texts.name)), /* @__PURE__ */ React33.createElement(Grid2, { item: true, xs: 12 }, /* @__PURE__ */ React33.createElement(
|
|
4736
|
-
TextField3,
|
|
4737
|
-
{
|
|
4738
|
-
id: nameInputId,
|
|
4739
|
-
size: FONT_SIZE,
|
|
4740
|
-
fullWidth: true,
|
|
4741
|
-
value: values.componentName,
|
|
4742
|
-
onChange: (e) => handleChange(e, "componentName", changeValidationSchema),
|
|
4743
|
-
inputProps: { style: { color: "text.primary", fontWeight: "600" } },
|
|
4744
|
-
error: Boolean(errors.componentName),
|
|
4745
|
-
helperText: errors.componentName,
|
|
4746
|
-
inputRef: nameInputRef
|
|
4747
|
-
}
|
|
4748
|
-
))), /* @__PURE__ */ React33.createElement(Stack18, { direction: "row", justifyContent: "flex-end", alignSelf: "end", py: 1, px: 1.5 }, /* @__PURE__ */ React33.createElement(Button5, { onClick: closePopup, color: "secondary", variant: "text", size: "small" }, texts.cancel), /* @__PURE__ */ React33.createElement(Button5, { type: "submit", disabled: !isValid, variant: "contained", color: "primary", size: "small" }, texts.create))));
|
|
4749
|
-
};
|
|
4750
|
-
|
|
4751
|
-
// src/extended/components/edit-component/edit-component.tsx
|
|
4752
|
-
import * as React35 from "react";
|
|
4753
|
-
import { useEffect as useEffect6, useState as useState11 } from "react";
|
|
4754
|
-
import { getV1DocumentsManager as getV1DocumentsManager5 } from "@elementor/editor-documents";
|
|
4755
|
-
import { __privateListenTo as listenTo, commandEndEvent as commandEndEvent2 } from "@elementor/editor-v1-adapters";
|
|
4756
|
-
import { __useSelector as useSelector5 } from "@elementor/store";
|
|
4757
|
-
import { throttle as throttle2 } from "@elementor/utils";
|
|
4758
|
-
|
|
4759
|
-
// src/extended/consts.ts
|
|
4760
|
-
var OVERRIDABLE_PROP_REPLACEMENT_ID = "overridable-prop";
|
|
4761
|
-
var COMPONENT_DOCUMENT_TYPE = "elementor_component";
|
|
4762
|
-
|
|
4763
|
-
// src/extended/store/actions/reset-sanitized-components.ts
|
|
4764
|
-
function resetSanitizedComponents() {
|
|
4765
|
-
componentsActions.resetSanitizedComponents();
|
|
4766
|
-
}
|
|
4767
|
-
|
|
4768
|
-
// src/extended/store/actions/update-current-component.ts
|
|
4769
|
-
function updateCurrentComponent(params) {
|
|
4770
|
-
componentsActions.setPath(params.path);
|
|
4771
|
-
componentsActions.setCurrentComponentId(params.currentComponentId);
|
|
4772
|
-
}
|
|
4773
|
-
|
|
4774
|
-
// src/extended/components/edit-component/component-modal.tsx
|
|
4775
|
-
import * as React34 from "react";
|
|
4776
|
-
import { useEffect as useEffect5 } from "react";
|
|
4777
|
-
import { createPortal } from "react-dom";
|
|
4778
|
-
import { __ as __30 } from "@wordpress/i18n";
|
|
4779
|
-
|
|
4780
|
-
// src/extended/components/edit-component/use-canvas-document.ts
|
|
4781
|
-
import {
|
|
4782
|
-
__privateUseListenTo as useListenTo,
|
|
4783
|
-
commandEndEvent,
|
|
4784
|
-
getCanvasIframeDocument
|
|
4785
|
-
} from "@elementor/editor-v1-adapters";
|
|
4786
|
-
function useCanvasDocument() {
|
|
4787
|
-
return useListenTo(commandEndEvent("editor/documents/attach-preview"), () => getCanvasIframeDocument());
|
|
4788
|
-
}
|
|
4789
|
-
|
|
4790
|
-
// src/extended/components/edit-component/use-element-rect.ts
|
|
4791
|
-
import { useEffect as useEffect4, useState as useState10 } from "react";
|
|
4792
|
-
import { throttle } from "@elementor/utils";
|
|
4793
|
-
function useElementRect(element) {
|
|
4794
|
-
const [rect, setRect] = useState10(new DOMRect(0, 0, 0, 0));
|
|
4795
|
-
const onChange = throttle(
|
|
4796
|
-
() => {
|
|
4797
|
-
setRect(element?.getBoundingClientRect() ?? new DOMRect(0, 0, 0, 0));
|
|
4798
|
-
},
|
|
4799
|
-
20,
|
|
4800
|
-
true
|
|
4801
|
-
);
|
|
4802
|
-
useScrollListener({ element, onChange });
|
|
4803
|
-
useResizeListener({ element, onChange });
|
|
4804
|
-
useMutationsListener({ element, onChange });
|
|
4805
|
-
useEffect4(
|
|
4806
|
-
() => () => {
|
|
4807
|
-
onChange.cancel();
|
|
4808
|
-
},
|
|
4809
|
-
[onChange]
|
|
4810
|
-
);
|
|
4811
|
-
return rect;
|
|
4812
|
-
}
|
|
4813
|
-
function useScrollListener({ element, onChange }) {
|
|
4814
|
-
useEffect4(() => {
|
|
4815
|
-
if (!element) {
|
|
4816
|
-
return;
|
|
4817
|
-
}
|
|
4818
|
-
const win = element.ownerDocument?.defaultView;
|
|
4819
|
-
win?.addEventListener("scroll", onChange, { passive: true });
|
|
4820
|
-
return () => {
|
|
4821
|
-
win?.removeEventListener("scroll", onChange);
|
|
4822
|
-
};
|
|
4823
|
-
}, [element, onChange]);
|
|
4824
|
-
}
|
|
4825
|
-
function useResizeListener({ element, onChange }) {
|
|
4826
|
-
useEffect4(() => {
|
|
4827
|
-
if (!element) {
|
|
4828
|
-
return;
|
|
4829
|
-
}
|
|
4830
|
-
const resizeObserver = new ResizeObserver(onChange);
|
|
4831
|
-
resizeObserver.observe(element);
|
|
4832
|
-
const win = element.ownerDocument?.defaultView;
|
|
4833
|
-
win?.addEventListener("resize", onChange, { passive: true });
|
|
4834
|
-
return () => {
|
|
4835
|
-
resizeObserver.disconnect();
|
|
4836
|
-
win?.removeEventListener("resize", onChange);
|
|
4837
|
-
};
|
|
4838
|
-
}, [element, onChange]);
|
|
4839
|
-
}
|
|
4840
|
-
function useMutationsListener({ element, onChange }) {
|
|
4841
|
-
useEffect4(() => {
|
|
4842
|
-
if (!element) {
|
|
4843
|
-
return;
|
|
4844
|
-
}
|
|
4845
|
-
const mutationObserver = new MutationObserver(onChange);
|
|
4846
|
-
mutationObserver.observe(element, { childList: true, subtree: true });
|
|
4847
|
-
return () => {
|
|
4848
|
-
mutationObserver.disconnect();
|
|
4849
|
-
};
|
|
4850
|
-
}, [element, onChange]);
|
|
4851
|
-
}
|
|
4852
|
-
|
|
4853
|
-
// src/extended/components/edit-component/component-modal.tsx
|
|
4854
|
-
function ComponentModal({ topLevelElementDom, onClose }) {
|
|
4855
|
-
const canvasDocument = useCanvasDocument();
|
|
4856
|
-
useEffect5(() => {
|
|
4857
|
-
const handleEsc = (event) => {
|
|
4858
|
-
if (event.key === "Escape") {
|
|
4859
|
-
onClose();
|
|
4860
|
-
}
|
|
4861
|
-
};
|
|
4862
|
-
canvasDocument?.body.addEventListener("keydown", handleEsc);
|
|
4863
|
-
return () => {
|
|
4864
|
-
canvasDocument?.body.removeEventListener("keydown", handleEsc);
|
|
4865
|
-
};
|
|
4866
|
-
}, [canvasDocument, onClose]);
|
|
4867
|
-
if (!canvasDocument?.body) {
|
|
4868
|
-
return null;
|
|
4869
|
-
}
|
|
4870
|
-
return createPortal(
|
|
4871
|
-
/* @__PURE__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement(BlockEditPage, null), /* @__PURE__ */ React34.createElement(Backdrop, { canvas: canvasDocument, element: topLevelElementDom, onClose })),
|
|
4872
|
-
canvasDocument.body
|
|
4873
|
-
);
|
|
4874
|
-
}
|
|
4875
|
-
function Backdrop({
|
|
4876
|
-
canvas,
|
|
4877
|
-
element,
|
|
4878
|
-
onClose
|
|
4879
|
-
}) {
|
|
4880
|
-
const rect = useElementRect(element);
|
|
4881
|
-
const clipPath = element ? getRectPath(rect, canvas.defaultView) : void 0;
|
|
4882
|
-
const backdropStyle = {
|
|
4883
|
-
position: "fixed",
|
|
4884
|
-
top: 0,
|
|
4885
|
-
left: 0,
|
|
4886
|
-
width: "100vw",
|
|
4887
|
-
height: "100vh",
|
|
4888
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
4889
|
-
zIndex: 999,
|
|
4890
|
-
pointerEvents: "painted",
|
|
4891
|
-
cursor: "pointer",
|
|
4892
|
-
clipPath
|
|
4893
|
-
};
|
|
4894
|
-
const handleKeyDown = (event) => {
|
|
4895
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
4896
|
-
event.preventDefault();
|
|
4897
|
-
onClose();
|
|
4898
|
-
}
|
|
4899
|
-
};
|
|
4900
|
-
return /* @__PURE__ */ React34.createElement(
|
|
4901
|
-
"div",
|
|
4902
|
-
{
|
|
4903
|
-
style: backdropStyle,
|
|
4904
|
-
onClick: onClose,
|
|
4905
|
-
onKeyDown: handleKeyDown,
|
|
4906
|
-
role: "button",
|
|
4907
|
-
tabIndex: 0,
|
|
4908
|
-
"aria-label": __30("Exit component editing mode", "elementor")
|
|
4909
|
-
}
|
|
4910
|
-
);
|
|
4911
|
-
}
|
|
4912
|
-
function getRectPath(rect, viewport) {
|
|
4913
|
-
const { x, y, width, height } = rect;
|
|
4914
|
-
const { innerWidth: vw, innerHeight: vh } = viewport;
|
|
4915
|
-
const path = `path(evenodd, 'M 0 0
|
|
4916
|
-
L ${vw} 0
|
|
4917
|
-
L ${vw} ${vh}
|
|
4918
|
-
L 0 ${vh}
|
|
4919
|
-
Z
|
|
4920
|
-
M ${x} ${y}
|
|
4921
|
-
L ${x + width} ${y}
|
|
4922
|
-
L ${x + width} ${y + height}
|
|
4923
|
-
L ${x} ${y + height}
|
|
4924
|
-
L ${x} ${y}
|
|
4925
|
-
Z'
|
|
4926
|
-
)`;
|
|
4927
|
-
return path.replace(/\s{2,}/g, " ");
|
|
4928
|
-
}
|
|
4929
|
-
function BlockEditPage() {
|
|
4930
|
-
const blockV3DocumentHandlesStyles = `
|
|
4931
|
-
.elementor-editor-active {
|
|
4932
|
-
& .elementor-section-wrap.ui-sortable {
|
|
4933
|
-
display: contents;
|
|
4934
|
-
}
|
|
4935
|
-
|
|
4936
|
-
& *[data-editable-elementor-document]:not(.elementor-edit-mode):hover {
|
|
4937
|
-
& .elementor-document-handle:not(.elementor-document-save-back-handle) {
|
|
4938
|
-
display: none;
|
|
4939
|
-
|
|
4940
|
-
&::before,
|
|
4941
|
-
& .elementor-document-handle__inner {
|
|
4942
|
-
display: none;
|
|
4943
|
-
}
|
|
4944
|
-
}
|
|
4945
|
-
}
|
|
4946
|
-
}
|
|
4947
|
-
`;
|
|
4948
|
-
return /* @__PURE__ */ React34.createElement("style", { "data-e-style-id": "e-block-v3-document-handles-styles" }, blockV3DocumentHandlesStyles);
|
|
4949
|
-
}
|
|
4950
|
-
|
|
4951
|
-
// src/extended/components/edit-component/edit-component.tsx
|
|
4952
|
-
function EditComponent() {
|
|
4953
|
-
const currentComponentId = useCurrentComponentId();
|
|
4954
|
-
useHandleDocumentSwitches();
|
|
4955
|
-
const navigateBack = useNavigateBack();
|
|
4956
|
-
const onClose = throttle2(navigateBack, 100);
|
|
4957
|
-
const topLevelElementDom = useComponentDOMElement(currentComponentId ?? void 0);
|
|
4958
|
-
if (!currentComponentId) {
|
|
4959
|
-
return null;
|
|
4960
|
-
}
|
|
4961
|
-
return /* @__PURE__ */ React35.createElement(ComponentModal, { topLevelElementDom, onClose });
|
|
4962
|
-
}
|
|
4963
|
-
function useHandleDocumentSwitches() {
|
|
4964
|
-
const documentsManager = getV1DocumentsManager5();
|
|
4965
|
-
const currentComponentId = useCurrentComponentId();
|
|
4966
|
-
const path = useSelector5(selectPath);
|
|
4967
|
-
useEffect6(() => {
|
|
4968
|
-
return listenTo(commandEndEvent2("editor/documents/open"), () => {
|
|
4969
|
-
const nextDocument = documentsManager.getCurrent();
|
|
4970
|
-
if (nextDocument.id === currentComponentId) {
|
|
4971
|
-
return;
|
|
4972
|
-
}
|
|
4973
|
-
if (currentComponentId) {
|
|
4974
|
-
apiClient.unlockComponent(currentComponentId);
|
|
4975
|
-
}
|
|
4976
|
-
resetSanitizedComponents();
|
|
4977
|
-
const isComponent2 = nextDocument.config.type === COMPONENT_DOCUMENT_TYPE;
|
|
4978
|
-
if (!isComponent2) {
|
|
4979
|
-
updateCurrentComponent({ path: [], currentComponentId: null });
|
|
4980
|
-
return;
|
|
4981
|
-
}
|
|
4982
|
-
updateCurrentComponent({
|
|
4983
|
-
path: getUpdatedComponentPath(path, nextDocument),
|
|
4984
|
-
currentComponentId: nextDocument.id
|
|
4985
|
-
});
|
|
4986
|
-
});
|
|
4987
|
-
}, [path, documentsManager, currentComponentId]);
|
|
4988
|
-
}
|
|
4989
|
-
function getUpdatedComponentPath(path, nextDocument) {
|
|
4990
|
-
const componentIndex = path.findIndex(({ componentId }) => componentId === nextDocument.id);
|
|
4991
|
-
if (componentIndex >= 0) {
|
|
4992
|
-
return path.slice(0, componentIndex + 1);
|
|
4993
|
-
}
|
|
4994
|
-
const instanceId = nextDocument?.container.view?.el?.dataset.id;
|
|
4995
|
-
const instanceTitle = getInstanceTitle(instanceId, path);
|
|
4996
|
-
return [
|
|
4997
|
-
...path,
|
|
4998
|
-
{
|
|
4999
|
-
instanceId,
|
|
5000
|
-
instanceTitle,
|
|
5001
|
-
componentId: nextDocument.id
|
|
5002
|
-
}
|
|
5003
|
-
];
|
|
5004
|
-
}
|
|
5005
|
-
function getInstanceTitle(instanceId, path) {
|
|
5006
|
-
if (!instanceId) {
|
|
5007
|
-
return void 0;
|
|
5008
|
-
}
|
|
5009
|
-
const documentsManager = getV1DocumentsManager5();
|
|
5010
|
-
const parentDocId = path.at(-1)?.componentId ?? documentsManager.getInitialId();
|
|
5011
|
-
const parentDoc = documentsManager.get(parentDocId);
|
|
5012
|
-
const parentContainer = parentDoc?.container;
|
|
5013
|
-
const widget = parentContainer?.children?.findRecursive?.(
|
|
5014
|
-
(container) => container.id === instanceId
|
|
5015
|
-
);
|
|
5016
|
-
const editorSettings = widget?.model?.get?.("editor_settings");
|
|
5017
|
-
return editorSettings?.title;
|
|
5018
|
-
}
|
|
5019
|
-
function useComponentDOMElement(id2) {
|
|
5020
|
-
const { componentContainerDomElement, topLevelElementDom } = getComponentDOMElements(id2);
|
|
5021
|
-
const [currentElementDom, setCurrentElementDom] = useState11(topLevelElementDom);
|
|
5022
|
-
useEffect6(() => {
|
|
5023
|
-
setCurrentElementDom(topLevelElementDom);
|
|
5024
|
-
}, [topLevelElementDom]);
|
|
5025
|
-
useEffect6(() => {
|
|
5026
|
-
if (!componentContainerDomElement) {
|
|
5027
|
-
return;
|
|
5028
|
-
}
|
|
5029
|
-
const mutationObserver = new MutationObserver(() => {
|
|
5030
|
-
const newElementDom = componentContainerDomElement.children[0];
|
|
5031
|
-
setCurrentElementDom(newElementDom);
|
|
5032
|
-
});
|
|
5033
|
-
mutationObserver.observe(componentContainerDomElement, { childList: true });
|
|
5034
|
-
return () => {
|
|
5035
|
-
mutationObserver.disconnect();
|
|
5036
|
-
};
|
|
5037
|
-
}, [componentContainerDomElement]);
|
|
5038
|
-
return currentElementDom;
|
|
5039
|
-
}
|
|
5040
|
-
function getComponentDOMElements(id2) {
|
|
5041
|
-
if (!id2) {
|
|
5042
|
-
return { componentContainerDomElement: null, topLevelElementDom: null };
|
|
5043
|
-
}
|
|
5044
|
-
const documentsManager = getV1DocumentsManager5();
|
|
5045
|
-
const currentComponent = documentsManager.get(id2);
|
|
5046
|
-
const componentContainer = currentComponent?.container;
|
|
5047
|
-
const componentContainerDomElement = componentContainer?.view?.el?.children?.[0] ?? null;
|
|
5048
|
-
const topLevelElementDom = componentContainerDomElement?.children[0] ?? null;
|
|
5049
|
-
return { componentContainerDomElement, topLevelElementDom };
|
|
5050
|
-
}
|
|
5051
|
-
|
|
5052
|
-
// src/extended/components/instance-editing-panel/instance-editing-panel.tsx
|
|
5053
|
-
import * as React36 from "react";
|
|
5054
|
-
import { PencilIcon as PencilIcon3 } from "@elementor/icons";
|
|
5055
|
-
import { Box as Box16 } from "@elementor/ui";
|
|
5056
|
-
import { __ as __31 } from "@wordpress/i18n";
|
|
5057
|
-
function ExtendedInstanceEditingPanel() {
|
|
5058
|
-
const { canEdit } = useComponentsPermissions();
|
|
5059
|
-
const data = useInstancePanelData();
|
|
5060
|
-
if (!data) {
|
|
5061
|
-
return null;
|
|
5062
|
-
}
|
|
5063
|
-
const { componentId, component, overrides, overridableProps, groups, isEmpty, componentInstanceId } = data;
|
|
5064
|
-
const panelTitle = __31("Edit %s", "elementor").replace("%s", component.name);
|
|
5065
|
-
const handleEditComponent = () => switchToComponent(componentId, componentInstanceId);
|
|
5066
|
-
return /* @__PURE__ */ React36.createElement(Box16, { "data-testid": "instance-editing-panel" }, /* @__PURE__ */ React36.createElement(
|
|
5067
|
-
ComponentInstanceProvider,
|
|
5068
|
-
{
|
|
5069
|
-
componentId,
|
|
5070
|
-
overrides,
|
|
5071
|
-
overridableProps
|
|
5072
|
-
},
|
|
5073
|
-
/* @__PURE__ */ React36.createElement(
|
|
5074
|
-
InstancePanelHeader,
|
|
5075
|
-
{
|
|
5076
|
-
componentName: component.name,
|
|
5077
|
-
actions: canEdit ? /* @__PURE__ */ React36.createElement(
|
|
5078
|
-
EditComponentAction,
|
|
5079
|
-
{
|
|
5080
|
-
label: panelTitle,
|
|
5081
|
-
onClick: handleEditComponent,
|
|
5082
|
-
icon: PencilIcon3
|
|
5083
|
-
}
|
|
5084
|
-
) : void 0
|
|
5085
|
-
}
|
|
5086
|
-
),
|
|
5087
|
-
/* @__PURE__ */ React36.createElement(
|
|
5088
|
-
InstancePanelBody,
|
|
5089
|
-
{
|
|
5090
|
-
groups,
|
|
5091
|
-
isEmpty,
|
|
5092
|
-
emptyState: /* @__PURE__ */ React36.createElement(EmptyState2, { onEditComponent: canEdit ? handleEditComponent : void 0 }),
|
|
5093
|
-
componentInstanceId
|
|
5094
|
-
}
|
|
5095
|
-
)
|
|
5096
|
-
));
|
|
5097
|
-
}
|
|
5098
|
-
|
|
5099
|
-
// src/extended/components/overridable-props/overridable-prop-control.tsx
|
|
5100
|
-
import * as React37 from "react";
|
|
5101
|
-
import {
|
|
5102
|
-
ControlReplacementsProvider as ControlReplacementsProvider2,
|
|
5103
|
-
getControlReplacements as getControlReplacements2,
|
|
5104
|
-
PropKeyProvider as PropKeyProvider2,
|
|
5105
|
-
PropProvider as PropProvider2,
|
|
5106
|
-
useBoundProp as useBoundProp2,
|
|
5107
|
-
useControlReplacement
|
|
5108
|
-
} from "@elementor/editor-controls";
|
|
5109
|
-
import { createTopLevelObjectType as createTopLevelObjectType2, useElement as useElement3 } from "@elementor/editor-editing-panel";
|
|
5110
|
-
function OverridablePropControl({
|
|
5111
|
-
OriginalControl: OriginalControl2,
|
|
5112
|
-
...props
|
|
5113
|
-
}) {
|
|
5114
|
-
const { elementType } = useElement3();
|
|
5115
|
-
const { value, bind, setValue, placeholder, ...propContext } = useBoundProp2(componentOverridablePropTypeUtil);
|
|
5116
|
-
const componentId = useCurrentComponentId();
|
|
5117
|
-
const overridableProps = useOverridableProps(componentId);
|
|
5118
|
-
const filteredReplacements = getControlReplacements2().filter(
|
|
5119
|
-
(r) => !r.id || r.id !== OVERRIDABLE_PROP_REPLACEMENT_ID
|
|
5120
|
-
);
|
|
5121
|
-
if (!componentId) {
|
|
5122
|
-
return null;
|
|
5123
|
-
}
|
|
5124
|
-
if (!value?.override_key) {
|
|
5125
|
-
throw new Error("Override key is required");
|
|
5126
|
-
}
|
|
5127
|
-
const isComponentInstance2 = elementType.key === "e-component";
|
|
5128
|
-
const overridablePropData = overridableProps?.props?.[value.override_key];
|
|
5129
|
-
const setOverridableValue = (newValue) => {
|
|
5130
|
-
const propValue2 = {
|
|
5131
|
-
...value,
|
|
5132
|
-
origin_value: newValue[bind]
|
|
5133
|
-
};
|
|
5134
|
-
setValue(propValue2);
|
|
5135
|
-
if (!isComponentInstance2) {
|
|
5136
|
-
updateOverridableProp(componentId, propValue2, overridablePropData?.originPropFields);
|
|
5137
|
-
}
|
|
5138
|
-
};
|
|
5139
|
-
const defaultPropType = elementType.propsSchema[bind];
|
|
5140
|
-
const overridePropType = overridablePropData ? getPropTypeForComponentOverride(overridablePropData) : void 0;
|
|
5141
|
-
const resolvedPropType = overridePropType ?? defaultPropType;
|
|
5142
|
-
if (!resolvedPropType) {
|
|
5143
|
-
return null;
|
|
5144
|
-
}
|
|
5145
|
-
const propType = createTopLevelObjectType2({
|
|
5146
|
-
schema: {
|
|
5147
|
-
[bind]: resolvedPropType
|
|
5148
|
-
}
|
|
5149
|
-
});
|
|
5150
|
-
const propValue = isComponentInstance2 ? (value.origin_value?.value).override_value : value.origin_value;
|
|
5151
|
-
const objectPlaceholder = placeholder ? { [bind]: placeholder } : void 0;
|
|
5152
|
-
return /* @__PURE__ */ React37.createElement(OverridablePropProvider, { value }, /* @__PURE__ */ React37.createElement(
|
|
5153
|
-
PropProvider2,
|
|
5154
|
-
{
|
|
5155
|
-
...propContext,
|
|
5156
|
-
propType,
|
|
5157
|
-
setValue: setOverridableValue,
|
|
5158
|
-
value: {
|
|
5159
|
-
[bind]: propValue
|
|
5160
|
-
},
|
|
5161
|
-
placeholder: objectPlaceholder
|
|
5162
|
-
},
|
|
5163
|
-
/* @__PURE__ */ React37.createElement(PropKeyProvider2, { bind }, /* @__PURE__ */ React37.createElement(ControlReplacementsProvider2, { replacements: filteredReplacements }, /* @__PURE__ */ React37.createElement(ControlWithReplacements, { OriginalControl: OriginalControl2, props })))
|
|
5164
|
-
));
|
|
5165
|
-
}
|
|
5166
|
-
function ControlWithReplacements({
|
|
5167
|
-
OriginalControl: OriginalControl2,
|
|
5168
|
-
props
|
|
5169
|
-
}) {
|
|
5170
|
-
const { ControlToRender, isReplaced } = useControlReplacement(OriginalControl2);
|
|
5171
|
-
if (isReplaced) {
|
|
5172
|
-
const ReplacementControl = ControlToRender;
|
|
5173
|
-
return /* @__PURE__ */ React37.createElement(ReplacementControl, { ...props, OriginalControl: OriginalControl2 });
|
|
5174
|
-
}
|
|
5175
|
-
return /* @__PURE__ */ React37.createElement(OriginalControl2, { ...props });
|
|
5176
|
-
}
|
|
5177
|
-
|
|
5178
|
-
// src/extended/components/overridable-props/overridable-prop-indicator.tsx
|
|
5179
|
-
import * as React39 from "react";
|
|
5180
|
-
import { useBoundProp as useBoundProp3 } from "@elementor/editor-controls";
|
|
5181
|
-
import { useElement as useElement4 } from "@elementor/editor-editing-panel";
|
|
5182
|
-
import { getWidgetsCache as getWidgetsCache3 } from "@elementor/editor-elements";
|
|
5183
|
-
import { bindPopover as bindPopover2, bindTrigger as bindTrigger4, Popover as Popover4, Tooltip as Tooltip6, usePopupState as usePopupState4 } from "@elementor/ui";
|
|
5184
|
-
import { __ as __33 } from "@wordpress/i18n";
|
|
5185
|
-
|
|
5186
|
-
// src/extended/store/actions/set-overridable-prop.ts
|
|
5187
|
-
import { generateUniqueId as generateUniqueId4 } from "@elementor/utils";
|
|
5188
|
-
function setOverridableProp({
|
|
5189
|
-
componentId,
|
|
5190
|
-
overrideKey,
|
|
5191
|
-
elementId,
|
|
5192
|
-
label,
|
|
5193
|
-
groupId,
|
|
5194
|
-
propKey,
|
|
5195
|
-
elType,
|
|
5196
|
-
widgetType,
|
|
5197
|
-
originValue,
|
|
5198
|
-
originPropFields,
|
|
5199
|
-
source
|
|
5200
|
-
}) {
|
|
5201
|
-
const overridableProps = componentsSelectors.getOverridableProps(componentId);
|
|
5202
|
-
if (!overridableProps) {
|
|
5203
|
-
return;
|
|
5204
|
-
}
|
|
5205
|
-
const existingOverridableProp = overrideKey ? overridableProps.props[overrideKey] : null;
|
|
5206
|
-
const duplicatedTargetProps = Object.values(overridableProps.props).filter(
|
|
5207
|
-
(prop) => prop.elementId === elementId && prop.propKey === propKey && prop !== existingOverridableProp
|
|
5208
|
-
);
|
|
5209
|
-
const { groups: groupsAfterResolve, groupId: currentGroupId } = resolveOrCreateGroup(
|
|
5210
|
-
overridableProps.groups,
|
|
5211
|
-
groupId || existingOverridableProp?.groupId || void 0
|
|
5212
|
-
);
|
|
5213
|
-
const overridableProp = {
|
|
5214
|
-
overrideKey: existingOverridableProp?.overrideKey || generateUniqueId4("prop"),
|
|
5215
|
-
label,
|
|
5216
|
-
elementId,
|
|
5217
|
-
propKey,
|
|
5218
|
-
widgetType,
|
|
5219
|
-
elType,
|
|
5220
|
-
originValue,
|
|
5221
|
-
groupId: currentGroupId,
|
|
5222
|
-
originPropFields
|
|
5223
|
-
};
|
|
5224
|
-
const stateAfterRemovingDuplicates = removePropsFromState(
|
|
5225
|
-
{ ...overridableProps, groups: groupsAfterResolve },
|
|
5226
|
-
duplicatedTargetProps
|
|
5227
|
-
);
|
|
5228
|
-
const props = {
|
|
5229
|
-
...stateAfterRemovingDuplicates.props,
|
|
5230
|
-
[overridableProp.overrideKey]: overridableProp
|
|
5231
|
-
};
|
|
5232
|
-
let groups = addPropToGroup(stateAfterRemovingDuplicates.groups, currentGroupId, overridableProp.overrideKey);
|
|
5233
|
-
groups = ensureGroupInOrder(groups, currentGroupId);
|
|
5234
|
-
const isChangingGroups = existingOverridableProp && existingOverridableProp.groupId !== currentGroupId;
|
|
5235
|
-
if (isChangingGroups) {
|
|
5236
|
-
groups = removePropFromGroup(groups, existingOverridableProp.groupId, overridableProp.overrideKey);
|
|
5237
|
-
}
|
|
5238
|
-
componentsActions.setOverridableProps(componentId, { props, groups });
|
|
5239
|
-
const isNewProperty = !existingOverridableProp;
|
|
5240
|
-
if (isNewProperty) {
|
|
5241
|
-
const currentComponent = componentsSelectors.getCurrentComponent();
|
|
5242
|
-
trackComponentEvent({
|
|
5243
|
-
action: "propertyExposed",
|
|
5244
|
-
source,
|
|
5245
|
-
component_uid: currentComponent?.uid,
|
|
5246
|
-
property_id: overridableProp.overrideKey,
|
|
5247
|
-
property_path: propKey,
|
|
5248
|
-
property_name: label,
|
|
5249
|
-
element_type: widgetType ?? elType
|
|
5250
|
-
});
|
|
5251
|
-
}
|
|
5252
|
-
return overridableProp;
|
|
5253
|
-
}
|
|
5254
|
-
|
|
5255
|
-
// src/extended/components/overridable-props/indicator.tsx
|
|
5256
|
-
import * as React38 from "react";
|
|
5257
|
-
import { forwardRef as forwardRef3 } from "react";
|
|
5258
|
-
import { CheckIcon, PlusIcon } from "@elementor/icons";
|
|
5259
|
-
import { Box as Box17, styled as styled4 } from "@elementor/ui";
|
|
5260
|
-
import { __ as __32 } from "@wordpress/i18n";
|
|
5261
|
-
var SIZE2 = "tiny";
|
|
5262
|
-
var IconContainer = styled4(Box17)`
|
|
5263
|
-
pointer-events: none;
|
|
5264
|
-
opacity: 0;
|
|
5265
|
-
transition: opacity 0.2s ease-in-out;
|
|
5266
|
-
|
|
5267
|
-
& > svg {
|
|
5268
|
-
position: absolute;
|
|
5269
|
-
top: 50%;
|
|
5270
|
-
left: 50%;
|
|
5271
|
-
transform: translate( -50%, -50% );
|
|
5272
|
-
width: 10px;
|
|
5273
|
-
height: 10px;
|
|
5274
|
-
fill: ${({ theme }) => theme.palette.primary.contrastText};
|
|
5275
|
-
stroke: ${({ theme }) => theme.palette.primary.contrastText};
|
|
5276
|
-
stroke-width: 2px;
|
|
5277
|
-
}
|
|
5278
|
-
`;
|
|
5279
|
-
var Content = styled4(Box17)`
|
|
5280
|
-
position: relative;
|
|
5281
|
-
display: flex;
|
|
5282
|
-
align-items: center;
|
|
5283
|
-
justify-content: center;
|
|
5284
|
-
cursor: pointer;
|
|
5285
|
-
width: 16px;
|
|
5286
|
-
height: 16px;
|
|
5287
|
-
margin-inline: ${({ theme }) => theme.spacing(0.5)};
|
|
5288
|
-
|
|
5289
|
-
&:before {
|
|
5290
|
-
content: '';
|
|
5291
|
-
display: block;
|
|
5292
|
-
position: absolute;
|
|
5293
|
-
top: 50%;
|
|
5294
|
-
left: 50%;
|
|
5295
|
-
transform: translate( -50%, -50% ) rotate( 45deg );
|
|
5296
|
-
width: 5px;
|
|
5297
|
-
height: 5px;
|
|
5298
|
-
border-radius: 1px;
|
|
5299
|
-
background-color: ${({ theme }) => theme.palette.primary.main};
|
|
5300
|
-
transition: all 0.1s ease-in-out;
|
|
5301
|
-
}
|
|
5302
|
-
|
|
5303
|
-
&:hover,
|
|
5304
|
-
&.enlarged {
|
|
5305
|
-
&:before {
|
|
5306
|
-
width: 12px;
|
|
5307
|
-
height: 12px;
|
|
5308
|
-
border-radius: 2px;
|
|
5309
|
-
}
|
|
5310
|
-
|
|
5311
|
-
.icon {
|
|
5312
|
-
opacity: 1;
|
|
5313
|
-
}
|
|
5314
|
-
}
|
|
5315
|
-
`;
|
|
5316
|
-
var Indicator2 = forwardRef3(({ isOpen, isOverridable, ...props }, ref) => /* @__PURE__ */ React38.createElement(
|
|
5317
|
-
Content,
|
|
5318
|
-
{
|
|
5319
|
-
role: "button",
|
|
5320
|
-
ref,
|
|
5321
|
-
...props,
|
|
5322
|
-
className: isOpen || isOverridable ? "enlarged" : "",
|
|
5323
|
-
"aria-label": isOverridable ? __32("Overridable property", "elementor") : __32("Make prop overridable", "elementor")
|
|
5324
|
-
},
|
|
5325
|
-
/* @__PURE__ */ React38.createElement(IconContainer, { className: "icon" }, isOverridable ? /* @__PURE__ */ React38.createElement(CheckIcon, { fontSize: SIZE2 }) : /* @__PURE__ */ React38.createElement(PlusIcon, { fontSize: SIZE2 }))
|
|
5326
|
-
));
|
|
5327
|
-
|
|
5328
|
-
// src/extended/components/overridable-props/overridable-prop-indicator.tsx
|
|
5329
|
-
function OverridablePropIndicator() {
|
|
5330
|
-
const { propType } = useBoundProp3();
|
|
5331
|
-
const componentId = useCurrentComponentId();
|
|
5332
|
-
const overridableProps = useSanitizeOverridableProps(componentId);
|
|
5333
|
-
if (!isPropAllowed(propType) || !componentId || !overridableProps) {
|
|
5334
|
-
return null;
|
|
5335
|
-
}
|
|
5336
|
-
return /* @__PURE__ */ React39.createElement(Content2, { componentId, overridableProps });
|
|
5337
|
-
}
|
|
5338
|
-
function Content2({ componentId, overridableProps }) {
|
|
5339
|
-
const {
|
|
5340
|
-
element: { id: elementId },
|
|
5341
|
-
elementType
|
|
5342
|
-
} = useElement4();
|
|
5343
|
-
const { value, bind, propType } = useBoundProp3();
|
|
5344
|
-
const contextOverridableValue = useOverridablePropValue();
|
|
5345
|
-
const componentInstanceElement = useComponentInstanceElement();
|
|
5346
|
-
const { value: boundPropOverridableValue, setValue: setOverridableValue } = useBoundProp3(
|
|
5347
|
-
componentOverridablePropTypeUtil
|
|
5348
|
-
);
|
|
5349
|
-
const overridableValue = boundPropOverridableValue ?? contextOverridableValue;
|
|
5350
|
-
const popupState = usePopupState4({
|
|
5351
|
-
variant: "popover"
|
|
5352
|
-
});
|
|
5353
|
-
const triggerProps = bindTrigger4(popupState);
|
|
5354
|
-
const popoverProps = bindPopover2(popupState);
|
|
5355
|
-
const { elType } = getWidgetsCache3()?.[elementType.key] ?? { elType: "widget" };
|
|
5356
|
-
const handleSubmit = ({ label, group }) => {
|
|
5357
|
-
const propTypeDefault = propType.default ?? {};
|
|
5358
|
-
const originValue = resolveOverridePropValue(overridableValue?.origin_value) ?? value ?? propTypeDefault;
|
|
5359
|
-
const matchingOverridableProp = overridableValue ? overridableProps?.props?.[overridableValue.override_key] : void 0;
|
|
5360
|
-
const overridablePropConfig = setOverridableProp({
|
|
5361
|
-
componentId,
|
|
5362
|
-
overrideKey: overridableValue?.override_key ?? null,
|
|
5363
|
-
elementId: componentInstanceElement?.element.id ?? elementId,
|
|
5364
|
-
label,
|
|
5365
|
-
groupId: group,
|
|
5366
|
-
propKey: bind,
|
|
5367
|
-
elType: elType ?? "widget",
|
|
5368
|
-
widgetType: componentInstanceElement?.elementType.key ?? elementType.key,
|
|
5369
|
-
originValue,
|
|
5370
|
-
originPropFields: matchingOverridableProp?.originPropFields,
|
|
5371
|
-
source: "user"
|
|
5372
|
-
});
|
|
5373
|
-
if (!overridableValue && overridablePropConfig) {
|
|
5374
|
-
setOverridableValue({
|
|
5375
|
-
override_key: overridablePropConfig.overrideKey,
|
|
5376
|
-
origin_value: originValue
|
|
5377
|
-
});
|
|
5378
|
-
}
|
|
5379
|
-
popupState.close();
|
|
5380
|
-
};
|
|
5381
|
-
const overridableConfig = overridableValue ? getOverridableProp({ componentId, overrideKey: overridableValue.override_key }) : void 0;
|
|
5382
|
-
return /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Tooltip6, { placement: "top", title: __33("Override Property", "elementor") }, /* @__PURE__ */ React39.createElement(Indicator2, { ...triggerProps, isOpen: !!popoverProps.open, isOverridable: !!overridableValue })), /* @__PURE__ */ React39.createElement(
|
|
5383
|
-
Popover4,
|
|
5384
|
-
{
|
|
5385
|
-
disableScrollLock: true,
|
|
5386
|
-
anchorOrigin: {
|
|
5387
|
-
vertical: "bottom",
|
|
5388
|
-
horizontal: "right"
|
|
5389
|
-
},
|
|
5390
|
-
transformOrigin: {
|
|
5391
|
-
vertical: "top",
|
|
5392
|
-
horizontal: "right"
|
|
5393
|
-
},
|
|
5394
|
-
PaperProps: {
|
|
5395
|
-
sx: { my: 2.5 }
|
|
5396
|
-
},
|
|
5397
|
-
...popoverProps
|
|
5398
|
-
},
|
|
5399
|
-
/* @__PURE__ */ React39.createElement(
|
|
5400
|
-
OverridablePropForm,
|
|
5401
|
-
{
|
|
5402
|
-
onSubmit: handleSubmit,
|
|
5403
|
-
groups: overridableProps?.groups.order.map((groupId) => ({
|
|
5404
|
-
value: groupId,
|
|
5405
|
-
label: overridableProps.groups.items[groupId].label
|
|
5406
|
-
})),
|
|
5407
|
-
existingLabels: Object.values(overridableProps?.props ?? {}).map((prop) => prop.label),
|
|
5408
|
-
currentValue: overridableConfig
|
|
5409
|
-
}
|
|
5410
|
-
)
|
|
5411
|
-
));
|
|
5412
|
-
}
|
|
5413
|
-
function isPropAllowed(propType) {
|
|
5414
|
-
return propType.meta.overridable !== false;
|
|
5415
|
-
}
|
|
5416
|
-
|
|
5417
|
-
// src/extended/mcp/index.ts
|
|
5418
|
-
import { getMCPByDomain as getMCPByDomain2 } from "@elementor/editor-mcp";
|
|
5419
|
-
|
|
5420
|
-
// src/extended/mcp/save-as-component-tool.ts
|
|
5421
|
-
import { DOCUMENT_STRUCTURE_URI, WIDGET_SCHEMA_URI } from "@elementor/editor-canvas";
|
|
5422
|
-
import { getContainer as getContainer6, getElementType as getElementType4, getWidgetsCache as getWidgetsCache4 } from "@elementor/editor-elements";
|
|
5423
|
-
import { getMCPByDomain, toolPrompts } from "@elementor/editor-mcp";
|
|
5424
|
-
import { AxiosError } from "@elementor/http-client";
|
|
5425
|
-
import { z as z6 } from "@elementor/schema";
|
|
5426
|
-
import { generateUniqueId as generateUniqueId5 } from "@elementor/utils";
|
|
5427
|
-
var InputSchema = {
|
|
5428
|
-
element_id: z6.string().describe(
|
|
5429
|
-
'The unique identifier of the element to save as a component. Use the "list-elements" tool to find available element IDs in the current document.'
|
|
5430
|
-
),
|
|
5431
|
-
component_name: z6.string().describe("The name for the new component. Should be descriptive and unique among existing components."),
|
|
5432
|
-
overridable_props: z6.object({
|
|
5433
|
-
props: z6.record(
|
|
5434
|
-
z6.object({
|
|
5435
|
-
elementId: z6.string().describe("The id of the child element that you want to override its settings"),
|
|
5436
|
-
propKey: z6.string().describe(
|
|
5437
|
-
'The property key of the child element that you want to override its settings (e.g., "text", "url", "tag"). To get the available propKeys for an element, use the "get-element-type-config" tool.'
|
|
5438
|
-
),
|
|
5439
|
-
label: z6.string().describe(
|
|
5440
|
-
'A unique, user-friendly display name for this property (e.g., "Hero Headline", "CTA Button Text"). Must be unique within the same component.'
|
|
5441
|
-
),
|
|
5442
|
-
group: z6.string().optional().describe("Non unique, optional property grouping")
|
|
5443
|
-
})
|
|
5444
|
-
)
|
|
5445
|
-
}).optional().describe(
|
|
5446
|
-
'Overridable properties configuration. Specify which CHILD element properties can be customized. Only elementId and propKey are required; To get the available propKeys for a child element you must use the "get-element-type-config" tool.'
|
|
5447
|
-
),
|
|
5448
|
-
groups: z6.array(z6.string()).describe("Property Groups, by order, unique values").optional()
|
|
5449
|
-
};
|
|
5450
|
-
var OutputSchema = {
|
|
5451
|
-
message: z6.string().optional().describe("Additional information about the operation result"),
|
|
5452
|
-
component_uid: z6.string().optional().describe("The unique identifier of the newly created component (only present on success)")
|
|
5453
|
-
};
|
|
5454
|
-
var ERROR_MESSAGES3 = {
|
|
5455
|
-
ELEMENT_NOT_FOUND: "Element not found. Use 'list-elements' to get valid element IDs.",
|
|
5456
|
-
ELEMENT_NOT_ONE_OF_TYPES: (validTypes) => `Element is not one of the following types: ${validTypes.join(", ")}`,
|
|
5457
|
-
ELEMENT_IS_LOCKED: "Cannot save a locked element as a component."
|
|
5458
|
-
};
|
|
5459
|
-
var handleSaveAsComponent = async (params) => {
|
|
5460
|
-
const {
|
|
5461
|
-
groups = [],
|
|
5462
|
-
element_id: elementId,
|
|
5463
|
-
component_name: componentName,
|
|
5464
|
-
overridable_props: overridablePropsInput
|
|
5465
|
-
} = params;
|
|
5466
|
-
const validElementTypes = getValidElementTypes();
|
|
5467
|
-
const container = getContainer6(elementId);
|
|
5468
|
-
if (!container) {
|
|
5469
|
-
throw new Error(ERROR_MESSAGES3.ELEMENT_NOT_FOUND);
|
|
5470
|
-
}
|
|
5471
|
-
const elType = container.model.get("elType");
|
|
5472
|
-
if (!validElementTypes.includes(elType)) {
|
|
5473
|
-
throw new Error(ERROR_MESSAGES3.ELEMENT_NOT_ONE_OF_TYPES(validElementTypes));
|
|
5474
|
-
}
|
|
5475
|
-
const element = container.model.toJSON({ remove: ["default"] });
|
|
5476
|
-
if (element?.isLocked) {
|
|
5477
|
-
throw new Error(ERROR_MESSAGES3.ELEMENT_IS_LOCKED);
|
|
5478
|
-
}
|
|
5479
|
-
const groupsWithDefaultGroup = groups.indexOf("Default") >= 0 ? [...groups] : ["Default", ...groups];
|
|
5480
|
-
const propertyGroups = groupsWithDefaultGroup.map((groupName) => ({
|
|
5481
|
-
id: generateUniqueId5("group"),
|
|
5482
|
-
label: groupName,
|
|
5483
|
-
props: []
|
|
5484
|
-
}));
|
|
5485
|
-
const overridableProps = overridablePropsInput ? enrichOverridableProps(overridablePropsInput, element, propertyGroups) : void 0;
|
|
5486
|
-
if (overridableProps) {
|
|
5487
|
-
updateElementDataWithOverridableProps(element, overridableProps);
|
|
5488
|
-
}
|
|
5489
|
-
const uid = generateUniqueId5("component");
|
|
5490
|
-
try {
|
|
5491
|
-
await apiClient.validate({
|
|
5492
|
-
items: [
|
|
5493
|
-
{ uid, title: componentName, elements: [element], settings: { overridable_props: overridableProps } }
|
|
5494
|
-
]
|
|
5495
|
-
});
|
|
5496
|
-
} catch (error) {
|
|
5497
|
-
if (error instanceof AxiosError) {
|
|
5498
|
-
throw new Error(error.response?.data.messge);
|
|
5499
|
-
}
|
|
5500
|
-
throw new Error("Unknown error");
|
|
5501
|
-
}
|
|
5502
|
-
await createUnpublishedComponent({
|
|
5503
|
-
name: componentName,
|
|
5504
|
-
element,
|
|
5505
|
-
eventData: null,
|
|
5506
|
-
uid,
|
|
5507
|
-
overridableProps,
|
|
5508
|
-
source: "mcp_tool"
|
|
5509
|
-
});
|
|
5510
|
-
return {
|
|
5511
|
-
status: "ok",
|
|
5512
|
-
message: `Component "${componentName}" created successfully.`,
|
|
5513
|
-
component_uid: uid
|
|
5514
|
-
};
|
|
5515
|
-
};
|
|
5516
|
-
function enrichOverridableProps(input, rootElement, propertGroups) {
|
|
5517
|
-
const enrichedProps = {};
|
|
5518
|
-
const enrichedGroups = {};
|
|
5519
|
-
const defaultGroup = propertGroups.find((g) => g.label === "Default");
|
|
5520
|
-
if (!defaultGroup) {
|
|
5521
|
-
throw new Error("Internal mcp error: could not generate default group");
|
|
5522
|
-
}
|
|
5523
|
-
Object.entries(input.props).forEach(([, prop]) => {
|
|
5524
|
-
const { elementId, propKey, label, group = "Default" } = prop;
|
|
5525
|
-
const targetGroup = propertGroups.find((g) => g.label === group) || defaultGroup;
|
|
5526
|
-
const targetGroupId = targetGroup.id;
|
|
5527
|
-
const element = findElementById(rootElement, elementId);
|
|
5528
|
-
if (!element) {
|
|
5529
|
-
throw new Error(`Element with ID "${elementId}" not found in component`);
|
|
5530
|
-
}
|
|
5531
|
-
const elType = element.elType;
|
|
5532
|
-
const widgetType = element.widgetType || element.elType;
|
|
5533
|
-
const elementType = getElementType4(widgetType);
|
|
5534
|
-
if (!elementType) {
|
|
5535
|
-
throw new Error(
|
|
5536
|
-
`Element type "${widgetType}" is not atomic or does not have a settings schema. Cannot expose property "${propKey}" for element "${elementId}".`
|
|
5537
|
-
);
|
|
5538
|
-
}
|
|
5539
|
-
if (!elementType.propsSchema[propKey]) {
|
|
5540
|
-
const availableProps = Object.keys(elementType.propsSchema).join(", ");
|
|
5541
|
-
throw new Error(
|
|
5542
|
-
`Property "${propKey}" does not exist in element "${elementId}" (type: ${widgetType}). Available properties: ${availableProps}`
|
|
5543
|
-
);
|
|
5544
|
-
}
|
|
5545
|
-
const overrideKey = generateUniqueId5("prop");
|
|
5546
|
-
const originValue = element.settings?.[propKey] ? element.settings[propKey] : elementType.propsSchema[propKey].default ?? null;
|
|
5547
|
-
if (!enrichedGroups[targetGroupId]) {
|
|
5548
|
-
enrichedGroups[targetGroupId] = {
|
|
5549
|
-
id: targetGroupId,
|
|
5550
|
-
label: targetGroup.label,
|
|
5551
|
-
props: []
|
|
5552
|
-
};
|
|
5553
|
-
}
|
|
5554
|
-
enrichedGroups[targetGroupId].props.push(overrideKey);
|
|
5555
|
-
enrichedProps[overrideKey] = {
|
|
5556
|
-
overrideKey,
|
|
5557
|
-
label,
|
|
5558
|
-
elementId,
|
|
5559
|
-
propKey,
|
|
5560
|
-
elType,
|
|
5561
|
-
widgetType,
|
|
5562
|
-
originValue,
|
|
5563
|
-
groupId: targetGroupId
|
|
5564
|
-
};
|
|
5565
|
-
});
|
|
5566
|
-
return {
|
|
5567
|
-
props: enrichedProps,
|
|
5568
|
-
groups: {
|
|
5569
|
-
items: enrichedGroups,
|
|
5570
|
-
order: [defaultGroup.id]
|
|
5571
|
-
}
|
|
5572
|
-
};
|
|
5573
|
-
}
|
|
5574
|
-
function updateElementDataWithOverridableProps(rootElement, overridableProps) {
|
|
5575
|
-
Object.values(overridableProps.props).forEach((prop) => {
|
|
5576
|
-
const element = findElementById(rootElement, prop.elementId);
|
|
5577
|
-
if (!element || !element.settings) {
|
|
5578
|
-
return;
|
|
5579
|
-
}
|
|
5580
|
-
element.settings[prop.propKey] = {
|
|
5581
|
-
$$type: "overridable",
|
|
5582
|
-
value: {
|
|
5583
|
-
override_key: prop.overrideKey,
|
|
5584
|
-
origin_value: prop.originValue
|
|
5585
|
-
}
|
|
5586
|
-
};
|
|
5587
|
-
});
|
|
5588
|
-
}
|
|
5589
|
-
function findElementById(root, targetId) {
|
|
5590
|
-
if (root.id === targetId) {
|
|
5591
|
-
return root;
|
|
5592
|
-
}
|
|
5593
|
-
if (root.elements) {
|
|
5594
|
-
for (const child of root.elements) {
|
|
5595
|
-
const found = findElementById(child, targetId);
|
|
5596
|
-
if (found) {
|
|
5597
|
-
return found;
|
|
5598
|
-
}
|
|
5599
|
-
}
|
|
5600
|
-
}
|
|
5601
|
-
return null;
|
|
5602
|
-
}
|
|
5603
|
-
function getValidElementTypes() {
|
|
5604
|
-
const types = getWidgetsCache4();
|
|
5605
|
-
if (!types) {
|
|
5606
|
-
return [];
|
|
5607
|
-
}
|
|
5608
|
-
return Object.entries(types).reduce((acc, [type, value]) => {
|
|
5609
|
-
if (!value.atomic_props_schema || !value.show_in_panel || value.elType === "widget") {
|
|
5610
|
-
return acc;
|
|
5611
|
-
}
|
|
5612
|
-
acc.push(type);
|
|
5613
|
-
return acc;
|
|
5614
|
-
}, []);
|
|
5615
|
-
}
|
|
5616
|
-
var generatePrompt = () => {
|
|
5617
|
-
const saveAsComponentPrompt = toolPrompts("save-as-component");
|
|
5618
|
-
saveAsComponentPrompt.description(`
|
|
5619
|
-
Save an existing element as a reusable component in the Elementor editor.
|
|
5620
|
-
|
|
5621
|
-
# When to use this tool
|
|
5622
|
-
Use this tool when the user wants to:
|
|
5623
|
-
- Create a reusable component from an existing element structure
|
|
5624
|
-
- Make specific child element properties customizable in component instances
|
|
5625
|
-
- Build a library of reusable design patterns
|
|
5626
|
-
|
|
5627
|
-
# When NOT to use this tool
|
|
5628
|
-
- Element is already a component (widgetType: 'e-component')
|
|
5629
|
-
- Element is locked
|
|
5630
|
-
- Element is not an atomic element (atomic_props_schema is not defined)
|
|
5631
|
-
- Element elType is a 'widget'
|
|
5632
|
-
|
|
5633
|
-
# **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
|
|
5634
|
-
1. [${DOCUMENT_STRUCTURE_URI}]
|
|
5635
|
-
**MANDATORY** - Required to understand the document structure and identify child elements for overridable properties.
|
|
5636
|
-
Use this resource to find element IDs and understand the element hierarchy.
|
|
5637
|
-
|
|
5638
|
-
2. [${WIDGET_SCHEMA_URI}]
|
|
5639
|
-
**MANDATORY** - Required to understand which properties are available for each widget type.
|
|
5640
|
-
Use this to identify available propKeys in the atomic_props_schema for child elements.
|
|
5641
|
-
|
|
5642
|
-
# Instructions - MUST FOLLOW IN ORDER
|
|
5643
|
-
## Step 1: Identify the Target Element
|
|
5644
|
-
1. Read the [${DOCUMENT_STRUCTURE_URI}] resource to understand the document structure
|
|
5645
|
-
2. Locate the element you want to save as a component by its element_id
|
|
5646
|
-
3. Verify the element type is a valid element type
|
|
5647
|
-
4. Ensure the element is not locked and is not already a component
|
|
5648
|
-
|
|
5649
|
-
## Step 2: Define Overridable Properties
|
|
5650
|
-
Do this step to make child element properties customizable.
|
|
5651
|
-
Skip that step ONLY if the user explicitly requests to not make any properties customizable.
|
|
5652
|
-
|
|
5653
|
-
1. **Identify Child Elements**
|
|
5654
|
-
- Use the [${DOCUMENT_STRUCTURE_URI}] resource to find all child elements
|
|
5655
|
-
- Note the elementId and widgetType/elType of each child element you want to customize
|
|
5656
|
-
|
|
5657
|
-
2. **Find Available Properties**
|
|
5658
|
-
- Use the [${WIDGET_SCHEMA_URI}] resource to find the child element's widget type schema
|
|
5659
|
-
- Review the atomic_props_schema to find available propKeys (ONLY use top-level props)
|
|
5660
|
-
- Common propKeys include: "text", "url", "tag", "size", etc.
|
|
5661
|
-
- Use only the top level properties, do not use nested properties.
|
|
5662
|
-
|
|
5663
|
-
3. **Build the overridable_props Object**
|
|
5664
|
-
- For each property you want to make overridable, add an entry:
|
|
5665
|
-
\`{ "elementId": "<child-element-id>", "propKey": "<property-key>", "label": "<user-friendly-name>" }\`
|
|
5666
|
-
- The label must be unique within the component and should be meaningful to the user (e.g., "Hero Headline", "CTA Button Text")
|
|
5667
|
-
- Group all entries under the "props" object
|
|
5668
|
-
|
|
5669
|
-
## Step 3: Execute the Tool
|
|
5670
|
-
Call the tool with:
|
|
5671
|
-
- element_id: The ID of the parent element to save as component
|
|
5672
|
-
- component_name: A descriptive name for the component
|
|
5673
|
-
- overridable_props: (Optional) The properties configuration from Step 2
|
|
5674
|
-
|
|
5675
|
-
# CONSTRAINTS
|
|
5676
|
-
- NEVER try to override properties of the parent element itself - ONLY child elements
|
|
5677
|
-
- NEVER use invalid propKeys - always verify against the widget's atomic_props_schema in [${WIDGET_SCHEMA_URI}]
|
|
5678
|
-
- Property keys must exist in the child element's atomic_props_schema
|
|
5679
|
-
- Element IDs must exist within the target element's children
|
|
5680
|
-
- When tool execution fails, read the error message and adjust accordingly
|
|
5681
|
-
- The element being saved must not be inside another component
|
|
5682
|
-
`);
|
|
5683
|
-
saveAsComponentPrompt.parameter(
|
|
5684
|
-
"element_id",
|
|
5685
|
-
`**MANDATORY** The unique identifier of the element to save as a component.
|
|
5686
|
-
Use the [${DOCUMENT_STRUCTURE_URI}] resource to find available element IDs.`
|
|
5687
|
-
);
|
|
5688
|
-
saveAsComponentPrompt.parameter(
|
|
5689
|
-
"component_name",
|
|
5690
|
-
`**MANDATORY** A descriptive name for the new component.
|
|
5691
|
-
Should be unique and clearly describe the component's purpose (e.g., "Hero Section", "Feature Card").`
|
|
5692
|
-
);
|
|
5693
|
-
saveAsComponentPrompt.parameter(
|
|
5694
|
-
"overridable_props",
|
|
5695
|
-
`**OPTIONAL** Configuration for which child element properties can be customized in component instances.
|
|
5696
|
-
|
|
5697
|
-
Structure:
|
|
5698
|
-
\`\`\`json
|
|
5699
|
-
{
|
|
5700
|
-
"props": {
|
|
5701
|
-
"<unique-key>": {
|
|
5702
|
-
"elementId": "<child-element-id>",
|
|
5703
|
-
"propKey": "<property-key>",
|
|
5704
|
-
"label": "<user-friendly-name>"
|
|
5705
|
-
}
|
|
5706
|
-
}
|
|
5707
|
-
}
|
|
5708
|
-
\`\`\`
|
|
5709
|
-
|
|
5710
|
-
To populate this correctly:
|
|
5711
|
-
1. Use [${DOCUMENT_STRUCTURE_URI}] to find child element IDs and their widgetType
|
|
5712
|
-
2. Use [${WIDGET_SCHEMA_URI}] to find the atomic_props_schema for each child element's widgetType
|
|
5713
|
-
3. Only include properties you want to be customizable in component instances
|
|
5714
|
-
4. Provide a unique, user-friendly label for each property (e.g., "Hero Headline", "CTA Button Text")`
|
|
5715
|
-
);
|
|
5716
|
-
saveAsComponentPrompt.example(`
|
|
5717
|
-
Basic component without overridable properties:
|
|
5718
|
-
\`\`\`json
|
|
5719
|
-
{
|
|
5720
|
-
"element_id": "abc123",
|
|
5721
|
-
"component_name": "Hero Section"
|
|
5722
|
-
}
|
|
5723
|
-
\`\`\`
|
|
5724
|
-
|
|
5725
|
-
Component with overridable properties:
|
|
5726
|
-
\`\`\`json
|
|
5727
|
-
{
|
|
5728
|
-
"element_id": "abc123",
|
|
5729
|
-
"component_name": "Feature Card",
|
|
5730
|
-
"overridable_props": {
|
|
5731
|
-
"props": {
|
|
5732
|
-
"heading-text": {
|
|
5733
|
-
"elementId": "heading-123",
|
|
5734
|
-
"propKey": "text",
|
|
5735
|
-
"label": "Card Title",
|
|
5736
|
-
"group": "Content"
|
|
5737
|
-
},
|
|
5738
|
-
"button-text": {
|
|
5739
|
-
"elementId": "button-456",
|
|
5740
|
-
"propKey": "text",
|
|
5741
|
-
"label": "Button Text",
|
|
5742
|
-
"group": "Content"
|
|
5743
|
-
},
|
|
5744
|
-
"button-link": {
|
|
5745
|
-
"elementId": "button-456",
|
|
5746
|
-
"propKey": "url",
|
|
5747
|
-
"label": "Button Link",
|
|
5748
|
-
"group": "Settings"
|
|
5749
|
-
}
|
|
5750
|
-
}
|
|
5751
|
-
}
|
|
5752
|
-
}
|
|
5753
|
-
\`\`\`
|
|
5754
|
-
`);
|
|
5755
|
-
saveAsComponentPrompt.instruction(
|
|
5756
|
-
`After successful creation, the component will be available in the components library and can be inserted into any page or template.`
|
|
5757
|
-
);
|
|
5758
|
-
saveAsComponentPrompt.instruction(
|
|
5759
|
-
`When overridable properties are defined, component instances will show customization controls for those specific properties in the editing panel.`
|
|
5760
|
-
);
|
|
5761
|
-
return saveAsComponentPrompt.prompt();
|
|
5762
|
-
};
|
|
5763
|
-
var initSaveAsComponentTool = () => {
|
|
5764
|
-
return getMCPByDomain("components").addTool({
|
|
5765
|
-
name: "save-as-component",
|
|
5766
|
-
schema: InputSchema,
|
|
5767
|
-
outputSchema: OutputSchema,
|
|
5768
|
-
description: generatePrompt(),
|
|
5769
|
-
handler: handleSaveAsComponent
|
|
5770
|
-
});
|
|
5771
|
-
};
|
|
5772
|
-
|
|
5773
|
-
// src/extended/mcp/index.ts
|
|
5774
|
-
function initMcp() {
|
|
5775
|
-
const { setMCPDescription } = getMCPByDomain2("components");
|
|
5776
|
-
setMCPDescription(
|
|
5777
|
-
`Elementor Editor Components MCP - Tools for creating and managing reusable components.
|
|
5778
|
-
Components are reusable blocks of content that can be used multiple times across the pages, its a widget which contains a set of elements and styles.`
|
|
5779
|
-
);
|
|
5780
|
-
initSaveAsComponentTool();
|
|
5781
|
-
}
|
|
5782
|
-
|
|
5783
|
-
// src/sync/publish-draft-components-in-page-before-save.ts
|
|
5784
|
-
import { invalidateDocumentData as invalidateDocumentData2, isDocumentDirty as isDocumentDirty2 } from "@elementor/editor-documents";
|
|
5785
|
-
async function publishDraftComponentsInPageBeforeSave({ status, elements }) {
|
|
5786
|
-
if (status !== "publish") {
|
|
5787
|
-
return;
|
|
5788
|
-
}
|
|
5789
|
-
const documents = await getComponentDocuments(elements);
|
|
5790
|
-
const draftIds = [...documents.values()].filter(isDocumentDirty2).map((document) => document.id);
|
|
5791
|
-
if (draftIds.length === 0) {
|
|
5792
|
-
return;
|
|
5793
|
-
}
|
|
5794
|
-
await apiClient.updateStatuses(draftIds, "publish");
|
|
5795
|
-
draftIds.forEach((id2) => invalidateDocumentData2(id2));
|
|
5796
|
-
}
|
|
5797
|
-
|
|
5798
|
-
// src/extended/sync/set-component-overridable-props-settings-before-save.ts
|
|
5799
|
-
var setComponentOverridablePropsSettingsBeforeSave = ({
|
|
5800
|
-
container
|
|
5801
|
-
}) => {
|
|
5802
|
-
const currentDocument = container.document;
|
|
5803
|
-
if (!currentDocument || currentDocument.config.type !== COMPONENT_DOCUMENT_TYPE) {
|
|
5804
|
-
return;
|
|
5805
|
-
}
|
|
5806
|
-
const overridableProps = componentsSelectors.getOverridableProps(currentDocument.id);
|
|
5807
|
-
if (overridableProps) {
|
|
5808
|
-
container.settings.set("overridable_props", overridableProps);
|
|
5809
|
-
}
|
|
5810
|
-
};
|
|
5811
|
-
|
|
5812
|
-
// src/extended/sync/update-archived-component-before-save.ts
|
|
5813
|
-
import { notify as notify6 } from "@elementor/editor-notifications";
|
|
5814
|
-
var failedNotification = (message) => ({
|
|
5815
|
-
type: "error",
|
|
5816
|
-
message: `Failed to archive components: ${message}`,
|
|
5817
|
-
id: "failed-archived-components-notification"
|
|
5818
|
-
});
|
|
5819
|
-
var updateArchivedComponentBeforeSave = async (status) => {
|
|
5820
|
-
try {
|
|
5821
|
-
const archivedComponents = componentsSelectors.getArchivedThisSession();
|
|
5822
|
-
if (!archivedComponents.length) {
|
|
5823
|
-
return;
|
|
5824
|
-
}
|
|
5825
|
-
const result = await apiClient.updateArchivedComponents(archivedComponents, status);
|
|
5826
|
-
const failedIds = result.failedIds.join(", ");
|
|
5827
|
-
if (failedIds) {
|
|
5828
|
-
notify6(failedNotification(failedIds));
|
|
5829
|
-
}
|
|
5830
|
-
} catch (error) {
|
|
5831
|
-
throw new Error(`Failed to update archived components: ${error}`);
|
|
5832
|
-
}
|
|
5833
|
-
};
|
|
5834
|
-
|
|
5835
|
-
// src/extended/sync/update-component-title-before-save.ts
|
|
5836
|
-
var updateComponentTitleBeforeSave = async (status) => {
|
|
5837
|
-
const updatedComponentNames = componentsSelectors.getUpdatedComponentNames();
|
|
5838
|
-
if (!updatedComponentNames.length) {
|
|
5839
|
-
return;
|
|
5840
|
-
}
|
|
5841
|
-
const result = await apiClient.updateComponentTitle(updatedComponentNames, status);
|
|
5842
|
-
if (result.failedIds.length === 0) {
|
|
5843
|
-
componentsActions.cleanUpdatedComponentNames();
|
|
5844
|
-
}
|
|
5845
|
-
};
|
|
5846
|
-
|
|
5847
|
-
// src/extended/sync/create-components-before-save.ts
|
|
5848
|
-
import { updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
|
|
5849
|
-
async function createComponentsBeforeSave({
|
|
5850
|
-
elements,
|
|
5851
|
-
status
|
|
5852
|
-
}) {
|
|
5853
|
-
const unpublishedComponents = componentsSelectors.getUnpublishedComponents();
|
|
5854
|
-
if (!unpublishedComponents.length) {
|
|
5855
|
-
return;
|
|
5856
|
-
}
|
|
5857
|
-
try {
|
|
5858
|
-
const uidToComponentId = await createComponents(unpublishedComponents, status);
|
|
5859
|
-
updateComponentInstances(elements, uidToComponentId);
|
|
5860
|
-
componentsActions.add(
|
|
5861
|
-
unpublishedComponents.map((component) => ({
|
|
5862
|
-
id: uidToComponentId.get(component.uid),
|
|
5863
|
-
name: component.name,
|
|
5864
|
-
uid: component.uid,
|
|
5865
|
-
overridableProps: component.overridableProps ? component.overridableProps : void 0
|
|
5866
|
-
}))
|
|
5867
|
-
);
|
|
5868
|
-
componentsActions.resetUnpublished();
|
|
5869
|
-
} catch (error) {
|
|
5870
|
-
const failedUids = unpublishedComponents.map((component) => component.uid);
|
|
5871
|
-
componentsActions.removeUnpublished(failedUids);
|
|
5872
|
-
throw new Error(`Failed to publish components: ${error}`);
|
|
5873
|
-
}
|
|
5874
|
-
}
|
|
5875
|
-
async function createComponents(components, status) {
|
|
5876
|
-
const response = await apiClient.create({
|
|
5877
|
-
status,
|
|
5878
|
-
items: components.map((component) => ({
|
|
5879
|
-
uid: component.uid,
|
|
5880
|
-
title: component.name,
|
|
5881
|
-
elements: component.elements,
|
|
5882
|
-
settings: component.overridableProps ? { overridable_props: component.overridableProps } : void 0
|
|
5883
|
-
}))
|
|
5884
|
-
});
|
|
5885
|
-
const map = /* @__PURE__ */ new Map();
|
|
5886
|
-
Object.entries(response).forEach(([key, value]) => {
|
|
5887
|
-
map.set(key, value);
|
|
5888
|
-
});
|
|
5889
|
-
return map;
|
|
5890
|
-
}
|
|
5891
|
-
function updateComponentInstances(elements, uidToComponentId) {
|
|
5892
|
-
elements.forEach((element) => {
|
|
5893
|
-
const { shouldUpdate, newComponentId } = shouldUpdateElement(element, uidToComponentId);
|
|
5894
|
-
if (shouldUpdate) {
|
|
5895
|
-
updateElementComponentId(element.id, newComponentId);
|
|
5896
|
-
}
|
|
5897
|
-
if (element.elements) {
|
|
5898
|
-
updateComponentInstances(element.elements, uidToComponentId);
|
|
5899
|
-
}
|
|
5900
|
-
});
|
|
5901
|
-
}
|
|
5902
|
-
function shouldUpdateElement(element, uidToComponentId) {
|
|
5903
|
-
if (element.widgetType === "e-component") {
|
|
5904
|
-
const currentComponentId = element.settings?.component_instance?.value?.component_id.value;
|
|
5905
|
-
if (currentComponentId && uidToComponentId.has(currentComponentId.toString())) {
|
|
5906
|
-
return {
|
|
5907
|
-
shouldUpdate: true,
|
|
5908
|
-
newComponentId: uidToComponentId.get(currentComponentId.toString())
|
|
5909
|
-
};
|
|
5910
|
-
}
|
|
5911
|
-
}
|
|
5912
|
-
return { shouldUpdate: false, newComponentId: null };
|
|
5913
|
-
}
|
|
5914
|
-
function updateElementComponentId(elementId, componentId) {
|
|
5915
|
-
updateElementSettings2({
|
|
5916
|
-
id: elementId,
|
|
5917
|
-
props: {
|
|
5918
|
-
component_instance: {
|
|
5919
|
-
$$type: "component-instance",
|
|
5920
|
-
value: {
|
|
5921
|
-
component_id: { $$type: "number", value: componentId }
|
|
5922
|
-
}
|
|
5923
|
-
}
|
|
5924
|
-
},
|
|
5925
|
-
withHistory: false
|
|
5926
|
-
});
|
|
5927
|
-
}
|
|
5928
|
-
|
|
5929
|
-
// src/extended/sync/before-save.ts
|
|
5930
|
-
var beforeSave = ({ container, status }) => {
|
|
5931
|
-
const elements = container?.model.get("elements").toJSON?.() ?? [];
|
|
5932
|
-
return Promise.all([
|
|
5933
|
-
syncComponents({ elements, status }),
|
|
5934
|
-
setComponentOverridablePropsSettingsBeforeSave({ container })
|
|
5935
|
-
]);
|
|
5936
|
-
};
|
|
5937
|
-
var syncComponents = async ({ elements, status }) => {
|
|
5938
|
-
await updateExistingComponentsBeforeSave({ elements, status });
|
|
5939
|
-
await createComponentsBeforeSave({ elements, status });
|
|
5940
|
-
};
|
|
5941
|
-
var updateExistingComponentsBeforeSave = async ({
|
|
5942
|
-
elements,
|
|
5943
|
-
status
|
|
5944
|
-
}) => {
|
|
5945
|
-
await updateComponentTitleBeforeSave(status);
|
|
5946
|
-
await updateArchivedComponentBeforeSave(status);
|
|
5947
|
-
await publishDraftComponentsInPageBeforeSave({ elements, status });
|
|
5948
|
-
};
|
|
5949
|
-
|
|
5950
|
-
// src/extended/sync/cleanup-overridable-props-on-delete.ts
|
|
5951
|
-
import { getAllDescendants as getAllDescendants4 } from "@elementor/editor-elements";
|
|
5952
|
-
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
5953
|
-
function initCleanupOverridablePropsOnDelete() {
|
|
5954
|
-
registerDataHook("dependency", "document/elements/delete", (args, options) => {
|
|
5955
|
-
if (isPartOfMoveCommand(options)) {
|
|
5956
|
-
return true;
|
|
5957
|
-
}
|
|
5958
|
-
const currentComponentId = componentsSelectors.getCurrentComponentId();
|
|
5959
|
-
if (!currentComponentId) {
|
|
5960
|
-
return true;
|
|
5961
|
-
}
|
|
5962
|
-
const overridableProps = componentsSelectors.getOverridableProps(currentComponentId);
|
|
5963
|
-
if (!overridableProps || Object.keys(overridableProps.props).length === 0) {
|
|
5964
|
-
return true;
|
|
5965
|
-
}
|
|
5966
|
-
const containers = args.containers ?? (args.container ? [args.container] : []);
|
|
5967
|
-
if (containers.length === 0) {
|
|
5968
|
-
return true;
|
|
5969
|
-
}
|
|
5970
|
-
const deletedElementIds = collectDeletedElementIds(containers);
|
|
5971
|
-
if (deletedElementIds.length === 0) {
|
|
5972
|
-
return true;
|
|
5973
|
-
}
|
|
5974
|
-
const propKeysToDelete = Object.entries(overridableProps.props).filter(([, prop]) => deletedElementIds.includes(prop.elementId)).map(([propKey]) => propKey);
|
|
5975
|
-
if (propKeysToDelete.length === 0) {
|
|
5976
|
-
return true;
|
|
5977
|
-
}
|
|
5978
|
-
deleteOverridableProp({ componentId: currentComponentId, propKey: propKeysToDelete, source: "system" });
|
|
5979
|
-
return true;
|
|
5980
|
-
});
|
|
5981
|
-
}
|
|
5982
|
-
function collectDeletedElementIds(containers) {
|
|
5983
|
-
const elementIds = containers.filter(Boolean).flatMap((container) => [container, ...getAllDescendants4(container)]).map((element) => element.model?.get?.("id") ?? element.id).filter((id2) => Boolean(id2));
|
|
5984
|
-
return elementIds;
|
|
5985
|
-
}
|
|
5986
|
-
function isPartOfMoveCommand(options) {
|
|
5987
|
-
const isMoveCommandInTrace = options?.commandsCurrentTrace?.includes("document/elements/move") || options?.commandsCurrentTrace?.includes("document/repeater/move");
|
|
5988
|
-
return Boolean(isMoveCommandInTrace);
|
|
5989
|
-
}
|
|
5990
|
-
|
|
5991
|
-
// src/extended/sync/handle-component-edit-mode-container.ts
|
|
5992
|
-
import { createElement as createElement40, selectElement as selectElement2 } from "@elementor/editor-elements";
|
|
5993
|
-
import { registerDataHook as registerDataHook2 } from "@elementor/editor-v1-adapters";
|
|
5994
|
-
var V4_DEFAULT_CONTAINER_TYPE = "e-flexbox";
|
|
5995
|
-
function initHandleComponentEditModeContainer() {
|
|
5996
|
-
initRedirectDropIntoComponent();
|
|
5997
|
-
initHandleTopLevelElementDelete();
|
|
5998
|
-
}
|
|
5999
|
-
function initHandleTopLevelElementDelete() {
|
|
6000
|
-
registerDataHook2("after", "document/elements/delete", (args) => {
|
|
6001
|
-
if (!isEditingComponent()) {
|
|
6002
|
-
return;
|
|
6003
|
-
}
|
|
6004
|
-
const containers = args.containers ?? (args.container ? [args.container] : []);
|
|
6005
|
-
for (const container of containers) {
|
|
6006
|
-
if (!container.parent || !isComponent(container.parent)) {
|
|
6007
|
-
continue;
|
|
6008
|
-
}
|
|
6009
|
-
const component = container.parent;
|
|
6010
|
-
const isComponentEmpty = component.children?.length === 0;
|
|
6011
|
-
if (isComponentEmpty) {
|
|
6012
|
-
createEmptyTopLevelContainer(container.parent);
|
|
6013
|
-
}
|
|
6014
|
-
}
|
|
6015
|
-
});
|
|
6016
|
-
}
|
|
6017
|
-
function initRedirectDropIntoComponent() {
|
|
6018
|
-
registerDataHook2("dependency", "preview/drop", (args) => {
|
|
6019
|
-
if (!isEditingComponent()) {
|
|
6020
|
-
return true;
|
|
6021
|
-
}
|
|
6022
|
-
const containers = args.containers ?? (args.container ? [args.container] : []);
|
|
6023
|
-
for (const container of containers) {
|
|
6024
|
-
if (!isComponent(container)) {
|
|
6025
|
-
continue;
|
|
6026
|
-
}
|
|
6027
|
-
const { shouldRedirect, container: redirectedContainer } = getComponentContainer(container);
|
|
6028
|
-
if (!shouldRedirect) {
|
|
6029
|
-
continue;
|
|
6030
|
-
}
|
|
6031
|
-
if (args.containers) {
|
|
6032
|
-
const index = args.containers.indexOf(container);
|
|
6033
|
-
args.containers[index] = redirectedContainer;
|
|
6034
|
-
} else {
|
|
6035
|
-
args.container = redirectedContainer;
|
|
6036
|
-
}
|
|
6037
|
-
}
|
|
6038
|
-
return true;
|
|
6039
|
-
});
|
|
6040
|
-
}
|
|
6041
|
-
function createEmptyTopLevelContainer(container) {
|
|
6042
|
-
const newContainer = createElement40({
|
|
6043
|
-
container,
|
|
6044
|
-
model: { elType: V4_DEFAULT_CONTAINER_TYPE }
|
|
6045
|
-
});
|
|
6046
|
-
selectElement2(newContainer.id);
|
|
6047
|
-
}
|
|
6048
|
-
function getComponentContainer(container) {
|
|
6049
|
-
const topLevelElement = container.children?.[0];
|
|
6050
|
-
if (topLevelElement) {
|
|
6051
|
-
return { shouldRedirect: true, container: topLevelElement };
|
|
6052
|
-
}
|
|
6053
|
-
return { shouldRedirect: false, container };
|
|
6054
|
-
}
|
|
6055
|
-
function isComponent(container) {
|
|
6056
|
-
const isDocument = container.id === "document";
|
|
6057
|
-
if (!isDocument) {
|
|
6058
|
-
return false;
|
|
6059
|
-
}
|
|
6060
|
-
return container.document?.config.type === COMPONENT_DOCUMENT_TYPE;
|
|
6061
|
-
}
|
|
6062
|
-
|
|
6063
|
-
// src/extended/sync/revert-overridables-on-copy-or-duplicate.ts
|
|
6064
|
-
import { registerDataHook as registerDataHook3 } from "@elementor/editor-v1-adapters";
|
|
6065
|
-
function initRevertOverridablesOnCopyOrDuplicate() {
|
|
6066
|
-
registerDataHook3("after", "document/elements/duplicate", (_args, result) => {
|
|
6067
|
-
if (!isEditingComponent()) {
|
|
6068
|
-
return;
|
|
6069
|
-
}
|
|
6070
|
-
revertOverridablesForDuplicatedElements(result);
|
|
6071
|
-
});
|
|
6072
|
-
registerDataHook3("after", "document/elements/copy", (args) => {
|
|
6073
|
-
if (!isEditingComponent()) {
|
|
6074
|
-
return;
|
|
6075
|
-
}
|
|
6076
|
-
revertOverridablesInStorage(args.storageKey ?? "clipboard");
|
|
6077
|
-
});
|
|
6078
|
-
}
|
|
6079
|
-
function revertOverridablesForDuplicatedElements(duplicatedElements) {
|
|
6080
|
-
const containers = Array.isArray(duplicatedElements) ? duplicatedElements : [duplicatedElements];
|
|
6081
|
-
containers.forEach((container) => {
|
|
6082
|
-
revertAllOverridablesInContainer(container);
|
|
6083
|
-
});
|
|
6084
|
-
}
|
|
6085
|
-
function revertOverridablesInStorage(storageKey) {
|
|
6086
|
-
const storage = window.elementorCommon?.storage;
|
|
6087
|
-
if (!storage) {
|
|
6088
|
-
return;
|
|
6089
|
-
}
|
|
6090
|
-
const storageData = storage.get(storageKey);
|
|
6091
|
-
if (!storageData?.elements?.length) {
|
|
6092
|
-
return;
|
|
6093
|
-
}
|
|
6094
|
-
const elementsDataWithOverridablesReverted = storageData.elements.map(revertAllOverridablesInElementData);
|
|
6095
|
-
storage.set(storageKey, {
|
|
6096
|
-
...storageData,
|
|
6097
|
-
elements: elementsDataWithOverridablesReverted
|
|
6098
|
-
});
|
|
6099
|
-
}
|
|
6100
|
-
|
|
6101
|
-
// src/extended/sync/sanitize-overridable-props.ts
|
|
6102
|
-
import { useEffect as useEffect7 } from "react";
|
|
6103
|
-
|
|
6104
|
-
// src/extended/store/actions/update-component-sanitized-attribute.ts
|
|
6105
|
-
function updateComponentSanitizedAttribute(componentId, attribute) {
|
|
6106
|
-
componentsActions.updateComponentSanitizedAttribute(componentId, attribute);
|
|
6107
|
-
}
|
|
6108
|
-
|
|
6109
|
-
// src/extended/sync/sanitize-overridable-props.ts
|
|
6110
|
-
function SanitizeOverridableProps() {
|
|
6111
|
-
const currentComponentId = useCurrentComponentId();
|
|
6112
|
-
const overridableProps = useOverridableProps(currentComponentId);
|
|
6113
|
-
const isSanitized = useIsSanitizedComponent(currentComponentId, "overridableProps");
|
|
6114
|
-
useEffect7(() => {
|
|
6115
|
-
if (isSanitized || !overridableProps || !currentComponentId) {
|
|
6116
|
-
return;
|
|
6117
|
-
}
|
|
6118
|
-
const filtered = filterValidOverridableProps(overridableProps);
|
|
6119
|
-
const propsToDelete = Object.keys(overridableProps.props ?? {}).filter((key) => !filtered.props[key]);
|
|
6120
|
-
if (propsToDelete.length > 0) {
|
|
6121
|
-
propsToDelete.forEach((key) => {
|
|
6122
|
-
deleteOverridableProp({ componentId: currentComponentId, propKey: key, source: "system" });
|
|
6123
|
-
});
|
|
6124
|
-
}
|
|
6125
|
-
updateComponentSanitizedAttribute(currentComponentId, "overridableProps");
|
|
6126
|
-
}, [currentComponentId, isSanitized, overridableProps]);
|
|
6127
|
-
return null;
|
|
6128
|
-
}
|
|
6129
|
-
|
|
6130
|
-
// src/extended/init.ts
|
|
6131
|
-
var PRIORITY = 1;
|
|
6132
|
-
function initExtended() {
|
|
6133
|
-
registerEditingPanelReplacement({
|
|
6134
|
-
id: "extended-component-instance-edit-panel",
|
|
6135
|
-
priority: PRIORITY,
|
|
6136
|
-
condition: (_, elementType) => elementType.key === "e-component",
|
|
6137
|
-
component: ExtendedInstanceEditingPanel
|
|
6138
|
-
});
|
|
6139
|
-
registerTab({
|
|
6140
|
-
id: "components",
|
|
6141
|
-
label: __34("Components", "elementor"),
|
|
6142
|
-
component: ExtendedComponents,
|
|
6143
|
-
priority: PRIORITY
|
|
6144
|
-
});
|
|
6145
|
-
registerPanel(panel);
|
|
6146
|
-
registerDataHook4("dependency", "editor/documents/close", (args) => {
|
|
6147
|
-
const document = getV1CurrentDocument();
|
|
6148
|
-
if (document.config.type === COMPONENT_DOCUMENT_TYPE) {
|
|
6149
|
-
args.mode = "autosave";
|
|
6150
|
-
}
|
|
6151
|
-
return true;
|
|
6152
|
-
});
|
|
6153
|
-
registerDataHook4("after", "preview/drop", onElementDrop);
|
|
6154
|
-
window.elementorCommon.__beforeSave = beforeSave;
|
|
6155
|
-
injectIntoTop({
|
|
6156
|
-
id: "create-component-popup",
|
|
6157
|
-
component: CreateComponentForm
|
|
6158
|
-
});
|
|
6159
|
-
injectIntoTop({
|
|
6160
|
-
id: "edit-component",
|
|
6161
|
-
component: EditComponent
|
|
6162
|
-
});
|
|
6163
|
-
injectIntoPanelHeaderTop({
|
|
6164
|
-
id: "component-panel-header",
|
|
6165
|
-
component: ComponentPanelHeader
|
|
6166
|
-
});
|
|
6167
|
-
registerFieldIndicator({
|
|
6168
|
-
fieldType: FIELD_TYPE.SETTINGS,
|
|
6169
|
-
id: "component-overridable-prop",
|
|
6170
|
-
priority: 1,
|
|
6171
|
-
indicator: OverridablePropIndicator
|
|
6172
|
-
});
|
|
6173
|
-
registerControlReplacement({
|
|
6174
|
-
id: OVERRIDABLE_PROP_REPLACEMENT_ID,
|
|
6175
|
-
component: OverridablePropControl,
|
|
6176
|
-
condition: ({ value }) => componentOverridablePropTypeUtil.isValid(value)
|
|
6177
|
-
});
|
|
6178
|
-
initCleanupOverridablePropsOnDelete();
|
|
6179
|
-
initMcp();
|
|
6180
|
-
initNonAtomicNestingPrevention();
|
|
6181
|
-
initHandleComponentEditModeContainer();
|
|
6182
|
-
initRevertOverridablesOnCopyOrDuplicate();
|
|
6183
|
-
injectIntoLogic({
|
|
6184
|
-
id: "sanitize-overridable-props",
|
|
6185
|
-
component: SanitizeOverridableProps
|
|
6186
|
-
});
|
|
6187
|
-
}
|
|
6188
|
-
|
|
6189
|
-
// src/extended/shortcuts/create-component-shortcut.ts
|
|
6190
|
-
import { getElementType as getElementType5, getSelectedElements as getSelectedElements2, getWidgetsCache as getWidgetsCache5 } from "@elementor/editor-elements";
|
|
6191
|
-
import { isProActive } from "@elementor/utils";
|
|
6192
|
-
var CREATE_COMPONENT_SHORTCUT_KEYS = "ctrl+shift+k";
|
|
6193
|
-
var OPEN_SAVE_AS_COMPONENT_FORM_EVENT = "elementor/editor/open-save-as-component-form";
|
|
6194
|
-
function isCreateComponentAllowed() {
|
|
6195
|
-
const selectedElements = getSelectedElements2();
|
|
6196
|
-
if (selectedElements.length !== 1) {
|
|
6197
|
-
return { allowed: false };
|
|
6198
|
-
}
|
|
6199
|
-
const element = selectedElements[0];
|
|
6200
|
-
const elementType = getElementType5(element.type);
|
|
6201
|
-
if (!elementType) {
|
|
6202
|
-
return { allowed: false };
|
|
6203
|
-
}
|
|
6204
|
-
if (!isProActive()) {
|
|
6205
|
-
return { allowed: false };
|
|
6206
|
-
}
|
|
6207
|
-
const widgetsCache = getWidgetsCache5();
|
|
6208
|
-
const elementConfig = widgetsCache?.[element.type];
|
|
6209
|
-
if (!elementConfig?.atomic_props_schema || !elementConfig?.show_in_panel || elementConfig?.elType === "widget") {
|
|
6210
|
-
return { allowed: false };
|
|
6211
|
-
}
|
|
6212
|
-
const legacyWindow = window;
|
|
6213
|
-
const container = legacyWindow.elementor.getContainer(element.id);
|
|
6214
|
-
if (!container || container.isLocked()) {
|
|
6215
|
-
return { allowed: false };
|
|
6216
|
-
}
|
|
6217
|
-
return { allowed: true, container };
|
|
6218
|
-
}
|
|
6219
|
-
function triggerCreateComponentForm(container) {
|
|
6220
|
-
const legacyWindow = window;
|
|
6221
|
-
const elementRect = container.view.el.getBoundingClientRect();
|
|
6222
|
-
const iframeRect = legacyWindow.elementor.$preview[0].getBoundingClientRect();
|
|
6223
|
-
const anchorPosition = {
|
|
6224
|
-
left: iframeRect.left + elementRect.left + elementRect.width / 2,
|
|
6225
|
-
top: iframeRect.top + elementRect.top
|
|
6226
|
-
};
|
|
6227
|
-
window.dispatchEvent(
|
|
6228
|
-
new CustomEvent(OPEN_SAVE_AS_COMPONENT_FORM_EVENT, {
|
|
6229
|
-
detail: {
|
|
6230
|
-
element: container.model.toJSON({ remove: ["default"] }),
|
|
6231
|
-
anchorPosition,
|
|
6232
|
-
options: {
|
|
6233
|
-
trigger: "keyboard",
|
|
6234
|
-
location: "canvas",
|
|
6235
|
-
secondaryLocation: "canvasElement"
|
|
6236
|
-
}
|
|
6237
|
-
}
|
|
6238
|
-
})
|
|
6239
|
-
);
|
|
6240
|
-
}
|
|
6241
|
-
function initCreateComponentShortcut() {
|
|
6242
|
-
const legacyWindow = window;
|
|
6243
|
-
legacyWindow.$e.shortcuts.register(CREATE_COMPONENT_SHORTCUT_KEYS, {
|
|
6244
|
-
callback: () => {
|
|
6245
|
-
const result = isCreateComponentAllowed();
|
|
6246
|
-
if (!result.allowed) {
|
|
6247
|
-
return;
|
|
6248
|
-
}
|
|
6249
|
-
triggerCreateComponentForm(result.container);
|
|
6250
|
-
},
|
|
6251
|
-
dependency: () => {
|
|
6252
|
-
const result = isCreateComponentAllowed();
|
|
6253
|
-
return result.allowed;
|
|
6254
|
-
},
|
|
6255
|
-
exclude: ["input"]
|
|
6256
|
-
});
|
|
6257
|
-
}
|
|
6258
|
-
|
|
6259
|
-
// src/populate-store.ts
|
|
6260
|
-
import { useEffect as useEffect8 } from "react";
|
|
6261
|
-
import { __dispatch as dispatch5 } from "@elementor/store";
|
|
6262
|
-
function PopulateStore() {
|
|
6263
|
-
useEffect8(() => {
|
|
6264
|
-
dispatch5(loadComponents());
|
|
6265
|
-
}, []);
|
|
6266
|
-
return null;
|
|
6267
|
-
}
|
|
6268
|
-
|
|
6269
|
-
// src/prevent-circular-nesting.ts
|
|
6270
|
-
import { getAllDescendants as getAllDescendants5 } from "@elementor/editor-elements";
|
|
6271
|
-
import { notify as notify7 } from "@elementor/editor-notifications";
|
|
6272
|
-
import { blockCommand as blockCommand2 } from "@elementor/editor-v1-adapters";
|
|
6273
|
-
import { __getState as getState10 } from "@elementor/store";
|
|
6274
|
-
import { __ as __35 } from "@wordpress/i18n";
|
|
6275
|
-
var COMPONENT_TYPE = "e-component";
|
|
6276
|
-
var COMPONENT_CIRCULAR_NESTING_ALERT = {
|
|
6277
|
-
type: "default",
|
|
6278
|
-
message: __35("Can't add this component - components that contain each other can't be nested.", "elementor"),
|
|
6279
|
-
id: "circular-component-nesting-blocked"
|
|
6280
|
-
};
|
|
6281
|
-
function initCircularNestingPrevention() {
|
|
6282
|
-
blockCommand2({
|
|
6283
|
-
command: "document/elements/create",
|
|
6284
|
-
condition: blockCircularCreate
|
|
6285
|
-
});
|
|
6286
|
-
blockCommand2({
|
|
6287
|
-
command: "document/elements/move",
|
|
6288
|
-
condition: blockCircularMove
|
|
6289
|
-
});
|
|
6290
|
-
blockCommand2({
|
|
6291
|
-
command: "document/elements/paste",
|
|
6292
|
-
condition: blockCircularPaste
|
|
6293
|
-
});
|
|
6294
|
-
}
|
|
6295
|
-
function wouldCreateCircularNesting(componentIdToAdd) {
|
|
6296
|
-
if (componentIdToAdd === void 0) {
|
|
6297
|
-
return false;
|
|
6298
|
-
}
|
|
6299
|
-
const state = getState10();
|
|
6300
|
-
const currentComponentId = selectCurrentComponentId(state);
|
|
6301
|
-
const path = selectPath(state);
|
|
6302
|
-
if (currentComponentId === null) {
|
|
6303
|
-
return false;
|
|
6304
|
-
}
|
|
6305
|
-
if (componentIdToAdd === currentComponentId) {
|
|
6306
|
-
return true;
|
|
6307
|
-
}
|
|
6308
|
-
return path.some((item) => item.componentId === componentIdToAdd);
|
|
6309
|
-
}
|
|
6310
|
-
function extractComponentIdFromModel(model) {
|
|
6311
|
-
if (!model) {
|
|
6312
|
-
return null;
|
|
6313
|
-
}
|
|
6314
|
-
const isComponent2 = model.widgetType === COMPONENT_TYPE;
|
|
6315
|
-
if (!isComponent2) {
|
|
6316
|
-
return null;
|
|
6317
|
-
}
|
|
6318
|
-
return model.settings?.component_instance?.value?.component_id?.value ?? null;
|
|
6319
|
-
}
|
|
6320
|
-
function extractComponentIdFromElement(element) {
|
|
6321
|
-
if (element.widgetType !== COMPONENT_TYPE) {
|
|
6322
|
-
return null;
|
|
6323
|
-
}
|
|
6324
|
-
return element.settings?.component_instance?.value?.component_id?.value ?? null;
|
|
6325
|
-
}
|
|
6326
|
-
function extractComponentIdsFromElements(elements) {
|
|
6327
|
-
const ids = [];
|
|
6328
|
-
for (const element of elements) {
|
|
6329
|
-
const componentId = extractComponentIdFromElement(element);
|
|
6330
|
-
if (componentId !== null) {
|
|
6331
|
-
ids.push(componentId);
|
|
6332
|
-
}
|
|
6333
|
-
if (element.elements?.length) {
|
|
6334
|
-
ids.push(...extractComponentIdsFromElements(element.elements));
|
|
6335
|
-
}
|
|
6336
|
-
}
|
|
6337
|
-
return ids;
|
|
6338
|
-
}
|
|
6339
|
-
function extractComponentIdFromContainer(container) {
|
|
6340
|
-
const widgetType = container.model?.get?.("widgetType");
|
|
6341
|
-
if (widgetType !== COMPONENT_TYPE) {
|
|
6342
|
-
return null;
|
|
6343
|
-
}
|
|
6344
|
-
const settings = container.model?.get?.("settings");
|
|
6345
|
-
const componentInstance = settings?.get?.("component_instance");
|
|
6346
|
-
return componentInstance?.value?.component_id?.value ?? null;
|
|
6347
|
-
}
|
|
6348
|
-
function blockCircularCreate(args) {
|
|
6349
|
-
const componentId = extractComponentIdFromModel(args.model);
|
|
6350
|
-
if (componentId === null) {
|
|
6351
|
-
return false;
|
|
6352
|
-
}
|
|
6353
|
-
const isBlocked = wouldCreateCircularNesting(componentId);
|
|
6354
|
-
if (isBlocked) {
|
|
6355
|
-
notify7(COMPONENT_CIRCULAR_NESTING_ALERT);
|
|
6356
|
-
}
|
|
6357
|
-
return isBlocked;
|
|
6358
|
-
}
|
|
6359
|
-
function blockCircularMove(args) {
|
|
6360
|
-
const { containers = [args.container] } = args;
|
|
6361
|
-
const hasCircularComponent = containers.some((container) => {
|
|
6362
|
-
if (!container) {
|
|
6363
|
-
return false;
|
|
6364
|
-
}
|
|
6365
|
-
const allElements = getAllDescendants5(container);
|
|
6366
|
-
return allElements.some((element) => {
|
|
6367
|
-
const componentId = extractComponentIdFromContainer(element);
|
|
6368
|
-
if (componentId === null) {
|
|
6369
|
-
return false;
|
|
6370
|
-
}
|
|
6371
|
-
return wouldCreateCircularNesting(componentId);
|
|
6372
|
-
});
|
|
6373
|
-
});
|
|
6374
|
-
if (hasCircularComponent) {
|
|
6375
|
-
notify7(COMPONENT_CIRCULAR_NESTING_ALERT);
|
|
6376
|
-
}
|
|
6377
|
-
return hasCircularComponent;
|
|
6378
|
-
}
|
|
6379
|
-
function blockCircularPaste(args) {
|
|
6380
|
-
const { storageType } = args;
|
|
6381
|
-
if (storageType !== "localstorage") {
|
|
6382
|
-
return false;
|
|
6383
|
-
}
|
|
6384
|
-
const data = window?.elementorCommon?.storage?.get();
|
|
6385
|
-
if (!data?.clipboard?.elements) {
|
|
6386
|
-
return false;
|
|
6387
|
-
}
|
|
6388
|
-
const allComponentIds = extractComponentIdsFromElements(data.clipboard.elements);
|
|
6389
|
-
const hasCircularComponent = allComponentIds.some(wouldCreateCircularNesting);
|
|
6390
|
-
if (hasCircularComponent) {
|
|
6391
|
-
notify7(COMPONENT_CIRCULAR_NESTING_ALERT);
|
|
6392
|
-
}
|
|
6393
|
-
return hasCircularComponent;
|
|
6394
|
-
}
|
|
6395
|
-
|
|
6396
|
-
// src/store/actions/remove-component-styles.ts
|
|
6397
|
-
import { __dispatch as dispatch6 } from "@elementor/store";
|
|
6398
|
-
function removeComponentStyles(id2) {
|
|
6399
|
-
apiClient.invalidateComponentConfigCache(id2);
|
|
6400
|
-
dispatch6(slice.actions.removeStyles({ id: id2 }));
|
|
2708
|
+
await apiClient.updateStatuses(draftIds, "publish");
|
|
2709
|
+
draftIds.forEach((id) => invalidateDocumentData2(id));
|
|
6401
2710
|
}
|
|
6402
2711
|
|
|
6403
|
-
// src/store/components-styles-provider.ts
|
|
6404
|
-
import { createStylesProvider } from "@elementor/editor-styles-repository";
|
|
6405
|
-
import { __getState as getState11, __subscribeWithSelector as subscribeWithSelector } from "@elementor/store";
|
|
6406
|
-
var componentsStylesProvider = createStylesProvider({
|
|
6407
|
-
key: "components-styles",
|
|
6408
|
-
priority: 100,
|
|
6409
|
-
subscribe: (cb) => subscribeWithSelector(
|
|
6410
|
-
(state) => state[SLICE_NAME],
|
|
6411
|
-
() => {
|
|
6412
|
-
cb();
|
|
6413
|
-
}
|
|
6414
|
-
),
|
|
6415
|
-
actions: {
|
|
6416
|
-
all: () => {
|
|
6417
|
-
return selectFlatStyles(getState11());
|
|
6418
|
-
},
|
|
6419
|
-
get: (id2) => {
|
|
6420
|
-
return selectFlatStyles(getState11()).find((style) => style.id === id2) ?? null;
|
|
6421
|
-
}
|
|
6422
|
-
}
|
|
6423
|
-
});
|
|
6424
|
-
|
|
6425
2712
|
// src/sync/before-save.ts
|
|
6426
|
-
var
|
|
2713
|
+
var beforeSave = ({ container, status }) => {
|
|
6427
2714
|
const elements = container?.model.get("elements").toJSON?.() ?? [];
|
|
6428
2715
|
return publishDraftComponentsInPageBeforeSave({ elements, status });
|
|
6429
2716
|
};
|
|
6430
2717
|
|
|
6431
2718
|
// src/sync/load-component-data-after-instance-added.ts
|
|
6432
|
-
import { registerDataHook
|
|
2719
|
+
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
6433
2720
|
function initLoadComponentDataAfterInstanceAdded() {
|
|
6434
|
-
|
|
2721
|
+
registerDataHook("after", "document/elements/paste", (_args, result) => {
|
|
6435
2722
|
load(result);
|
|
6436
2723
|
});
|
|
6437
|
-
|
|
2724
|
+
registerDataHook("after", "document/elements/import", (_args, result) => {
|
|
6438
2725
|
load(result);
|
|
6439
2726
|
});
|
|
6440
2727
|
}
|
|
@@ -6444,7 +2731,6 @@ function load(result) {
|
|
|
6444
2731
|
}
|
|
6445
2732
|
|
|
6446
2733
|
// src/init.ts
|
|
6447
|
-
var PRO_EXTENDED_MIGRATION_VERSION = "4.0.0";
|
|
6448
2734
|
function init() {
|
|
6449
2735
|
stylesRepository.register(componentsStylesProvider);
|
|
6450
2736
|
registerSlice(slice);
|
|
@@ -6456,29 +2742,29 @@ function init() {
|
|
|
6456
2742
|
showDetachConfirmDialog: openDetachConfirmDialog
|
|
6457
2743
|
})
|
|
6458
2744
|
);
|
|
6459
|
-
window.elementorCommon.__beforeSave =
|
|
2745
|
+
window.elementorCommon.__beforeSave = beforeSave;
|
|
6460
2746
|
injectTab({
|
|
6461
2747
|
id: "components",
|
|
6462
|
-
label:
|
|
2748
|
+
label: __12("Components", "elementor"),
|
|
6463
2749
|
component: Components,
|
|
6464
2750
|
position: 1
|
|
6465
2751
|
});
|
|
6466
|
-
|
|
2752
|
+
injectIntoLogic({
|
|
6467
2753
|
id: "components-populate-store",
|
|
6468
2754
|
component: PopulateStore
|
|
6469
2755
|
});
|
|
6470
|
-
|
|
6471
|
-
const { id
|
|
6472
|
-
if (
|
|
6473
|
-
removeComponentStyles(
|
|
2756
|
+
registerDataHook2("after", "editor/documents/attach-preview", async () => {
|
|
2757
|
+
const { id, config } = getV1CurrentDocument();
|
|
2758
|
+
if (id) {
|
|
2759
|
+
removeComponentStyles(id);
|
|
6474
2760
|
}
|
|
6475
2761
|
await loadComponentsAssets(config?.elements ?? []);
|
|
6476
2762
|
});
|
|
6477
|
-
|
|
2763
|
+
injectIntoLogic({
|
|
6478
2764
|
id: "templates",
|
|
6479
2765
|
component: LoadTemplateComponents
|
|
6480
2766
|
});
|
|
6481
|
-
|
|
2767
|
+
registerEditingPanelReplacement({
|
|
6482
2768
|
id: "component-instance-edit-panel",
|
|
6483
2769
|
condition: (_, elementType) => elementType.key === "e-component",
|
|
6484
2770
|
component: InstanceEditingPanel
|
|
@@ -6488,12 +2774,6 @@ function init() {
|
|
|
6488
2774
|
settingsTransformersRegistry2.register("override", componentOverrideTransformer);
|
|
6489
2775
|
initCircularNestingPrevention();
|
|
6490
2776
|
initLoadComponentDataAfterInstanceAdded();
|
|
6491
|
-
if (!!window.elementorPro && !isProAtLeast(PRO_EXTENDED_MIGRATION_VERSION)) {
|
|
6492
|
-
initExtended();
|
|
6493
|
-
}
|
|
6494
|
-
if (!!window.elementorPro) {
|
|
6495
|
-
initCreateComponentShortcut();
|
|
6496
|
-
}
|
|
6497
2777
|
}
|
|
6498
2778
|
export {
|
|
6499
2779
|
COMPONENT_WIDGET_TYPE2 as COMPONENT_WIDGET_TYPE,
|