@elementor/editor-components 3.33.0-99 → 3.35.0-324
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 +2225 -128
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2236 -111
- package/dist/index.mjs.map +1 -1
- package/package.json +23 -12
- package/src/api.ts +71 -11
- package/src/component-instance-transformer.ts +24 -0
- package/src/component-overridable-transformer.ts +28 -0
- package/src/components/component-panel-header/component-badge.tsx +62 -0
- package/src/components/component-panel-header/component-panel-header.tsx +58 -0
- package/src/components/component-panel-header/use-overridable-props.ts +14 -0
- package/src/components/components-tab/component-search.tsx +32 -0
- package/src/components/components-tab/components-item.tsx +115 -0
- package/src/components/components-tab/components-list.tsx +141 -0
- package/src/components/components-tab/components.tsx +17 -0
- package/src/components/components-tab/loading-components.tsx +43 -0
- package/src/components/components-tab/search-provider.tsx +38 -0
- package/src/components/consts.ts +1 -0
- package/src/components/create-component-form/create-component-form.tsx +109 -100
- package/src/components/create-component-form/utils/get-component-event-data.ts +54 -0
- package/src/components/create-component-form/utils/replace-element-with-component.ts +28 -10
- package/src/components/edit-component/component-modal.tsx +134 -0
- package/src/components/edit-component/edit-component.tsx +96 -0
- package/src/components/in-edit-mode.tsx +43 -0
- package/src/components/overridable-props/indicator.tsx +80 -0
- package/src/components/overridable-props/overridable-prop-control.tsx +67 -0
- package/src/components/overridable-props/overridable-prop-form.tsx +98 -0
- package/src/components/overridable-props/overridable-prop-indicator.tsx +124 -0
- package/src/components/overridable-props/utils/get-overridable-prop.ts +20 -0
- package/src/create-component-type.ts +194 -0
- package/src/hooks/use-canvas-document.ts +6 -0
- package/src/hooks/use-components.ts +6 -9
- package/src/hooks/use-element-rect.ts +81 -0
- package/src/hooks/use-navigate-back.ts +34 -0
- package/src/init.ts +100 -3
- package/src/mcp/index.ts +14 -0
- package/src/mcp/save-as-component-tool.ts +92 -0
- package/src/populate-store.ts +12 -0
- package/src/prop-types/component-overridable-prop-type.ts +17 -0
- package/src/store/actions/archive-component.ts +16 -0
- package/src/store/actions/create-unpublished-component.ts +40 -0
- package/src/store/actions/load-components-assets.ts +29 -0
- package/src/store/actions/load-components-overridable-props.ts +33 -0
- package/src/store/actions/load-components-styles.ts +44 -0
- package/src/store/actions/remove-component-styles.ts +9 -0
- package/src/store/actions/set-overridable-prop.ts +200 -0
- package/src/store/actions/update-current-component.ts +33 -0
- package/src/store/actions/update-overridable-prop-origin-value.ts +37 -0
- package/src/store/components-styles-provider.ts +24 -0
- package/src/store/store.ts +193 -0
- package/src/store/thunks.ts +10 -0
- package/src/sync/before-save.ts +31 -0
- package/src/sync/create-components-before-save.ts +102 -0
- package/src/sync/set-component-overridable-props-settings-before-save.ts +23 -0
- package/src/sync/update-archived-component-before-save.ts +44 -0
- package/src/sync/update-components-before-save.ts +35 -0
- package/src/types.ts +83 -0
- package/src/utils/component-document-data.ts +19 -0
- package/src/utils/get-component-ids.ts +36 -0
- package/src/utils/get-container-for-new-element.ts +49 -0
- package/src/utils/tracking.ts +47 -0
- package/src/components/components-tab.tsx +0 -6
- package/src/hooks/use-create-component.ts +0 -13
package/dist/index.mjs
CHANGED
|
@@ -1,54 +1,1103 @@
|
|
|
1
1
|
// src/init.ts
|
|
2
|
-
import { injectIntoTop } from "@elementor/editor";
|
|
2
|
+
import { injectIntoLogic, injectIntoTop } from "@elementor/editor";
|
|
3
|
+
import {
|
|
4
|
+
registerElementType,
|
|
5
|
+
settingsTransformersRegistry as settingsTransformersRegistry2
|
|
6
|
+
} from "@elementor/editor-canvas";
|
|
7
|
+
import { getV1CurrentDocument as getV1CurrentDocument2 } from "@elementor/editor-documents";
|
|
8
|
+
import {
|
|
9
|
+
FIELD_TYPE,
|
|
10
|
+
injectIntoPanelHeaderTop,
|
|
11
|
+
registerControlReplacement,
|
|
12
|
+
registerFieldIndicator
|
|
13
|
+
} from "@elementor/editor-editing-panel";
|
|
3
14
|
import { injectTab } from "@elementor/editor-elements-panel";
|
|
4
|
-
import {
|
|
15
|
+
import { stylesRepository } from "@elementor/editor-styles-repository";
|
|
16
|
+
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
17
|
+
import { __registerSlice as registerSlice } from "@elementor/store";
|
|
18
|
+
import { __ as __15 } from "@wordpress/i18n";
|
|
5
19
|
|
|
6
|
-
// src/
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
function ComponentsTab() {
|
|
10
|
-
return /* @__PURE__ */ React.createElement(Box, { px: 2 }, "This is the Components tab.");
|
|
11
|
-
}
|
|
20
|
+
// src/component-instance-transformer.ts
|
|
21
|
+
import { createTransformer } from "@elementor/editor-canvas";
|
|
22
|
+
import { __getState as getState } from "@elementor/store";
|
|
12
23
|
|
|
13
|
-
// src/
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import { StarIcon } from "@elementor/icons";
|
|
19
|
-
import { Alert, Button, FormLabel, Grid, Popover, Snackbar, Stack, TextField, Typography } from "@elementor/ui";
|
|
20
|
-
import { __ as __2 } from "@wordpress/i18n";
|
|
24
|
+
// src/store/store.ts
|
|
25
|
+
import {
|
|
26
|
+
__createSelector as createSelector,
|
|
27
|
+
__createSlice as createSlice
|
|
28
|
+
} from "@elementor/store";
|
|
21
29
|
|
|
22
|
-
// src/
|
|
23
|
-
import {
|
|
30
|
+
// src/store/thunks.ts
|
|
31
|
+
import { __createAsyncThunk as createAsyncThunk } from "@elementor/store";
|
|
24
32
|
|
|
25
33
|
// src/api.ts
|
|
34
|
+
import { ajax } from "@elementor/editor-v1-adapters";
|
|
26
35
|
import { httpService } from "@elementor/http-client";
|
|
27
36
|
var BASE_URL = "elementor/v1/components";
|
|
37
|
+
var getParams = (id) => ({
|
|
38
|
+
action: "get_document_config",
|
|
39
|
+
unique_id: `document-config-${id}`,
|
|
40
|
+
data: { id }
|
|
41
|
+
});
|
|
28
42
|
var apiClient = {
|
|
29
43
|
get: () => httpService().get(`${BASE_URL}`).then((res) => res.data.data),
|
|
30
|
-
create: (payload) => httpService().post(`${BASE_URL}`, payload).then((res) => res.data.data)
|
|
44
|
+
create: (payload) => httpService().post(`${BASE_URL}`, payload).then((res) => res.data.data),
|
|
45
|
+
updateStatuses: (ids, status) => httpService().put(`${BASE_URL}/status`, {
|
|
46
|
+
ids,
|
|
47
|
+
status
|
|
48
|
+
}),
|
|
49
|
+
getComponentConfig: (id) => ajax.load(getParams(id)),
|
|
50
|
+
invalidateComponentConfigCache: (id) => ajax.invalidateCache(getParams(id)),
|
|
51
|
+
getComponentLockStatus: async (componentId) => await httpService().get(`${BASE_URL}/lock-status`, {
|
|
52
|
+
params: {
|
|
53
|
+
componentId
|
|
54
|
+
}
|
|
55
|
+
}).then((res) => {
|
|
56
|
+
const { is_current_user_allow_to_edit: isAllowedToSwitchDocument, locked_by: lockedBy } = res.data.data;
|
|
57
|
+
return { isAllowedToSwitchDocument, lockedBy: lockedBy || "" };
|
|
58
|
+
}),
|
|
59
|
+
lockComponent: async (componentId) => await httpService().post(`${BASE_URL}/lock`, {
|
|
60
|
+
componentId
|
|
61
|
+
}).then((res) => res.data),
|
|
62
|
+
unlockComponent: async (componentId) => await httpService().post(`${BASE_URL}/unlock`, {
|
|
63
|
+
componentId
|
|
64
|
+
}).then((res) => res.data),
|
|
65
|
+
getOverridableProps: async (componentId) => await httpService().get(`${BASE_URL}/overridable-props`, {
|
|
66
|
+
params: {
|
|
67
|
+
componentId: componentId.toString()
|
|
68
|
+
}
|
|
69
|
+
}).then((res) => res.data.data),
|
|
70
|
+
updateArchivedComponents: async (componentIds) => await httpService().post(
|
|
71
|
+
`${BASE_URL}/archive`,
|
|
72
|
+
{
|
|
73
|
+
componentIds
|
|
74
|
+
}
|
|
75
|
+
).then((res) => res.data.data)
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/store/thunks.ts
|
|
79
|
+
var loadComponents = createAsyncThunk("components/load", async () => {
|
|
80
|
+
const response = await apiClient.get();
|
|
81
|
+
return response;
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// src/store/store.ts
|
|
85
|
+
var initialState = {
|
|
86
|
+
data: [],
|
|
87
|
+
unpublishedData: [],
|
|
88
|
+
loadStatus: "idle",
|
|
89
|
+
styles: {},
|
|
90
|
+
createdThisSession: [],
|
|
91
|
+
archivedData: [],
|
|
92
|
+
path: [],
|
|
93
|
+
currentComponentId: null
|
|
94
|
+
};
|
|
95
|
+
var SLICE_NAME = "components";
|
|
96
|
+
var slice = createSlice({
|
|
97
|
+
name: SLICE_NAME,
|
|
98
|
+
initialState,
|
|
99
|
+
reducers: {
|
|
100
|
+
add: (state, { payload }) => {
|
|
101
|
+
if (Array.isArray(payload)) {
|
|
102
|
+
state.data = [...state.data, ...payload];
|
|
103
|
+
} else {
|
|
104
|
+
state.data.unshift(payload);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
load: (state, { payload }) => {
|
|
108
|
+
state.data = payload;
|
|
109
|
+
},
|
|
110
|
+
addUnpublished: (state, { payload }) => {
|
|
111
|
+
state.unpublishedData.unshift(payload);
|
|
112
|
+
},
|
|
113
|
+
resetUnpublished: (state) => {
|
|
114
|
+
state.unpublishedData = [];
|
|
115
|
+
},
|
|
116
|
+
removeStyles(state, { payload }) {
|
|
117
|
+
const { [payload.id]: _, ...rest } = state.styles;
|
|
118
|
+
state.styles = rest;
|
|
119
|
+
},
|
|
120
|
+
addStyles: (state, { payload }) => {
|
|
121
|
+
state.styles = { ...state.styles, ...payload };
|
|
122
|
+
},
|
|
123
|
+
addCreatedThisSession: (state, { payload }) => {
|
|
124
|
+
state.createdThisSession.push(payload);
|
|
125
|
+
},
|
|
126
|
+
archive: (state, { payload }) => {
|
|
127
|
+
state.data = state.data.filter((component) => {
|
|
128
|
+
const isArchived = component.id === payload;
|
|
129
|
+
if (isArchived) {
|
|
130
|
+
state.archivedData.push(component);
|
|
131
|
+
}
|
|
132
|
+
return !isArchived;
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
setCurrentComponentId: (state, { payload }) => {
|
|
136
|
+
state.currentComponentId = payload;
|
|
137
|
+
},
|
|
138
|
+
setPath: (state, { payload }) => {
|
|
139
|
+
state.path = payload;
|
|
140
|
+
},
|
|
141
|
+
setOverridableProps: (state, { payload }) => {
|
|
142
|
+
const component = state.data.find((comp) => comp.id === payload.componentId);
|
|
143
|
+
if (!component) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
component.overridableProps = payload.overridableProps;
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
extraReducers: (builder) => {
|
|
150
|
+
builder.addCase(loadComponents.fulfilled, (state, { payload }) => {
|
|
151
|
+
state.data = payload;
|
|
152
|
+
state.loadStatus = "idle";
|
|
153
|
+
});
|
|
154
|
+
builder.addCase(loadComponents.pending, (state) => {
|
|
155
|
+
state.loadStatus = "pending";
|
|
156
|
+
});
|
|
157
|
+
builder.addCase(loadComponents.rejected, (state) => {
|
|
158
|
+
state.loadStatus = "error";
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
var selectData = (state) => state[SLICE_NAME].data;
|
|
163
|
+
var selectArchivedData = (state) => state[SLICE_NAME].archivedData;
|
|
164
|
+
var selectLoadStatus = (state) => state[SLICE_NAME].loadStatus;
|
|
165
|
+
var selectStylesDefinitions = (state) => state[SLICE_NAME].styles ?? {};
|
|
166
|
+
var selectUnpublishedData = (state) => state[SLICE_NAME].unpublishedData;
|
|
167
|
+
var getCreatedThisSession = (state) => state[SLICE_NAME].createdThisSession;
|
|
168
|
+
var getPath = (state) => state[SLICE_NAME].path;
|
|
169
|
+
var getCurrentComponentId = (state) => state[SLICE_NAME].currentComponentId;
|
|
170
|
+
var selectComponent = (state, componentId) => state[SLICE_NAME].data.find((component) => component.id === componentId);
|
|
171
|
+
var selectComponents = createSelector(
|
|
172
|
+
selectData,
|
|
173
|
+
selectUnpublishedData,
|
|
174
|
+
(data, unpublishedData) => [
|
|
175
|
+
...unpublishedData.map((item) => ({ uid: item.uid, name: item.name })),
|
|
176
|
+
...data
|
|
177
|
+
]
|
|
178
|
+
);
|
|
179
|
+
var selectUnpublishedComponents = createSelector(
|
|
180
|
+
selectUnpublishedData,
|
|
181
|
+
(unpublishedData) => unpublishedData
|
|
182
|
+
);
|
|
183
|
+
var selectLoadIsPending = createSelector(selectLoadStatus, (status) => status === "pending");
|
|
184
|
+
var selectLoadIsError = createSelector(selectLoadStatus, (status) => status === "error");
|
|
185
|
+
var selectStyles = (state) => state[SLICE_NAME].styles ?? {};
|
|
186
|
+
var selectFlatStyles = createSelector(selectStylesDefinitions, (data) => Object.values(data).flat());
|
|
187
|
+
var selectCreatedThisSession = createSelector(
|
|
188
|
+
getCreatedThisSession,
|
|
189
|
+
(createdThisSession) => createdThisSession
|
|
190
|
+
);
|
|
191
|
+
var DEFAULT_OVERRIDABLE_PROPS = {
|
|
192
|
+
props: {},
|
|
193
|
+
groups: {
|
|
194
|
+
items: {},
|
|
195
|
+
order: []
|
|
196
|
+
}
|
|
31
197
|
};
|
|
198
|
+
var selectOverridableProps = createSelector(
|
|
199
|
+
selectComponent,
|
|
200
|
+
(component) => {
|
|
201
|
+
if (!component) {
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
return component.overridableProps ?? DEFAULT_OVERRIDABLE_PROPS;
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
var selectIsOverridablePropsLoaded = createSelector(
|
|
208
|
+
selectComponent,
|
|
209
|
+
(component) => {
|
|
210
|
+
return !!component?.overridableProps;
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
var selectPath = createSelector(getPath, (path) => path);
|
|
214
|
+
var selectCurrentComponentId = createSelector(
|
|
215
|
+
getCurrentComponentId,
|
|
216
|
+
(currentComponentId) => currentComponentId
|
|
217
|
+
);
|
|
218
|
+
var selectArchivedComponents = createSelector(
|
|
219
|
+
selectArchivedData,
|
|
220
|
+
(archivedData) => archivedData
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
// src/utils/component-document-data.ts
|
|
224
|
+
import { getV1DocumentsManager } from "@elementor/editor-documents";
|
|
225
|
+
var getComponentDocumentData = async (id) => {
|
|
226
|
+
const documentManager = getV1DocumentsManager();
|
|
227
|
+
try {
|
|
228
|
+
return await documentManager.request(id);
|
|
229
|
+
} catch {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
var invalidateComponentDocumentData = (id) => {
|
|
234
|
+
const documentManager = getV1DocumentsManager();
|
|
235
|
+
documentManager.invalidateCache(id);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// src/component-instance-transformer.ts
|
|
239
|
+
var componentInstanceTransformer = createTransformer(
|
|
240
|
+
async ({ component_id: id }) => {
|
|
241
|
+
const unpublishedComponents = selectUnpublishedComponents(getState());
|
|
242
|
+
const unpublishedComponent = unpublishedComponents.find(({ uid }) => uid === id);
|
|
243
|
+
if (unpublishedComponent) {
|
|
244
|
+
return structuredClone(unpublishedComponent.elements);
|
|
245
|
+
}
|
|
246
|
+
if (typeof id !== "number") {
|
|
247
|
+
throw new Error(`Component ID "${id}" not found.`);
|
|
248
|
+
}
|
|
249
|
+
const data = await getComponentDocumentData(id);
|
|
250
|
+
return data?.elements ?? [];
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
// src/component-overridable-transformer.ts
|
|
255
|
+
import { createTransformer as createTransformer2, settingsTransformersRegistry } from "@elementor/editor-canvas";
|
|
256
|
+
var componentOverridableTransformer = createTransformer2(
|
|
257
|
+
async (value, options) => {
|
|
258
|
+
return await transformOriginValue(value, options);
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
async function transformOriginValue(value, options) {
|
|
262
|
+
if (!value.origin_value || !value.origin_value.value || !value.origin_value.$$type) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
const transformer = settingsTransformersRegistry.get(value.origin_value.$$type);
|
|
266
|
+
if (!transformer) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
return await transformer(value.origin_value.value, options);
|
|
271
|
+
} catch {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// src/components/component-panel-header/component-panel-header.tsx
|
|
277
|
+
import * as React2 from "react";
|
|
278
|
+
import { getV1DocumentsManager as getV1DocumentsManager3 } from "@elementor/editor-documents";
|
|
279
|
+
import { ArrowLeftIcon, ComponentsIcon } from "@elementor/icons";
|
|
280
|
+
import { __useSelector as useSelector3 } from "@elementor/store";
|
|
281
|
+
import { Box as Box2, Divider, IconButton, Stack, Tooltip, Typography } from "@elementor/ui";
|
|
282
|
+
import { __ as __2 } from "@wordpress/i18n";
|
|
283
|
+
|
|
284
|
+
// src/hooks/use-navigate-back.ts
|
|
285
|
+
import { useCallback } from "react";
|
|
286
|
+
import { getV1DocumentsManager as getV1DocumentsManager2 } from "@elementor/editor-documents";
|
|
287
|
+
import { __privateRunCommand as runCommand } from "@elementor/editor-v1-adapters";
|
|
288
|
+
import { __useSelector as useSelector } from "@elementor/store";
|
|
289
|
+
function useNavigateBack() {
|
|
290
|
+
const path = useSelector(selectPath);
|
|
291
|
+
const documentsManager = getV1DocumentsManager2();
|
|
292
|
+
return useCallback(() => {
|
|
293
|
+
const { componentId: prevComponentId, instanceId: prevComponentInstanceId } = path.at(-2) ?? {};
|
|
294
|
+
const switchToDocument = (id, selector) => {
|
|
295
|
+
runCommand("editor/documents/switch", {
|
|
296
|
+
id,
|
|
297
|
+
selector,
|
|
298
|
+
mode: "autosave",
|
|
299
|
+
setAsInitial: false,
|
|
300
|
+
shouldScroll: false
|
|
301
|
+
});
|
|
302
|
+
};
|
|
303
|
+
if (prevComponentId && prevComponentInstanceId) {
|
|
304
|
+
switchToDocument(prevComponentId, `[data-id="${prevComponentInstanceId}"]`);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
switchToDocument(documentsManager.getInitialId());
|
|
308
|
+
}, [path, documentsManager]);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/components/component-panel-header/component-badge.tsx
|
|
312
|
+
import * as React from "react";
|
|
313
|
+
import { useEffect, useRef } from "react";
|
|
314
|
+
import { SettingsIcon } from "@elementor/icons";
|
|
315
|
+
import { Badge, Box, keyframes, styled, ToggleButton } from "@elementor/ui";
|
|
316
|
+
import { __ } from "@wordpress/i18n";
|
|
317
|
+
var ComponentsBadge = ({ overridesCount }) => {
|
|
318
|
+
const prevCount = usePrevious(overridesCount);
|
|
319
|
+
const isFirstOverride = prevCount === 0 && overridesCount === 1;
|
|
320
|
+
return /* @__PURE__ */ React.createElement(
|
|
321
|
+
StyledBadge,
|
|
322
|
+
{
|
|
323
|
+
color: "primary",
|
|
324
|
+
key: overridesCount,
|
|
325
|
+
invisible: overridesCount === 0,
|
|
326
|
+
animate: isFirstOverride,
|
|
327
|
+
anchorOrigin: { vertical: "top", horizontal: "right" },
|
|
328
|
+
badgeContent: /* @__PURE__ */ React.createElement(Box, { sx: { animation: !isFirstOverride ? `${slideUp} 300ms ease-out` : "none" } }, overridesCount)
|
|
329
|
+
},
|
|
330
|
+
/* @__PURE__ */ React.createElement(ToggleButton, { value: "overrides", size: "tiny", "aria-label": __("View overrides", "elementor") }, /* @__PURE__ */ React.createElement(SettingsIcon, { fontSize: "tiny" }))
|
|
331
|
+
);
|
|
332
|
+
};
|
|
333
|
+
var StyledBadge = styled(Badge, { shouldForwardProp: (prop) => prop !== "animate" })(
|
|
334
|
+
({ theme, animate }) => ({
|
|
335
|
+
"& .MuiBadge-badge": {
|
|
336
|
+
minWidth: theme.spacing(2),
|
|
337
|
+
height: theme.spacing(2),
|
|
338
|
+
minHeight: theme.spacing(2),
|
|
339
|
+
maxWidth: theme.spacing(2),
|
|
340
|
+
fontSize: theme.typography.caption.fontSize,
|
|
341
|
+
animation: animate ? `${bounceIn} 300ms ease-out` : "none"
|
|
342
|
+
}
|
|
343
|
+
})
|
|
344
|
+
);
|
|
345
|
+
function usePrevious(value) {
|
|
346
|
+
const ref = useRef(value);
|
|
347
|
+
useEffect(() => {
|
|
348
|
+
ref.current = value;
|
|
349
|
+
}, [value]);
|
|
350
|
+
return ref.current;
|
|
351
|
+
}
|
|
352
|
+
var bounceIn = keyframes`
|
|
353
|
+
0% { transform: scale(0) translate(50%, 50%); opacity: 0; }
|
|
354
|
+
70% { transform: scale(1.1) translate(50%, -50%); opacity: 1; }
|
|
355
|
+
100% { transform: scale(1) translate(50%, -50%); opacity: 1; }
|
|
356
|
+
`;
|
|
357
|
+
var slideUp = keyframes`
|
|
358
|
+
from { transform: translateY(100%); opacity: 0; }
|
|
359
|
+
to { transform: translateY(0); opacity: 1; }
|
|
360
|
+
`;
|
|
361
|
+
|
|
362
|
+
// src/components/component-panel-header/use-overridable-props.ts
|
|
363
|
+
import { __useSelector as useSelector2 } from "@elementor/store";
|
|
364
|
+
function useOverridableProps(componentId) {
|
|
365
|
+
return useSelector2((state) => {
|
|
366
|
+
if (!componentId) {
|
|
367
|
+
return void 0;
|
|
368
|
+
}
|
|
369
|
+
return selectOverridableProps(state, componentId);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/components/component-panel-header/component-panel-header.tsx
|
|
374
|
+
var ComponentPanelHeader = () => {
|
|
375
|
+
const currentComponentId = useSelector3(selectCurrentComponentId);
|
|
376
|
+
const overridableProps = useOverridableProps(currentComponentId);
|
|
377
|
+
const onBack = useNavigateBack();
|
|
378
|
+
const componentName = getComponentName();
|
|
379
|
+
const overridesCount = overridableProps ? Object.keys(overridableProps.props).length : 0;
|
|
380
|
+
if (!currentComponentId) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
return /* @__PURE__ */ React2.createElement(Box2, null, /* @__PURE__ */ React2.createElement(
|
|
384
|
+
Stack,
|
|
385
|
+
{
|
|
386
|
+
direction: "row",
|
|
387
|
+
alignItems: "center",
|
|
388
|
+
justifyContent: "space-between",
|
|
389
|
+
sx: { height: 48, pl: 1.5, pr: 2, py: 1 }
|
|
390
|
+
},
|
|
391
|
+
/* @__PURE__ */ React2.createElement(Stack, { direction: "row", alignItems: "center", gap: 0.5 }, /* @__PURE__ */ React2.createElement(Tooltip, { title: __2("Back", "elementor") }, /* @__PURE__ */ React2.createElement(IconButton, { size: "tiny", onClick: onBack, "aria-label": __2("Back", "elementor") }, /* @__PURE__ */ React2.createElement(ArrowLeftIcon, null))), /* @__PURE__ */ React2.createElement(Stack, { direction: "row", alignItems: "center", gap: 0.5 }, /* @__PURE__ */ React2.createElement(ComponentsIcon, { color: "secondary", fontSize: "tiny" }), /* @__PURE__ */ React2.createElement(Typography, { variant: "caption", sx: { fontWeight: 500 } }, componentName))),
|
|
392
|
+
/* @__PURE__ */ React2.createElement(ComponentsBadge, { overridesCount })
|
|
393
|
+
), /* @__PURE__ */ React2.createElement(Divider, null));
|
|
394
|
+
};
|
|
395
|
+
function getComponentName() {
|
|
396
|
+
const documentsManager = getV1DocumentsManager3();
|
|
397
|
+
const currentDocument = documentsManager.getCurrent();
|
|
398
|
+
return currentDocument?.container?.settings?.get("post_title") ?? "";
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// src/components/components-tab/components.tsx
|
|
402
|
+
import * as React8 from "react";
|
|
403
|
+
import { ThemeProvider } from "@elementor/editor-ui";
|
|
404
|
+
|
|
405
|
+
// src/components/components-tab/component-search.tsx
|
|
406
|
+
import * as React4 from "react";
|
|
407
|
+
import { SearchIcon } from "@elementor/icons";
|
|
408
|
+
import { Box as Box3, InputAdornment, Stack as Stack2, TextField } from "@elementor/ui";
|
|
409
|
+
import { __ as __3 } from "@wordpress/i18n";
|
|
410
|
+
|
|
411
|
+
// src/components/components-tab/search-provider.tsx
|
|
412
|
+
import * as React3 from "react";
|
|
413
|
+
import { createContext, useContext } from "react";
|
|
414
|
+
import { useSearchState } from "@elementor/utils";
|
|
415
|
+
var SearchContext = createContext(void 0);
|
|
416
|
+
var SearchProvider = ({
|
|
417
|
+
children,
|
|
418
|
+
localStorageKey
|
|
419
|
+
}) => {
|
|
420
|
+
const { debouncedValue, handleChange, inputValue } = useSearchState({ localStorageKey });
|
|
421
|
+
const clearSearch = () => {
|
|
422
|
+
handleChange("");
|
|
423
|
+
};
|
|
424
|
+
return /* @__PURE__ */ React3.createElement(SearchContext.Provider, { value: { handleChange, clearSearch, searchValue: debouncedValue, inputValue } }, children);
|
|
425
|
+
};
|
|
426
|
+
var useSearch = () => {
|
|
427
|
+
const context = useContext(SearchContext);
|
|
428
|
+
if (!context) {
|
|
429
|
+
throw new Error("useSearch must be used within a SearchProvider");
|
|
430
|
+
}
|
|
431
|
+
return context;
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// src/components/components-tab/component-search.tsx
|
|
435
|
+
var ComponentSearch = () => {
|
|
436
|
+
const { inputValue, handleChange } = useSearch();
|
|
437
|
+
return /* @__PURE__ */ React4.createElement(Stack2, { direction: "row", gap: 0.5, sx: { width: "100%", px: 2, py: 1.5 } }, /* @__PURE__ */ React4.createElement(Box3, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React4.createElement(
|
|
438
|
+
TextField,
|
|
439
|
+
{
|
|
440
|
+
role: "search",
|
|
441
|
+
fullWidth: true,
|
|
442
|
+
size: "tiny",
|
|
443
|
+
value: inputValue,
|
|
444
|
+
placeholder: __3("Search", "elementor"),
|
|
445
|
+
onChange: (e) => handleChange(e.target.value),
|
|
446
|
+
InputProps: {
|
|
447
|
+
startAdornment: /* @__PURE__ */ React4.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React4.createElement(SearchIcon, { fontSize: "tiny" }))
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
)));
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
// src/components/components-tab/components-list.tsx
|
|
454
|
+
import * as React7 from "react";
|
|
455
|
+
import { ComponentsIcon as ComponentsIcon3, EyeIcon } from "@elementor/icons";
|
|
456
|
+
import { Box as Box6, Divider as Divider2, Icon, Link, List, Stack as Stack4, Typography as Typography3 } from "@elementor/ui";
|
|
457
|
+
import { __ as __6 } from "@wordpress/i18n";
|
|
32
458
|
|
|
33
459
|
// src/hooks/use-components.ts
|
|
34
|
-
|
|
460
|
+
import { __useSelector as useSelector4 } from "@elementor/store";
|
|
35
461
|
var useComponents = () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
462
|
+
const components = useSelector4(selectComponents);
|
|
463
|
+
const isLoading = useSelector4(selectLoadIsPending);
|
|
464
|
+
return { components, isLoading };
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
// src/components/components-tab/components-item.tsx
|
|
468
|
+
import * as React5 from "react";
|
|
469
|
+
import { endDragElementFromPanel, startDragElementFromPanel } from "@elementor/editor-canvas";
|
|
470
|
+
import { dropElement } from "@elementor/editor-elements";
|
|
471
|
+
import { MenuListItem } from "@elementor/editor-ui";
|
|
472
|
+
import { ComponentsIcon as ComponentsIcon2, DotsVerticalIcon } from "@elementor/icons";
|
|
473
|
+
import {
|
|
474
|
+
bindMenu,
|
|
475
|
+
bindTrigger,
|
|
476
|
+
Box as Box4,
|
|
477
|
+
IconButton as IconButton2,
|
|
478
|
+
ListItemButton,
|
|
479
|
+
ListItemIcon,
|
|
480
|
+
ListItemText,
|
|
481
|
+
Menu,
|
|
482
|
+
Typography as Typography2,
|
|
483
|
+
usePopupState
|
|
484
|
+
} from "@elementor/ui";
|
|
485
|
+
import { __ as __5 } from "@wordpress/i18n";
|
|
486
|
+
|
|
487
|
+
// src/store/actions/archive-component.ts
|
|
488
|
+
import { setDocumentModifiedStatus } from "@elementor/editor-documents";
|
|
489
|
+
import { __getStore as getStore } from "@elementor/store";
|
|
490
|
+
var archiveComponent = (componentId) => {
|
|
491
|
+
const store = getStore();
|
|
492
|
+
const dispatch9 = store?.dispatch;
|
|
493
|
+
if (!dispatch9) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
dispatch9(slice.actions.archive(componentId));
|
|
497
|
+
setDocumentModifiedStatus(true);
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// src/store/actions/load-components-assets.ts
|
|
501
|
+
import { isDocumentDirty, setDocumentModifiedStatus as setDocumentModifiedStatus2 } from "@elementor/editor-documents";
|
|
502
|
+
|
|
503
|
+
// src/create-component-type.ts
|
|
504
|
+
import {
|
|
505
|
+
createTemplatedElementView
|
|
506
|
+
} from "@elementor/editor-canvas";
|
|
507
|
+
import { getCurrentDocument } from "@elementor/editor-documents";
|
|
508
|
+
import { __privateRunCommand as runCommand2 } from "@elementor/editor-v1-adapters";
|
|
509
|
+
import { __ as __4 } from "@wordpress/i18n";
|
|
510
|
+
|
|
511
|
+
// src/utils/tracking.ts
|
|
512
|
+
import { getMixpanel } from "@elementor/mixpanel";
|
|
513
|
+
import { __getState as getState2 } from "@elementor/store";
|
|
514
|
+
var trackComponentEvent = ({ action, ...data }) => {
|
|
515
|
+
const { dispatchEvent, config } = getMixpanel();
|
|
516
|
+
if (!config?.names?.components?.[action]) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
const name = config.names.components[action];
|
|
520
|
+
dispatchEvent?.(name, data);
|
|
521
|
+
};
|
|
522
|
+
var onElementDrop = (_args, element) => {
|
|
523
|
+
if (!(element.model.get("widgetType") === "e-component")) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const editorSettings = element.model.get("editor_settings");
|
|
527
|
+
const componentName = editorSettings?.title;
|
|
528
|
+
const componentUID = editorSettings?.component_uid;
|
|
529
|
+
const instanceId = element.id;
|
|
530
|
+
const createdThisSession = selectCreatedThisSession(getState2());
|
|
531
|
+
const isSameSessionReuse = componentUID && createdThisSession.includes(componentUID);
|
|
532
|
+
const eventsManagerConfig = window.elementorCommon.eventsManager.config;
|
|
533
|
+
const { locations, secondaryLocations } = eventsManagerConfig;
|
|
534
|
+
trackComponentEvent({
|
|
535
|
+
action: "instanceAdded",
|
|
536
|
+
instance_id: instanceId,
|
|
537
|
+
component_uid: componentUID,
|
|
538
|
+
component_name: componentName,
|
|
539
|
+
is_same_session_reuse: isSameSessionReuse,
|
|
540
|
+
location: locations.widgetPanel,
|
|
541
|
+
secondary_location: secondaryLocations.componentsTab
|
|
542
|
+
});
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
// src/create-component-type.ts
|
|
546
|
+
var TYPE = "e-component";
|
|
547
|
+
function createComponentType(options) {
|
|
548
|
+
const legacyWindow = window;
|
|
549
|
+
return class extends legacyWindow.elementor.modules.elements.types.Widget {
|
|
550
|
+
getType() {
|
|
551
|
+
return options.type;
|
|
552
|
+
}
|
|
553
|
+
getView() {
|
|
554
|
+
return createComponentView(options);
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
function createComponentView(options) {
|
|
559
|
+
return class extends createTemplatedElementView(options) {
|
|
560
|
+
legacyWindow = window;
|
|
561
|
+
eventsManagerConfig = this.legacyWindow.elementorCommon.eventsManager.config;
|
|
562
|
+
isComponentCurrentlyEdited() {
|
|
563
|
+
const currentDocument = getCurrentDocument();
|
|
564
|
+
return currentDocument?.id === this.getComponentId();
|
|
565
|
+
}
|
|
566
|
+
afterSettingsResolve(settings) {
|
|
567
|
+
if (settings.component_instance) {
|
|
568
|
+
this.collection = this.legacyWindow.elementor.createBackboneElementsCollection(
|
|
569
|
+
settings.component_instance
|
|
570
|
+
);
|
|
571
|
+
this.collection.models.forEach(setInactiveRecursively);
|
|
572
|
+
settings.component_instance = "<template data-children-placeholder></template>";
|
|
573
|
+
}
|
|
574
|
+
return settings;
|
|
575
|
+
}
|
|
576
|
+
getDomElement() {
|
|
577
|
+
return this.children.findByIndex(0)?.getDomElement() ?? this.$el;
|
|
578
|
+
}
|
|
579
|
+
attachBuffer(collectionView, buffer) {
|
|
580
|
+
const childrenPlaceholder = collectionView.$el.find("[data-children-placeholder]").get(0);
|
|
581
|
+
if (!childrenPlaceholder) {
|
|
582
|
+
super.attachBuffer(collectionView, buffer);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
childrenPlaceholder.replaceWith(buffer);
|
|
586
|
+
}
|
|
587
|
+
getComponentId() {
|
|
588
|
+
const componentInstance = this.options?.model?.get("settings")?.get("component_instance")?.value;
|
|
589
|
+
return componentInstance.component_id;
|
|
590
|
+
}
|
|
591
|
+
getContextMenuGroups() {
|
|
592
|
+
const filteredGroups = super.getContextMenuGroups().filter((group) => group.name !== "save");
|
|
593
|
+
const componentId = this.getComponentId();
|
|
594
|
+
if (!componentId) {
|
|
595
|
+
return filteredGroups;
|
|
596
|
+
}
|
|
597
|
+
const newGroup = [
|
|
598
|
+
{
|
|
599
|
+
name: "edit component",
|
|
600
|
+
actions: [
|
|
601
|
+
{
|
|
602
|
+
name: "edit component",
|
|
603
|
+
icon: "eicon-edit",
|
|
604
|
+
title: () => __4("Edit Component", "elementor"),
|
|
605
|
+
isEnabled: () => true,
|
|
606
|
+
callback: (_, eventData) => this.editComponent(eventData)
|
|
607
|
+
}
|
|
608
|
+
]
|
|
609
|
+
}
|
|
610
|
+
];
|
|
611
|
+
return [...filteredGroups, ...newGroup];
|
|
612
|
+
}
|
|
613
|
+
async switchDocument() {
|
|
614
|
+
const { isAllowedToSwitchDocument, lockedBy } = await apiClient.getComponentLockStatus(
|
|
615
|
+
this.getComponentId()
|
|
616
|
+
);
|
|
617
|
+
if (!isAllowedToSwitchDocument) {
|
|
618
|
+
options.showLockedByModal?.(lockedBy || "");
|
|
619
|
+
} else {
|
|
620
|
+
runCommand2("editor/documents/switch", {
|
|
621
|
+
id: this.getComponentId(),
|
|
622
|
+
mode: "autosave",
|
|
623
|
+
selector: `[data-id="${this.model.get("id")}"]`,
|
|
624
|
+
shouldScroll: false
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
editComponent({ trigger, location, secondaryLocation }) {
|
|
629
|
+
if (this.isComponentCurrentlyEdited()) {
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
this.switchDocument();
|
|
633
|
+
const editorSettings = this.model.get("editor_settings");
|
|
634
|
+
trackComponentEvent({
|
|
635
|
+
action: "edited",
|
|
636
|
+
component_uid: editorSettings?.component_uid,
|
|
637
|
+
component_name: editorSettings?.title,
|
|
638
|
+
location,
|
|
639
|
+
secondary_location: secondaryLocation,
|
|
640
|
+
trigger
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
handleDblClick(e) {
|
|
644
|
+
e.stopPropagation();
|
|
645
|
+
const { triggers, locations, secondaryLocations } = this.eventsManagerConfig;
|
|
646
|
+
this.editComponent({
|
|
647
|
+
trigger: triggers.doubleClick,
|
|
648
|
+
location: locations.canvas,
|
|
649
|
+
secondaryLocation: secondaryLocations.canvasElement
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
events() {
|
|
653
|
+
return {
|
|
654
|
+
...super.events(),
|
|
655
|
+
dblclick: this.handleDblClick
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
attributes() {
|
|
659
|
+
return {
|
|
660
|
+
...super.attributes(),
|
|
661
|
+
"data-elementor-id": this.getComponentId()
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
function setInactiveRecursively(model) {
|
|
667
|
+
const editSettings = model.get("editSettings");
|
|
668
|
+
if (editSettings) {
|
|
669
|
+
editSettings.set("inactive", true);
|
|
670
|
+
}
|
|
671
|
+
const elements = model.get("elements");
|
|
672
|
+
if (elements) {
|
|
673
|
+
elements.forEach((childModel) => {
|
|
674
|
+
setInactiveRecursively(childModel);
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// src/utils/get-component-ids.ts
|
|
680
|
+
var getComponentIds = async (elements) => {
|
|
681
|
+
const components = elements.map(async ({ widgetType, elType, elements: childElements, settings }) => {
|
|
682
|
+
const ids = [];
|
|
683
|
+
const isComponent = [widgetType, elType].includes(TYPE);
|
|
684
|
+
if (isComponent) {
|
|
685
|
+
const componentId = settings?.component_instance?.value?.component_id;
|
|
686
|
+
const document = await getComponentDocumentData(componentId);
|
|
687
|
+
childElements = document?.elements;
|
|
688
|
+
if (Boolean(componentId)) {
|
|
689
|
+
ids.push(componentId);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
if (!!childElements?.length) {
|
|
693
|
+
ids.push(...await getComponentIds(childElements));
|
|
694
|
+
}
|
|
695
|
+
return ids;
|
|
40
696
|
});
|
|
697
|
+
const result = (await Promise.all(components)).flat();
|
|
698
|
+
return Array.from(new Set(result));
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
// src/store/actions/load-components-overridable-props.ts
|
|
702
|
+
import { __dispatch as dispatch, __getState as getState3 } from "@elementor/store";
|
|
703
|
+
function loadComponentsOverridableProps(componentIds) {
|
|
704
|
+
if (!componentIds.length) {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
componentIds.forEach(loadComponentOverrides);
|
|
708
|
+
}
|
|
709
|
+
async function loadComponentOverrides(componentId) {
|
|
710
|
+
const isOverridablePropsLoaded = selectIsOverridablePropsLoaded(getState3(), componentId);
|
|
711
|
+
if (isOverridablePropsLoaded) {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
const overridableProps = await apiClient.getOverridableProps(componentId);
|
|
715
|
+
if (!overridableProps) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
dispatch(
|
|
719
|
+
slice.actions.setOverridableProps({
|
|
720
|
+
componentId,
|
|
721
|
+
overridableProps
|
|
722
|
+
})
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// src/store/actions/load-components-styles.ts
|
|
727
|
+
import { __dispatch as dispatch2, __getState as getState4 } from "@elementor/store";
|
|
728
|
+
async function loadComponentsStyles(componentIds) {
|
|
729
|
+
if (!componentIds.length) {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
const knownComponents = selectStyles(getState4());
|
|
733
|
+
const unknownComponentIds = componentIds.filter((id) => !knownComponents[id]);
|
|
734
|
+
if (!unknownComponentIds.length) {
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
addComponentStyles(unknownComponentIds);
|
|
738
|
+
}
|
|
739
|
+
async function addComponentStyles(ids) {
|
|
740
|
+
const newComponents = await loadStyles(ids);
|
|
741
|
+
addStyles(newComponents);
|
|
742
|
+
}
|
|
743
|
+
async function loadStyles(ids) {
|
|
744
|
+
return Promise.all(ids.map(async (id) => [id, await apiClient.getComponentConfig(id)]));
|
|
745
|
+
}
|
|
746
|
+
function addStyles(data) {
|
|
747
|
+
const styles = Object.fromEntries(
|
|
748
|
+
data.map(([componentId, componentData]) => [componentId, extractStyles(componentData)])
|
|
749
|
+
);
|
|
750
|
+
dispatch2(slice.actions.addStyles(styles));
|
|
751
|
+
}
|
|
752
|
+
function extractStyles(element) {
|
|
753
|
+
return [...Object.values(element.styles ?? {}), ...(element.elements ?? []).flatMap(extractStyles)];
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// src/store/actions/load-components-assets.ts
|
|
757
|
+
async function loadComponentsAssets(elements) {
|
|
758
|
+
const componentIds = await getComponentIds(elements);
|
|
759
|
+
return Promise.all([
|
|
760
|
+
updateDocumentState(componentIds),
|
|
761
|
+
loadComponentsOverridableProps(componentIds),
|
|
762
|
+
loadComponentsStyles(componentIds)
|
|
763
|
+
]);
|
|
764
|
+
}
|
|
765
|
+
async function updateDocumentState(componentIds) {
|
|
766
|
+
const components = (await Promise.all(componentIds.map(getComponentDocumentData))).filter(
|
|
767
|
+
(document) => !!document
|
|
768
|
+
);
|
|
769
|
+
const isDrafted = components.some(isDocumentDirty);
|
|
770
|
+
if (isDrafted) {
|
|
771
|
+
setDocumentModifiedStatus2(true);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// src/utils/get-container-for-new-element.ts
|
|
776
|
+
import {
|
|
777
|
+
getContainer,
|
|
778
|
+
getCurrentDocumentContainer,
|
|
779
|
+
getSelectedElements
|
|
780
|
+
} from "@elementor/editor-elements";
|
|
781
|
+
var getContainerForNewElement = () => {
|
|
782
|
+
const currentDocumentContainer = getCurrentDocumentContainer();
|
|
783
|
+
const selectedElement = getSelectedElementContainer();
|
|
784
|
+
let container, options;
|
|
785
|
+
if (selectedElement) {
|
|
786
|
+
switch (selectedElement.model.get("elType")) {
|
|
787
|
+
case "widget": {
|
|
788
|
+
container = selectedElement?.parent;
|
|
789
|
+
const selectedElIndex = selectedElement.view?._index ?? -1;
|
|
790
|
+
if (selectedElIndex > -1) {
|
|
791
|
+
options = { at: selectedElIndex + 1 };
|
|
792
|
+
}
|
|
793
|
+
break;
|
|
794
|
+
}
|
|
795
|
+
case "section": {
|
|
796
|
+
container = selectedElement?.children?.[0];
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
799
|
+
default: {
|
|
800
|
+
container = selectedElement;
|
|
801
|
+
break;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
return { container: container ?? currentDocumentContainer, options };
|
|
41
806
|
};
|
|
807
|
+
function getSelectedElementContainer() {
|
|
808
|
+
const selectedElements = getSelectedElements();
|
|
809
|
+
if (selectedElements.length !== 1) {
|
|
810
|
+
return void 0;
|
|
811
|
+
}
|
|
812
|
+
return getContainer(selectedElements[0].id);
|
|
813
|
+
}
|
|
42
814
|
|
|
43
|
-
// src/
|
|
44
|
-
import {
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
815
|
+
// src/components/create-component-form/utils/replace-element-with-component.ts
|
|
816
|
+
import { replaceElement } from "@elementor/editor-elements";
|
|
817
|
+
var replaceElementWithComponent = (element, component) => {
|
|
818
|
+
replaceElement({
|
|
819
|
+
currentElement: element,
|
|
820
|
+
newElement: createComponentModel(component),
|
|
821
|
+
withHistory: false
|
|
50
822
|
});
|
|
51
823
|
};
|
|
824
|
+
var createComponentModel = (component) => {
|
|
825
|
+
return {
|
|
826
|
+
elType: "widget",
|
|
827
|
+
widgetType: "e-component",
|
|
828
|
+
settings: {
|
|
829
|
+
component_instance: {
|
|
830
|
+
$$type: "component-instance",
|
|
831
|
+
value: {
|
|
832
|
+
component_id: component.id ?? component.uid
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
},
|
|
836
|
+
editor_settings: {
|
|
837
|
+
title: component.name,
|
|
838
|
+
component_uid: component.uid
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
// src/components/components-tab/components-item.tsx
|
|
844
|
+
var ComponentItem = ({ component }) => {
|
|
845
|
+
const componentModel = createComponentModel(component);
|
|
846
|
+
const popupState = usePopupState({
|
|
847
|
+
variant: "popover",
|
|
848
|
+
disableAutoFocus: true
|
|
849
|
+
});
|
|
850
|
+
const handleClick = () => {
|
|
851
|
+
addComponentToPage(componentModel);
|
|
852
|
+
};
|
|
853
|
+
const handleDragEnd = () => {
|
|
854
|
+
loadComponentsAssets([componentModel]);
|
|
855
|
+
endDragElementFromPanel();
|
|
856
|
+
};
|
|
857
|
+
const handleArchiveClick = () => {
|
|
858
|
+
popupState.close();
|
|
859
|
+
if (!component.id) {
|
|
860
|
+
throw new Error("Component ID is required");
|
|
861
|
+
}
|
|
862
|
+
archiveComponent(component.id);
|
|
863
|
+
};
|
|
864
|
+
return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(
|
|
865
|
+
ListItemButton,
|
|
866
|
+
{
|
|
867
|
+
draggable: true,
|
|
868
|
+
onDragStart: () => startDragElementFromPanel(componentModel),
|
|
869
|
+
onDragEnd: handleDragEnd,
|
|
870
|
+
shape: "rounded",
|
|
871
|
+
sx: { border: "solid 1px", borderColor: "divider", py: 0.5, px: 1 }
|
|
872
|
+
},
|
|
873
|
+
/* @__PURE__ */ React5.createElement(Box4, { sx: { display: "flex", width: "100%", alignItems: "center", gap: 1 }, onClick: handleClick }, /* @__PURE__ */ React5.createElement(ListItemIcon, { size: "tiny" }, /* @__PURE__ */ React5.createElement(ComponentsIcon2, { fontSize: "tiny" })), /* @__PURE__ */ React5.createElement(
|
|
874
|
+
ListItemText,
|
|
875
|
+
{
|
|
876
|
+
primary: /* @__PURE__ */ React5.createElement(Typography2, { variant: "caption", sx: { color: "text.primary" } }, component.name)
|
|
877
|
+
}
|
|
878
|
+
)),
|
|
879
|
+
/* @__PURE__ */ React5.createElement(IconButton2, { size: "tiny", ...bindTrigger(popupState), "aria-label": "More actions" }, /* @__PURE__ */ React5.createElement(DotsVerticalIcon, { fontSize: "tiny" }))
|
|
880
|
+
), /* @__PURE__ */ React5.createElement(
|
|
881
|
+
Menu,
|
|
882
|
+
{
|
|
883
|
+
...bindMenu(popupState),
|
|
884
|
+
anchorOrigin: {
|
|
885
|
+
vertical: "bottom",
|
|
886
|
+
horizontal: "right"
|
|
887
|
+
},
|
|
888
|
+
transformOrigin: {
|
|
889
|
+
vertical: "top",
|
|
890
|
+
horizontal: "right"
|
|
891
|
+
}
|
|
892
|
+
},
|
|
893
|
+
/* @__PURE__ */ React5.createElement(MenuListItem, { sx: { minWidth: "160px" }, onClick: handleArchiveClick }, __5("Archive", "elementor"))
|
|
894
|
+
));
|
|
895
|
+
};
|
|
896
|
+
var addComponentToPage = (model) => {
|
|
897
|
+
const { container, options } = getContainerForNewElement();
|
|
898
|
+
if (!container) {
|
|
899
|
+
throw new Error(`Can't find container to drop new component instance at`);
|
|
900
|
+
}
|
|
901
|
+
loadComponentsAssets([model]);
|
|
902
|
+
dropElement({
|
|
903
|
+
containerId: container.id,
|
|
904
|
+
model,
|
|
905
|
+
options: { ...options, useHistory: false, scrollIntoView: true }
|
|
906
|
+
});
|
|
907
|
+
};
|
|
908
|
+
|
|
909
|
+
// src/components/components-tab/loading-components.tsx
|
|
910
|
+
import * as React6 from "react";
|
|
911
|
+
import { Box as Box5, ListItemButton as ListItemButton2, Skeleton, Stack as Stack3 } from "@elementor/ui";
|
|
912
|
+
var ROWS_COUNT = 6;
|
|
913
|
+
var rows = Array.from({ length: ROWS_COUNT }, (_, index) => index);
|
|
914
|
+
var LoadingComponents = () => {
|
|
915
|
+
return /* @__PURE__ */ React6.createElement(
|
|
916
|
+
Stack3,
|
|
917
|
+
{
|
|
918
|
+
"aria-label": "Loading components",
|
|
919
|
+
gap: 1,
|
|
920
|
+
sx: {
|
|
921
|
+
pointerEvents: "none",
|
|
922
|
+
position: "relative",
|
|
923
|
+
maxHeight: "300px",
|
|
924
|
+
overflow: "hidden",
|
|
925
|
+
"&:after": {
|
|
926
|
+
position: "absolute",
|
|
927
|
+
top: 0,
|
|
928
|
+
content: '""',
|
|
929
|
+
left: 0,
|
|
930
|
+
width: "100%",
|
|
931
|
+
height: "300px",
|
|
932
|
+
background: "linear-gradient(to top, white, transparent)",
|
|
933
|
+
pointerEvents: "none"
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
},
|
|
937
|
+
rows.map((row) => /* @__PURE__ */ React6.createElement(
|
|
938
|
+
ListItemButton2,
|
|
939
|
+
{
|
|
940
|
+
key: row,
|
|
941
|
+
sx: { border: "solid 1px", borderColor: "divider", py: 0.5, px: 1 },
|
|
942
|
+
shape: "rounded"
|
|
943
|
+
},
|
|
944
|
+
/* @__PURE__ */ React6.createElement(Box5, { display: "flex", gap: 1, width: "100%" }, /* @__PURE__ */ React6.createElement(Skeleton, { variant: "text", width: "24px", height: "36px" }), /* @__PURE__ */ React6.createElement(Skeleton, { variant: "text", width: "100%", height: "36px" }))
|
|
945
|
+
))
|
|
946
|
+
);
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
// src/components/components-tab/components-list.tsx
|
|
950
|
+
function ComponentsList() {
|
|
951
|
+
const { components, isLoading, searchValue } = useFilteredComponents();
|
|
952
|
+
if (isLoading) {
|
|
953
|
+
return /* @__PURE__ */ React7.createElement(LoadingComponents, null);
|
|
954
|
+
}
|
|
955
|
+
const isEmpty = !components || components.length === 0;
|
|
956
|
+
if (isEmpty) {
|
|
957
|
+
if (searchValue.length > 0) {
|
|
958
|
+
return /* @__PURE__ */ React7.createElement(EmptySearchResult, null);
|
|
959
|
+
}
|
|
960
|
+
return /* @__PURE__ */ React7.createElement(EmptyState, null);
|
|
961
|
+
}
|
|
962
|
+
return /* @__PURE__ */ React7.createElement(List, { sx: { display: "flex", flexDirection: "column", gap: 1, px: 2 } }, components.map((component) => /* @__PURE__ */ React7.createElement(ComponentItem, { key: component.uid, component })));
|
|
963
|
+
}
|
|
964
|
+
var EmptyState = () => {
|
|
965
|
+
return /* @__PURE__ */ React7.createElement(
|
|
966
|
+
Stack4,
|
|
967
|
+
{
|
|
968
|
+
alignItems: "center",
|
|
969
|
+
justifyContent: "center",
|
|
970
|
+
height: "100%",
|
|
971
|
+
sx: { px: 2.5, pt: 10 },
|
|
972
|
+
gap: 1.75,
|
|
973
|
+
overflow: "hidden"
|
|
974
|
+
},
|
|
975
|
+
/* @__PURE__ */ React7.createElement(Icon, { fontSize: "large" }, /* @__PURE__ */ React7.createElement(EyeIcon, { fontSize: "large" })),
|
|
976
|
+
/* @__PURE__ */ React7.createElement(Typography3, { align: "center", variant: "subtitle2", color: "text.secondary", fontWeight: "bold" }, __6("Text that explains that there are no Components yet.", "elementor")),
|
|
977
|
+
/* @__PURE__ */ React7.createElement(Typography3, { variant: "caption", align: "center", color: "text.secondary" }, __6(
|
|
978
|
+
"Once you have Components, this is where you can manage them\u2014rearrange, duplicate, rename and delete irrelevant classes.",
|
|
979
|
+
"elementor"
|
|
980
|
+
)),
|
|
981
|
+
/* @__PURE__ */ React7.createElement(Divider2, { sx: { width: "100%" }, color: "text.secondary" }),
|
|
982
|
+
/* @__PURE__ */ React7.createElement(Typography3, { align: "left", variant: "caption", color: "text.secondary" }, __6("To create a component, first design it, then choose one of three options:", "elementor")),
|
|
983
|
+
/* @__PURE__ */ React7.createElement(
|
|
984
|
+
Typography3,
|
|
985
|
+
{
|
|
986
|
+
align: "left",
|
|
987
|
+
variant: "caption",
|
|
988
|
+
color: "text.secondary",
|
|
989
|
+
sx: { display: "flex", flexDirection: "column" }
|
|
990
|
+
},
|
|
991
|
+
/* @__PURE__ */ React7.createElement("span", null, __6("1. Right-click and select Create Component", "elementor")),
|
|
992
|
+
/* @__PURE__ */ React7.createElement("span", null, __6("2. Use the component icon in the Structure panel", "elementor")),
|
|
993
|
+
/* @__PURE__ */ React7.createElement("span", null, __6("3. Use the component icon in the Edit panel header", "elementor"))
|
|
994
|
+
)
|
|
995
|
+
);
|
|
996
|
+
};
|
|
997
|
+
var EmptySearchResult = () => {
|
|
998
|
+
const { searchValue, clearSearch } = useSearch();
|
|
999
|
+
return /* @__PURE__ */ React7.createElement(
|
|
1000
|
+
Stack4,
|
|
1001
|
+
{
|
|
1002
|
+
color: "text.secondary",
|
|
1003
|
+
pt: 5,
|
|
1004
|
+
alignItems: "center",
|
|
1005
|
+
gap: 1,
|
|
1006
|
+
overflow: "hidden",
|
|
1007
|
+
justifySelf: "center"
|
|
1008
|
+
},
|
|
1009
|
+
/* @__PURE__ */ React7.createElement(ComponentsIcon3, null),
|
|
1010
|
+
/* @__PURE__ */ React7.createElement(
|
|
1011
|
+
Box6,
|
|
1012
|
+
{
|
|
1013
|
+
sx: {
|
|
1014
|
+
width: "100%"
|
|
1015
|
+
}
|
|
1016
|
+
},
|
|
1017
|
+
/* @__PURE__ */ React7.createElement(Typography3, { align: "center", variant: "subtitle2", color: "inherit" }, __6("Sorry, nothing matched", "elementor")),
|
|
1018
|
+
searchValue && /* @__PURE__ */ React7.createElement(
|
|
1019
|
+
Typography3,
|
|
1020
|
+
{
|
|
1021
|
+
variant: "subtitle2",
|
|
1022
|
+
color: "inherit",
|
|
1023
|
+
sx: {
|
|
1024
|
+
display: "flex",
|
|
1025
|
+
width: "100%",
|
|
1026
|
+
justifyContent: "center"
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
/* @__PURE__ */ React7.createElement("span", null, "\u201C"),
|
|
1030
|
+
/* @__PURE__ */ React7.createElement(
|
|
1031
|
+
"span",
|
|
1032
|
+
{
|
|
1033
|
+
style: {
|
|
1034
|
+
maxWidth: "80%",
|
|
1035
|
+
overflow: "hidden",
|
|
1036
|
+
textOverflow: "ellipsis"
|
|
1037
|
+
}
|
|
1038
|
+
},
|
|
1039
|
+
searchValue
|
|
1040
|
+
),
|
|
1041
|
+
/* @__PURE__ */ React7.createElement("span", null, "\u201D.")
|
|
1042
|
+
)
|
|
1043
|
+
),
|
|
1044
|
+
/* @__PURE__ */ React7.createElement(Typography3, { align: "center", variant: "caption", color: "inherit" }, __6("Try something else.", "elementor")),
|
|
1045
|
+
/* @__PURE__ */ React7.createElement(Typography3, { align: "center", variant: "caption", color: "inherit" }, /* @__PURE__ */ React7.createElement(Link, { color: "secondary", variant: "caption", component: "button", onClick: clearSearch }, __6("Clear & try again", "elementor")))
|
|
1046
|
+
);
|
|
1047
|
+
};
|
|
1048
|
+
var useFilteredComponents = () => {
|
|
1049
|
+
const { components, isLoading } = useComponents();
|
|
1050
|
+
const { searchValue } = useSearch();
|
|
1051
|
+
return {
|
|
1052
|
+
components: components.filter(
|
|
1053
|
+
(component) => component.name.toLowerCase().includes(searchValue.toLowerCase())
|
|
1054
|
+
),
|
|
1055
|
+
isLoading,
|
|
1056
|
+
searchValue
|
|
1057
|
+
};
|
|
1058
|
+
};
|
|
1059
|
+
|
|
1060
|
+
// src/components/components-tab/components.tsx
|
|
1061
|
+
var Components = () => {
|
|
1062
|
+
return /* @__PURE__ */ React8.createElement(ThemeProvider, null, /* @__PURE__ */ React8.createElement(SearchProvider, { localStorageKey: "elementor-components-search" }, /* @__PURE__ */ React8.createElement(ComponentSearch, null), /* @__PURE__ */ React8.createElement(ComponentsList, null)));
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
// src/components/consts.ts
|
|
1066
|
+
var COMPONENT_DOCUMENT_TYPE = "elementor_component";
|
|
1067
|
+
|
|
1068
|
+
// src/components/create-component-form/create-component-form.tsx
|
|
1069
|
+
import * as React9 from "react";
|
|
1070
|
+
import { useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
1071
|
+
import { getElementLabel } from "@elementor/editor-elements";
|
|
1072
|
+
import { Form as FormElement, ThemeProvider as ThemeProvider2 } from "@elementor/editor-ui";
|
|
1073
|
+
import { StarIcon } from "@elementor/icons";
|
|
1074
|
+
import { Alert, Button, FormLabel, Grid, Popover, Snackbar, Stack as Stack5, TextField as TextField2, Typography as Typography4 } from "@elementor/ui";
|
|
1075
|
+
import { __ as __8 } from "@wordpress/i18n";
|
|
1076
|
+
|
|
1077
|
+
// src/store/actions/create-unpublished-component.ts
|
|
1078
|
+
import { __privateRunCommand as runCommand3 } from "@elementor/editor-v1-adapters";
|
|
1079
|
+
import { __dispatch as dispatch3 } from "@elementor/store";
|
|
1080
|
+
import { generateUniqueId } from "@elementor/utils";
|
|
1081
|
+
function createUnpublishedComponent(name, element, eventData) {
|
|
1082
|
+
const uid = generateUniqueId("component");
|
|
1083
|
+
const componentBase = { uid, name };
|
|
1084
|
+
dispatch3(
|
|
1085
|
+
slice.actions.addUnpublished({
|
|
1086
|
+
...componentBase,
|
|
1087
|
+
elements: [element]
|
|
1088
|
+
})
|
|
1089
|
+
);
|
|
1090
|
+
dispatch3(slice.actions.addCreatedThisSession(uid));
|
|
1091
|
+
replaceElementWithComponent(element, componentBase);
|
|
1092
|
+
trackComponentEvent({
|
|
1093
|
+
action: "created",
|
|
1094
|
+
component_uid: uid,
|
|
1095
|
+
component_name: name,
|
|
1096
|
+
...eventData
|
|
1097
|
+
});
|
|
1098
|
+
runCommand3("document/save/auto");
|
|
1099
|
+
return uid;
|
|
1100
|
+
}
|
|
52
1101
|
|
|
53
1102
|
// src/components/create-component-form/hooks/use-form.ts
|
|
54
1103
|
import { useMemo, useState } from "react";
|
|
@@ -101,16 +1150,16 @@ var validateForm = (values, schema) => {
|
|
|
101
1150
|
|
|
102
1151
|
// src/components/create-component-form/utils/component-form-schema.ts
|
|
103
1152
|
import { z } from "@elementor/schema";
|
|
104
|
-
import { __ } from "@wordpress/i18n";
|
|
1153
|
+
import { __ as __7 } from "@wordpress/i18n";
|
|
105
1154
|
var MIN_NAME_LENGTH = 2;
|
|
106
1155
|
var MAX_NAME_LENGTH = 50;
|
|
107
1156
|
var createBaseComponentSchema = (existingNames) => {
|
|
108
1157
|
return z.object({
|
|
109
1158
|
componentName: z.string().trim().max(
|
|
110
1159
|
MAX_NAME_LENGTH,
|
|
111
|
-
|
|
1160
|
+
__7("Component name is too long. Please keep it under 50 characters.", "elementor")
|
|
112
1161
|
).refine((value) => !existingNames.includes(value), {
|
|
113
|
-
message:
|
|
1162
|
+
message: __7("Component name already exists", "elementor")
|
|
114
1163
|
})
|
|
115
1164
|
});
|
|
116
1165
|
};
|
|
@@ -118,103 +1167,114 @@ var createSubmitComponentSchema = (existingNames) => {
|
|
|
118
1167
|
const baseSchema = createBaseComponentSchema(existingNames);
|
|
119
1168
|
return baseSchema.extend({
|
|
120
1169
|
componentName: baseSchema.shape.componentName.refine((value) => value.length > 0, {
|
|
121
|
-
message:
|
|
1170
|
+
message: __7("Component name is required.", "elementor")
|
|
122
1171
|
}).refine((value) => value.length >= MIN_NAME_LENGTH, {
|
|
123
|
-
message:
|
|
1172
|
+
message: __7("Component name is too short. Please enter at least 2 characters.", "elementor")
|
|
124
1173
|
})
|
|
125
1174
|
});
|
|
126
1175
|
};
|
|
127
1176
|
|
|
128
|
-
// src/components/create-component-form/utils/
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
withHistory: false
|
|
142
|
-
});
|
|
1177
|
+
// src/components/create-component-form/utils/get-component-event-data.ts
|
|
1178
|
+
var getComponentEventData = (containerElement, options) => {
|
|
1179
|
+
const { elementsCount, componentsCount } = countNestedElements(containerElement);
|
|
1180
|
+
return {
|
|
1181
|
+
nested_elements_count: elementsCount,
|
|
1182
|
+
nested_components_count: componentsCount,
|
|
1183
|
+
top_element_type: containerElement.elType,
|
|
1184
|
+
location: options?.location,
|
|
1185
|
+
secondary_location: options?.secondaryLocation,
|
|
1186
|
+
trigger: options?.trigger
|
|
1187
|
+
};
|
|
143
1188
|
};
|
|
1189
|
+
function countNestedElements(container) {
|
|
1190
|
+
if (!container.elements || container.elements.length === 0) {
|
|
1191
|
+
return { elementsCount: 0, componentsCount: 0 };
|
|
1192
|
+
}
|
|
1193
|
+
let elementsCount = container.elements.length;
|
|
1194
|
+
let componentsCount = 0;
|
|
1195
|
+
for (const element of container.elements) {
|
|
1196
|
+
if (element.widgetType === "e-component") {
|
|
1197
|
+
componentsCount++;
|
|
1198
|
+
}
|
|
1199
|
+
const { elementsCount: nestedElementsCount, componentsCount: nestedComponentsCount } = countNestedElements(element);
|
|
1200
|
+
elementsCount += nestedElementsCount;
|
|
1201
|
+
componentsCount += nestedComponentsCount;
|
|
1202
|
+
}
|
|
1203
|
+
return { elementsCount, componentsCount };
|
|
1204
|
+
}
|
|
144
1205
|
|
|
145
1206
|
// src/components/create-component-form/create-component-form.tsx
|
|
146
1207
|
function CreateComponentForm() {
|
|
147
1208
|
const [element, setElement] = useState2(null);
|
|
148
1209
|
const [anchorPosition, setAnchorPosition] = useState2();
|
|
149
1210
|
const [resultNotification, setResultNotification] = useState2(null);
|
|
150
|
-
const
|
|
151
|
-
|
|
1211
|
+
const eventData = useRef2(null);
|
|
1212
|
+
useEffect2(() => {
|
|
152
1213
|
const OPEN_SAVE_AS_COMPONENT_FORM_EVENT = "elementor/editor/open-save-as-component-form";
|
|
153
1214
|
const openPopup = (event) => {
|
|
154
1215
|
setElement({ element: event.detail.element, elementLabel: getElementLabel(event.detail.element.id) });
|
|
155
1216
|
setAnchorPosition(event.detail.anchorPosition);
|
|
1217
|
+
eventData.current = getComponentEventData(event.detail.element, event.detail.options);
|
|
1218
|
+
trackComponentEvent({
|
|
1219
|
+
action: "createClicked",
|
|
1220
|
+
...eventData.current
|
|
1221
|
+
});
|
|
156
1222
|
};
|
|
157
1223
|
window.addEventListener(OPEN_SAVE_AS_COMPONENT_FORM_EVENT, openPopup);
|
|
158
1224
|
return () => {
|
|
159
1225
|
window.removeEventListener(OPEN_SAVE_AS_COMPONENT_FORM_EVENT, openPopup);
|
|
160
1226
|
};
|
|
161
1227
|
}, []);
|
|
162
|
-
const handleSave =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
createComponent(
|
|
167
|
-
{
|
|
168
|
-
name: values.componentName,
|
|
169
|
-
content: [element.element.model.toJSON({ remove: ["default"] })]
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
onSuccess: (result) => {
|
|
173
|
-
if (!element) {
|
|
174
|
-
throw new Error(`Can't replace element with component: element not found`);
|
|
175
|
-
}
|
|
176
|
-
replaceElementWithComponent(element.element, result.component_id);
|
|
177
|
-
setResultNotification({
|
|
178
|
-
show: true,
|
|
179
|
-
// Translators: %1$s: Component name, %2$s: Component ID
|
|
180
|
-
message: __2("Component saved successfully as: %1$s (ID: %2$s)", "elementor").replace("%1$s", values.componentName).replace("%2$s", result.component_id.toString()),
|
|
181
|
-
type: "success"
|
|
182
|
-
});
|
|
183
|
-
resetAndClosePopup();
|
|
184
|
-
},
|
|
185
|
-
onError: () => {
|
|
186
|
-
const errorMessage = __2("Failed to save component. Please try again.", "elementor");
|
|
187
|
-
setResultNotification({
|
|
188
|
-
show: true,
|
|
189
|
-
message: errorMessage,
|
|
190
|
-
type: "error"
|
|
191
|
-
});
|
|
192
|
-
}
|
|
1228
|
+
const handleSave = (values) => {
|
|
1229
|
+
try {
|
|
1230
|
+
if (!element) {
|
|
1231
|
+
throw new Error(`Can't save element as component: element not found`);
|
|
193
1232
|
}
|
|
194
|
-
|
|
1233
|
+
const uid = createUnpublishedComponent(values.componentName, element.element, eventData.current);
|
|
1234
|
+
setResultNotification({
|
|
1235
|
+
show: true,
|
|
1236
|
+
// Translators: %1$s: Component name, %2$s: Component UID
|
|
1237
|
+
message: __8("Component saved successfully as: %1$s (UID: %2$s)", "elementor").replace("%1$s", values.componentName).replace("%2$s", uid),
|
|
1238
|
+
type: "success"
|
|
1239
|
+
});
|
|
1240
|
+
resetAndClosePopup();
|
|
1241
|
+
} catch {
|
|
1242
|
+
const errorMessage = __8("Failed to save component. Please try again.", "elementor");
|
|
1243
|
+
setResultNotification({
|
|
1244
|
+
show: true,
|
|
1245
|
+
message: errorMessage,
|
|
1246
|
+
type: "error"
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
195
1249
|
};
|
|
196
1250
|
const resetAndClosePopup = () => {
|
|
197
1251
|
setElement(null);
|
|
198
1252
|
setAnchorPosition(void 0);
|
|
199
1253
|
};
|
|
200
|
-
|
|
1254
|
+
const cancelSave = () => {
|
|
1255
|
+
resetAndClosePopup();
|
|
1256
|
+
trackComponentEvent({
|
|
1257
|
+
action: "createCancelled",
|
|
1258
|
+
...eventData.current
|
|
1259
|
+
});
|
|
1260
|
+
};
|
|
1261
|
+
return /* @__PURE__ */ React9.createElement(ThemeProvider2, null, /* @__PURE__ */ React9.createElement(
|
|
201
1262
|
Popover,
|
|
202
1263
|
{
|
|
203
1264
|
open: element !== null,
|
|
204
|
-
onClose:
|
|
1265
|
+
onClose: cancelSave,
|
|
205
1266
|
anchorReference: "anchorPosition",
|
|
206
1267
|
anchorPosition
|
|
207
1268
|
},
|
|
208
|
-
element !== null && /* @__PURE__ */
|
|
1269
|
+
element !== null && /* @__PURE__ */ React9.createElement(
|
|
209
1270
|
Form,
|
|
210
1271
|
{
|
|
211
1272
|
initialValues: { componentName: element.elementLabel },
|
|
212
1273
|
handleSave,
|
|
213
|
-
|
|
214
|
-
closePopup: resetAndClosePopup
|
|
1274
|
+
closePopup: cancelSave
|
|
215
1275
|
}
|
|
216
1276
|
)
|
|
217
|
-
), /* @__PURE__ */
|
|
1277
|
+
), /* @__PURE__ */ React9.createElement(Snackbar, { open: resultNotification?.show, onClose: () => setResultNotification(null) }, /* @__PURE__ */ React9.createElement(
|
|
218
1278
|
Alert,
|
|
219
1279
|
{
|
|
220
1280
|
onClose: () => setResultNotification(null),
|
|
@@ -228,11 +1288,10 @@ var FONT_SIZE = "tiny";
|
|
|
228
1288
|
var Form = ({
|
|
229
1289
|
initialValues,
|
|
230
1290
|
handleSave,
|
|
231
|
-
isSubmitting,
|
|
232
1291
|
closePopup
|
|
233
1292
|
}) => {
|
|
234
1293
|
const { values, errors, isValid, handleChange, validateForm: validateForm2 } = useForm(initialValues);
|
|
235
|
-
const {
|
|
1294
|
+
const { components } = useComponents();
|
|
236
1295
|
const existingComponentNames = useMemo2(() => {
|
|
237
1296
|
return components?.map((component) => component.name) ?? [];
|
|
238
1297
|
}, [components]);
|
|
@@ -250,8 +1309,15 @@ var Form = ({
|
|
|
250
1309
|
handleSave(parsedValues);
|
|
251
1310
|
}
|
|
252
1311
|
};
|
|
253
|
-
|
|
254
|
-
|
|
1312
|
+
const texts = {
|
|
1313
|
+
heading: __8("Save as a component", "elementor"),
|
|
1314
|
+
name: __8("Name", "elementor"),
|
|
1315
|
+
cancel: __8("Cancel", "elementor"),
|
|
1316
|
+
create: __8("Create", "elementor")
|
|
1317
|
+
};
|
|
1318
|
+
const nameInputId = "component-name";
|
|
1319
|
+
return /* @__PURE__ */ React9.createElement(FormElement, { onSubmit: handleSubmit }, /* @__PURE__ */ React9.createElement(Stack5, { alignItems: "start", width: "268px" }, /* @__PURE__ */ React9.createElement(
|
|
1320
|
+
Stack5,
|
|
255
1321
|
{
|
|
256
1322
|
direction: "row",
|
|
257
1323
|
alignItems: "center",
|
|
@@ -259,12 +1325,12 @@ var Form = ({
|
|
|
259
1325
|
px: 1.5,
|
|
260
1326
|
sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%" }
|
|
261
1327
|
},
|
|
262
|
-
/* @__PURE__ */
|
|
263
|
-
/* @__PURE__ */
|
|
264
|
-
), /* @__PURE__ */
|
|
265
|
-
|
|
1328
|
+
/* @__PURE__ */ React9.createElement(StarIcon, { fontSize: FONT_SIZE }),
|
|
1329
|
+
/* @__PURE__ */ React9.createElement(Typography4, { variant: "caption", sx: { color: "text.primary", fontWeight: "500", lineHeight: 1 } }, texts.heading)
|
|
1330
|
+
), /* @__PURE__ */ React9.createElement(Grid, { container: true, gap: 0.75, alignItems: "start", p: 1.5 }, /* @__PURE__ */ React9.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React9.createElement(FormLabel, { htmlFor: nameInputId, size: "tiny" }, texts.name)), /* @__PURE__ */ React9.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React9.createElement(
|
|
1331
|
+
TextField2,
|
|
266
1332
|
{
|
|
267
|
-
id:
|
|
1333
|
+
id: nameInputId,
|
|
268
1334
|
size: FONT_SIZE,
|
|
269
1335
|
fullWidth: true,
|
|
270
1336
|
value: values.componentName,
|
|
@@ -273,30 +1339,1089 @@ var Form = ({
|
|
|
273
1339
|
error: Boolean(errors.componentName),
|
|
274
1340
|
helperText: errors.componentName
|
|
275
1341
|
}
|
|
276
|
-
))), /* @__PURE__ */
|
|
277
|
-
|
|
1342
|
+
))), /* @__PURE__ */ React9.createElement(Stack5, { direction: "row", justifyContent: "flex-end", alignSelf: "end", py: 1, px: 1.5 }, /* @__PURE__ */ React9.createElement(Button, { onClick: closePopup, color: "secondary", variant: "text", size: "small" }, texts.cancel), /* @__PURE__ */ React9.createElement(Button, { type: "submit", disabled: !isValid, variant: "contained", color: "primary", size: "small" }, texts.create))));
|
|
1343
|
+
};
|
|
1344
|
+
|
|
1345
|
+
// src/components/edit-component/edit-component.tsx
|
|
1346
|
+
import * as React11 from "react";
|
|
1347
|
+
import { useEffect as useEffect5 } from "react";
|
|
1348
|
+
import { getV1DocumentsManager as getV1DocumentsManager4 } from "@elementor/editor-documents";
|
|
1349
|
+
import { __privateListenTo as listenTo, commandEndEvent as commandEndEvent2 } from "@elementor/editor-v1-adapters";
|
|
1350
|
+
import { __useSelector as useSelector5 } from "@elementor/store";
|
|
1351
|
+
|
|
1352
|
+
// src/store/actions/update-current-component.ts
|
|
1353
|
+
import { setDocumentModifiedStatus as setDocumentModifiedStatus3 } from "@elementor/editor-documents";
|
|
1354
|
+
import { __getStore as getStore2 } from "@elementor/store";
|
|
1355
|
+
function updateCurrentComponent({
|
|
1356
|
+
path,
|
|
1357
|
+
currentComponentId
|
|
1358
|
+
}) {
|
|
1359
|
+
const dispatch9 = getStore2()?.dispatch;
|
|
1360
|
+
if (!dispatch9) {
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
dispatch9(slice.actions.setPath(path));
|
|
1364
|
+
dispatch9(slice.actions.setCurrentComponentId(currentComponentId));
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
// src/components/edit-component/component-modal.tsx
|
|
1368
|
+
import * as React10 from "react";
|
|
1369
|
+
import { useEffect as useEffect4 } from "react";
|
|
1370
|
+
import { createPortal } from "react-dom";
|
|
1371
|
+
import { __ as __9 } from "@wordpress/i18n";
|
|
1372
|
+
|
|
1373
|
+
// src/hooks/use-canvas-document.ts
|
|
1374
|
+
import { getCanvasIframeDocument } from "@elementor/editor-canvas";
|
|
1375
|
+
import { __privateUseListenTo as useListenTo, commandEndEvent } from "@elementor/editor-v1-adapters";
|
|
1376
|
+
function useCanvasDocument() {
|
|
1377
|
+
return useListenTo(commandEndEvent("editor/documents/attach-preview"), () => getCanvasIframeDocument());
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
// src/hooks/use-element-rect.ts
|
|
1381
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
1382
|
+
import { throttle } from "@elementor/utils";
|
|
1383
|
+
function useElementRect(element) {
|
|
1384
|
+
const [rect, setRect] = useState3(new DOMRect(0, 0, 0, 0));
|
|
1385
|
+
const onChange = throttle(
|
|
1386
|
+
() => {
|
|
1387
|
+
setRect(element?.getBoundingClientRect() ?? new DOMRect(0, 0, 0, 0));
|
|
1388
|
+
},
|
|
1389
|
+
20,
|
|
1390
|
+
true
|
|
1391
|
+
);
|
|
1392
|
+
useScrollListener({ element, onChange });
|
|
1393
|
+
useResizeListener({ element, onChange });
|
|
1394
|
+
useMutationsListener({ element, onChange });
|
|
1395
|
+
useEffect3(
|
|
1396
|
+
() => () => {
|
|
1397
|
+
onChange.cancel();
|
|
1398
|
+
},
|
|
1399
|
+
[onChange]
|
|
1400
|
+
);
|
|
1401
|
+
return rect;
|
|
1402
|
+
}
|
|
1403
|
+
function useScrollListener({ element, onChange }) {
|
|
1404
|
+
useEffect3(() => {
|
|
1405
|
+
if (!element) {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
const win = element.ownerDocument?.defaultView;
|
|
1409
|
+
win?.addEventListener("scroll", onChange, { passive: true });
|
|
1410
|
+
return () => {
|
|
1411
|
+
win?.removeEventListener("scroll", onChange);
|
|
1412
|
+
};
|
|
1413
|
+
}, [element, onChange]);
|
|
1414
|
+
}
|
|
1415
|
+
function useResizeListener({ element, onChange }) {
|
|
1416
|
+
useEffect3(() => {
|
|
1417
|
+
if (!element) {
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1420
|
+
const resizeObserver = new ResizeObserver(onChange);
|
|
1421
|
+
resizeObserver.observe(element);
|
|
1422
|
+
const win = element.ownerDocument?.defaultView;
|
|
1423
|
+
win?.addEventListener("resize", onChange, { passive: true });
|
|
1424
|
+
return () => {
|
|
1425
|
+
resizeObserver.disconnect();
|
|
1426
|
+
win?.removeEventListener("resize", onChange);
|
|
1427
|
+
};
|
|
1428
|
+
}, [element, onChange]);
|
|
1429
|
+
}
|
|
1430
|
+
function useMutationsListener({ element, onChange }) {
|
|
1431
|
+
useEffect3(() => {
|
|
1432
|
+
if (!element) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
const mutationObserver = new MutationObserver(onChange);
|
|
1436
|
+
mutationObserver.observe(element, { childList: true, subtree: true });
|
|
1437
|
+
return () => {
|
|
1438
|
+
mutationObserver.disconnect();
|
|
1439
|
+
};
|
|
1440
|
+
}, [element, onChange]);
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
// src/components/edit-component/component-modal.tsx
|
|
1444
|
+
function ComponentModal({ element, onClose }) {
|
|
1445
|
+
const canvasDocument = useCanvasDocument();
|
|
1446
|
+
useEffect4(() => {
|
|
1447
|
+
const handleEsc = (event) => {
|
|
1448
|
+
if (event.key === "Escape") {
|
|
1449
|
+
onClose();
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
|
+
canvasDocument?.body.addEventListener("keydown", handleEsc);
|
|
1453
|
+
return () => {
|
|
1454
|
+
canvasDocument?.body.removeEventListener("keydown", handleEsc);
|
|
1455
|
+
};
|
|
1456
|
+
}, [canvasDocument, onClose]);
|
|
1457
|
+
if (!canvasDocument?.body) {
|
|
1458
|
+
return null;
|
|
1459
|
+
}
|
|
1460
|
+
return createPortal(
|
|
1461
|
+
/* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(BlockEditPage, null), /* @__PURE__ */ React10.createElement(Backdrop, { canvas: canvasDocument, element, onClose })),
|
|
1462
|
+
canvasDocument.body
|
|
1463
|
+
);
|
|
1464
|
+
}
|
|
1465
|
+
function Backdrop({ canvas, element, onClose }) {
|
|
1466
|
+
const rect = useElementRect(element);
|
|
1467
|
+
const backdropStyle = {
|
|
1468
|
+
position: "fixed",
|
|
1469
|
+
top: 0,
|
|
1470
|
+
left: 0,
|
|
1471
|
+
width: "100vw",
|
|
1472
|
+
height: "100vh",
|
|
1473
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
1474
|
+
zIndex: 999,
|
|
1475
|
+
pointerEvents: "painted",
|
|
1476
|
+
cursor: "pointer",
|
|
1477
|
+
clipPath: getRoundedRectPath(rect, canvas.defaultView, 5)
|
|
1478
|
+
};
|
|
1479
|
+
const handleKeyDown = (event) => {
|
|
1480
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1481
|
+
event.preventDefault();
|
|
1482
|
+
onClose();
|
|
1483
|
+
}
|
|
1484
|
+
};
|
|
1485
|
+
return /* @__PURE__ */ React10.createElement(
|
|
1486
|
+
"div",
|
|
278
1487
|
{
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
1488
|
+
style: backdropStyle,
|
|
1489
|
+
onClick: onClose,
|
|
1490
|
+
onKeyDown: handleKeyDown,
|
|
1491
|
+
role: "button",
|
|
1492
|
+
tabIndex: 0,
|
|
1493
|
+
"aria-label": __9("Exit component editing mode", "elementor")
|
|
1494
|
+
}
|
|
1495
|
+
);
|
|
1496
|
+
}
|
|
1497
|
+
function getRoundedRectPath(rect, viewport, borderRadius) {
|
|
1498
|
+
const padding = borderRadius / 2;
|
|
1499
|
+
const { x: originalX, y: originalY, width: originalWidth, height: originalHeight } = rect;
|
|
1500
|
+
const x = originalX - padding;
|
|
1501
|
+
const y = originalY - padding;
|
|
1502
|
+
const width = originalWidth + 2 * padding;
|
|
1503
|
+
const height = originalHeight + 2 * padding;
|
|
1504
|
+
const radius = Math.min(borderRadius, width / 2, height / 2);
|
|
1505
|
+
const { innerWidth: vw, innerHeight: vh } = viewport;
|
|
1506
|
+
const path = `path(evenodd, 'M 0 0
|
|
1507
|
+
L ${vw} 0
|
|
1508
|
+
L ${vw} ${vh}
|
|
1509
|
+
L 0 ${vh}
|
|
1510
|
+
Z
|
|
1511
|
+
M ${x + radius} ${y}
|
|
1512
|
+
L ${x + width - radius} ${y}
|
|
1513
|
+
A ${radius} ${radius} 0 0 1 ${x + width} ${y + radius}
|
|
1514
|
+
L ${x + width} ${y + height - radius}
|
|
1515
|
+
A ${radius} ${radius} 0 0 1 ${x + width - radius} ${y + height}
|
|
1516
|
+
L ${x + radius} ${y + height}
|
|
1517
|
+
A ${radius} ${radius} 0 0 1 ${x} ${y + height - radius}
|
|
1518
|
+
L ${x} ${y + radius}
|
|
1519
|
+
A ${radius} ${radius} 0 0 1 ${x + radius} ${y}
|
|
1520
|
+
Z'
|
|
1521
|
+
)`;
|
|
1522
|
+
return path.replace(/\s{2,}/g, " ");
|
|
1523
|
+
}
|
|
1524
|
+
function BlockEditPage() {
|
|
1525
|
+
const blockV3DocumentHandlesStyles = `
|
|
1526
|
+
.elementor-editor-active {
|
|
1527
|
+
& .elementor-section-wrap.ui-sortable {
|
|
1528
|
+
display: contents;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
& *[data-editable-elementor-document]:not(.elementor-edit-mode):hover {
|
|
1532
|
+
& .elementor-document-handle:not(.elementor-document-save-back-handle) {
|
|
1533
|
+
display: none;
|
|
1534
|
+
|
|
1535
|
+
&::before,
|
|
1536
|
+
& .elementor-document-handle__inner {
|
|
1537
|
+
display: none;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
`;
|
|
1543
|
+
return /* @__PURE__ */ React10.createElement("style", { "data-e-style-id": "e-block-v3-document-handles-styles" }, blockV3DocumentHandlesStyles);
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
// src/components/edit-component/edit-component.tsx
|
|
1547
|
+
function EditComponent() {
|
|
1548
|
+
const currentComponentId = useSelector5(selectCurrentComponentId);
|
|
1549
|
+
useHandleDocumentSwitches();
|
|
1550
|
+
const onBack = useNavigateBack();
|
|
1551
|
+
const elementDom = getComponentDOMElement(currentComponentId ?? void 0);
|
|
1552
|
+
if (!elementDom) {
|
|
1553
|
+
return null;
|
|
1554
|
+
}
|
|
1555
|
+
return /* @__PURE__ */ React11.createElement(ComponentModal, { element: elementDom, onClose: onBack });
|
|
1556
|
+
}
|
|
1557
|
+
function useHandleDocumentSwitches() {
|
|
1558
|
+
const documentsManager = getV1DocumentsManager4();
|
|
1559
|
+
const currentComponentId = useSelector5(selectCurrentComponentId);
|
|
1560
|
+
const path = useSelector5(selectPath);
|
|
1561
|
+
useEffect5(() => {
|
|
1562
|
+
return listenTo(commandEndEvent2("editor/documents/attach-preview"), () => {
|
|
1563
|
+
const nextDocument = documentsManager.getCurrent();
|
|
1564
|
+
if (nextDocument.id === currentComponentId) {
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1567
|
+
if (currentComponentId) {
|
|
1568
|
+
apiClient.unlockComponent(currentComponentId);
|
|
1569
|
+
}
|
|
1570
|
+
const isComponent = nextDocument.config.type === COMPONENT_DOCUMENT_TYPE;
|
|
1571
|
+
if (!isComponent) {
|
|
1572
|
+
updateCurrentComponent({ path: [], currentComponentId: null });
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
updateCurrentComponent({
|
|
1576
|
+
path: getUpdatedComponentPath(path, nextDocument),
|
|
1577
|
+
currentComponentId: nextDocument.id
|
|
1578
|
+
});
|
|
1579
|
+
});
|
|
1580
|
+
}, [path, documentsManager, currentComponentId]);
|
|
1581
|
+
}
|
|
1582
|
+
function getUpdatedComponentPath(path, nextDocument) {
|
|
1583
|
+
const componentIndex = path.findIndex(({ componentId }) => componentId === nextDocument.id);
|
|
1584
|
+
if (componentIndex >= 0) {
|
|
1585
|
+
return path.slice(0, componentIndex + 1);
|
|
1586
|
+
}
|
|
1587
|
+
return [
|
|
1588
|
+
...path,
|
|
1589
|
+
{
|
|
1590
|
+
instanceId: nextDocument?.container.view?.el?.dataset.id,
|
|
1591
|
+
componentId: nextDocument.id
|
|
1592
|
+
}
|
|
1593
|
+
];
|
|
1594
|
+
}
|
|
1595
|
+
function getComponentDOMElement(id) {
|
|
1596
|
+
if (!id) {
|
|
1597
|
+
return null;
|
|
1598
|
+
}
|
|
1599
|
+
const documentsManager = getV1DocumentsManager4();
|
|
1600
|
+
const currentComponent = documentsManager.get(id);
|
|
1601
|
+
const widget = currentComponent?.container;
|
|
1602
|
+
const container = widget?.view?.el?.children?.[0] ?? null;
|
|
1603
|
+
const elementDom = container?.children[0];
|
|
1604
|
+
return elementDom ?? null;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
// src/components/in-edit-mode.tsx
|
|
1608
|
+
import * as React12 from "react";
|
|
1609
|
+
import { closeDialog, openDialog } from "@elementor/editor-ui";
|
|
1610
|
+
import { InfoCircleFilledIcon } from "@elementor/icons";
|
|
1611
|
+
import { Box as Box7, Button as Button2, DialogActions, DialogContent, DialogHeader, Icon as Icon2, Stack as Stack6, Typography as Typography5 } from "@elementor/ui";
|
|
1612
|
+
import { __ as __10 } from "@wordpress/i18n";
|
|
1613
|
+
var openEditModeDialog = (lockedBy) => {
|
|
1614
|
+
openDialog({
|
|
1615
|
+
component: /* @__PURE__ */ React12.createElement(EditModeDialog, { lockedBy })
|
|
1616
|
+
});
|
|
1617
|
+
};
|
|
1618
|
+
var EditModeDialog = ({ lockedBy }) => {
|
|
1619
|
+
const content = __10("%s is currently editing this document", "elementor").replace("%s", lockedBy);
|
|
1620
|
+
return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(DialogHeader, { logo: false }, /* @__PURE__ */ React12.createElement(Box7, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ React12.createElement(Icon2, { color: "secondary" }, /* @__PURE__ */ React12.createElement(InfoCircleFilledIcon, { fontSize: "medium" })), /* @__PURE__ */ React12.createElement(Typography5, { variant: "subtitle1" }, content))), /* @__PURE__ */ React12.createElement(DialogContent, null, /* @__PURE__ */ React12.createElement(Stack6, { spacing: 2, direction: "column" }, /* @__PURE__ */ React12.createElement(Typography5, { variant: "body2" }, __10(
|
|
1621
|
+
"You can wait for them to finish or reach out to coordinate your changes together.",
|
|
1622
|
+
"elementor"
|
|
1623
|
+
)), /* @__PURE__ */ React12.createElement(DialogActions, null, /* @__PURE__ */ React12.createElement(Button2, { color: "secondary", variant: "contained", onClick: closeDialog }, __10("Close", "elementor"))))));
|
|
1624
|
+
};
|
|
1625
|
+
|
|
1626
|
+
// src/components/overridable-props/overridable-prop-control.tsx
|
|
1627
|
+
import * as React13 from "react";
|
|
1628
|
+
import { ControlReplacementsProvider, PropKeyProvider, PropProvider, useBoundProp } from "@elementor/editor-controls";
|
|
1629
|
+
import { createTopLevelObjectType, useElement } from "@elementor/editor-editing-panel";
|
|
1630
|
+
import { __getState as getState6 } from "@elementor/store";
|
|
1631
|
+
|
|
1632
|
+
// src/prop-types/component-overridable-prop-type.ts
|
|
1633
|
+
import { createPropUtils } from "@elementor/editor-props";
|
|
1634
|
+
import { z as z2 } from "@elementor/schema";
|
|
1635
|
+
var componentOverridablePropTypeUtil = createPropUtils(
|
|
1636
|
+
"overridable",
|
|
1637
|
+
z2.object({
|
|
1638
|
+
override_key: z2.string(),
|
|
1639
|
+
origin_value: z2.object({
|
|
1640
|
+
$$type: z2.string(),
|
|
1641
|
+
value: z2.unknown()
|
|
1642
|
+
}).nullable()
|
|
1643
|
+
})
|
|
1644
|
+
);
|
|
1645
|
+
|
|
1646
|
+
// src/store/actions/update-overridable-prop-origin-value.ts
|
|
1647
|
+
import { __dispatch as dispatch4, __getState as getState5 } from "@elementor/store";
|
|
1648
|
+
function updateOverridablePropOriginValue(componentId, propValue) {
|
|
1649
|
+
const overridableProps = selectOverridableProps(getState5(), componentId);
|
|
1650
|
+
if (!overridableProps) {
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1653
|
+
const existingOverridableProp = overridableProps.props[propValue.override_key];
|
|
1654
|
+
if (!existingOverridableProp) {
|
|
1655
|
+
return;
|
|
1656
|
+
}
|
|
1657
|
+
const newOverridableProps = {
|
|
1658
|
+
...overridableProps,
|
|
1659
|
+
props: {
|
|
1660
|
+
...overridableProps.props,
|
|
1661
|
+
[existingOverridableProp.overrideKey]: {
|
|
1662
|
+
...existingOverridableProp,
|
|
1663
|
+
originValue: propValue.origin_value
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
dispatch4(
|
|
1668
|
+
slice.actions.setOverridableProps({
|
|
1669
|
+
componentId,
|
|
1670
|
+
overridableProps: newOverridableProps
|
|
1671
|
+
})
|
|
1672
|
+
);
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
// src/components/overridable-props/overridable-prop-control.tsx
|
|
1676
|
+
function OverridablePropControl({
|
|
1677
|
+
OriginalControl,
|
|
1678
|
+
...props
|
|
1679
|
+
}) {
|
|
1680
|
+
const { elementType } = useElement();
|
|
1681
|
+
const { value, bind, setValue, placeholder, ...propContext } = useBoundProp(componentOverridablePropTypeUtil);
|
|
1682
|
+
const componentId = selectCurrentComponentId(getState6());
|
|
1683
|
+
if (!componentId) {
|
|
1684
|
+
throw new Error("Component ID is required");
|
|
1685
|
+
}
|
|
1686
|
+
if (!value?.override_key) {
|
|
1687
|
+
throw new Error("Override key is required");
|
|
1688
|
+
}
|
|
1689
|
+
const setOverridableValue = (newValue) => {
|
|
1690
|
+
const propValue = {
|
|
1691
|
+
...value,
|
|
1692
|
+
origin_value: newValue[bind]
|
|
1693
|
+
};
|
|
1694
|
+
setValue(propValue);
|
|
1695
|
+
updateOverridablePropOriginValue(componentId, propValue);
|
|
1696
|
+
};
|
|
1697
|
+
const propType = createTopLevelObjectType({
|
|
1698
|
+
schema: {
|
|
1699
|
+
[bind]: elementType.propsSchema[bind]
|
|
1700
|
+
}
|
|
1701
|
+
});
|
|
1702
|
+
const objectPlaceholder = placeholder ? { [bind]: placeholder } : void 0;
|
|
1703
|
+
return /* @__PURE__ */ React13.createElement(
|
|
1704
|
+
PropProvider,
|
|
1705
|
+
{
|
|
1706
|
+
...propContext,
|
|
1707
|
+
propType,
|
|
1708
|
+
setValue: setOverridableValue,
|
|
1709
|
+
value: { [bind]: value.origin_value },
|
|
1710
|
+
placeholder: objectPlaceholder
|
|
284
1711
|
},
|
|
285
|
-
|
|
286
|
-
)
|
|
1712
|
+
/* @__PURE__ */ React13.createElement(PropKeyProvider, { bind }, /* @__PURE__ */ React13.createElement(ControlReplacementsProvider, { replacements: [] }, /* @__PURE__ */ React13.createElement(OriginalControl, { ...props })))
|
|
1713
|
+
);
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
// src/components/overridable-props/overridable-prop-indicator.tsx
|
|
1717
|
+
import * as React16 from "react";
|
|
1718
|
+
import { useBoundProp as useBoundProp2 } from "@elementor/editor-controls";
|
|
1719
|
+
import { getV1CurrentDocument } from "@elementor/editor-documents";
|
|
1720
|
+
import { useElement as useElement2 } from "@elementor/editor-editing-panel";
|
|
1721
|
+
import { getWidgetsCache } from "@elementor/editor-elements";
|
|
1722
|
+
import { __getState as getState9 } from "@elementor/store";
|
|
1723
|
+
import { bindPopover, bindTrigger as bindTrigger2, Popover as Popover2, Tooltip as Tooltip2, usePopupState as usePopupState2 } from "@elementor/ui";
|
|
1724
|
+
import { __ as __14 } from "@wordpress/i18n";
|
|
1725
|
+
|
|
1726
|
+
// src/store/actions/set-overridable-prop.ts
|
|
1727
|
+
import { __dispatch as dispatch5, __getState as getState7 } from "@elementor/store";
|
|
1728
|
+
import { generateUniqueId as generateUniqueId2 } from "@elementor/utils";
|
|
1729
|
+
import { __ as __11 } from "@wordpress/i18n";
|
|
1730
|
+
function setOverridableProp({
|
|
1731
|
+
componentId,
|
|
1732
|
+
overrideKey,
|
|
1733
|
+
elementId,
|
|
1734
|
+
label,
|
|
1735
|
+
groupId,
|
|
1736
|
+
propKey,
|
|
1737
|
+
elType,
|
|
1738
|
+
widgetType,
|
|
1739
|
+
originValue
|
|
1740
|
+
}) {
|
|
1741
|
+
const overridableProps = selectOverridableProps(getState7(), componentId);
|
|
1742
|
+
if (!overridableProps) {
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
const existingOverridableProp = overrideKey ? overridableProps.props[overrideKey] : null;
|
|
1746
|
+
const duplicatedTargetProps = Object.values(overridableProps.props).filter(
|
|
1747
|
+
(prop) => prop.elementId === elementId && prop.propKey === propKey && prop !== existingOverridableProp
|
|
1748
|
+
);
|
|
1749
|
+
const { props: prevProps, groups: prevGroups } = { ...overridableProps };
|
|
1750
|
+
const { groups: updatedGroups, currentGroupId } = getUpdatedGroups(
|
|
1751
|
+
prevGroups,
|
|
1752
|
+
groupId || existingOverridableProp?.groupId
|
|
1753
|
+
);
|
|
1754
|
+
const overridableProp = {
|
|
1755
|
+
overrideKey: existingOverridableProp?.overrideKey || generateUniqueId2("prop"),
|
|
1756
|
+
label,
|
|
1757
|
+
elementId,
|
|
1758
|
+
propKey,
|
|
1759
|
+
widgetType,
|
|
1760
|
+
elType,
|
|
1761
|
+
originValue,
|
|
1762
|
+
groupId: currentGroupId
|
|
1763
|
+
};
|
|
1764
|
+
const { props: propsWithoutDuplicates, groups: groupsWithoutDuplicates } = removeProps({
|
|
1765
|
+
props: prevProps,
|
|
1766
|
+
groups: updatedGroups,
|
|
1767
|
+
propsToRemove: duplicatedTargetProps
|
|
1768
|
+
});
|
|
1769
|
+
const props = {
|
|
1770
|
+
...propsWithoutDuplicates,
|
|
1771
|
+
[overridableProp.overrideKey]: overridableProp
|
|
1772
|
+
};
|
|
1773
|
+
const groups = {
|
|
1774
|
+
items: {
|
|
1775
|
+
...groupsWithoutDuplicates.items,
|
|
1776
|
+
[currentGroupId]: getGroupWithProp(groupsWithoutDuplicates, currentGroupId, overridableProp)
|
|
1777
|
+
},
|
|
1778
|
+
order: groupsWithoutDuplicates.order.includes(currentGroupId) ? groupsWithoutDuplicates.order : [...groupsWithoutDuplicates.order, currentGroupId]
|
|
1779
|
+
};
|
|
1780
|
+
const isChangingGroups = existingOverridableProp && existingOverridableProp.groupId !== currentGroupId;
|
|
1781
|
+
if (isChangingGroups) {
|
|
1782
|
+
groups.items[existingOverridableProp.groupId] = getGroupWithoutProp(
|
|
1783
|
+
groupsWithoutDuplicates,
|
|
1784
|
+
existingOverridableProp.groupId,
|
|
1785
|
+
overridableProp
|
|
1786
|
+
);
|
|
1787
|
+
}
|
|
1788
|
+
dispatch5(
|
|
1789
|
+
slice.actions.setOverridableProps({
|
|
1790
|
+
componentId,
|
|
1791
|
+
overridableProps: {
|
|
1792
|
+
props,
|
|
1793
|
+
groups
|
|
1794
|
+
}
|
|
1795
|
+
})
|
|
1796
|
+
);
|
|
1797
|
+
return overridableProp;
|
|
1798
|
+
}
|
|
1799
|
+
function getUpdatedGroups(groups, groupId) {
|
|
1800
|
+
if (!groupId) {
|
|
1801
|
+
if (groups.order.length > 0) {
|
|
1802
|
+
return { groups, currentGroupId: groups.order[0] };
|
|
1803
|
+
}
|
|
1804
|
+
return addNewGroup(groups);
|
|
1805
|
+
}
|
|
1806
|
+
if (!groups.items[groupId]) {
|
|
1807
|
+
return addNewGroup(groups, groupId);
|
|
1808
|
+
}
|
|
1809
|
+
return { groups, currentGroupId: groupId };
|
|
1810
|
+
}
|
|
1811
|
+
function addNewGroup(groups, groupId) {
|
|
1812
|
+
const currentGroupId = groupId || generateUniqueId2("group");
|
|
1813
|
+
const updatedGroups = {
|
|
1814
|
+
...groups,
|
|
1815
|
+
items: {
|
|
1816
|
+
...groups.items,
|
|
1817
|
+
[currentGroupId]: {
|
|
1818
|
+
id: currentGroupId,
|
|
1819
|
+
label: __11("Default", "elementor"),
|
|
1820
|
+
props: []
|
|
1821
|
+
}
|
|
1822
|
+
},
|
|
1823
|
+
order: [...groups.order, currentGroupId]
|
|
1824
|
+
};
|
|
1825
|
+
return { groups: updatedGroups, currentGroupId };
|
|
1826
|
+
}
|
|
1827
|
+
function getGroupWithProp(groups, groupId, overridableProp) {
|
|
1828
|
+
const group = { ...groups.items[groupId] };
|
|
1829
|
+
if (!group.props.includes(overridableProp.overrideKey)) {
|
|
1830
|
+
group.props = [...group.props, overridableProp.overrideKey];
|
|
1831
|
+
}
|
|
1832
|
+
return group;
|
|
1833
|
+
}
|
|
1834
|
+
function getGroupWithoutProp(groups, groupId, overridableProp) {
|
|
1835
|
+
const group = { ...groups.items[groupId] };
|
|
1836
|
+
if (group) {
|
|
1837
|
+
group.props = group.props.filter((key) => key !== overridableProp.overrideKey);
|
|
1838
|
+
}
|
|
1839
|
+
return group;
|
|
1840
|
+
}
|
|
1841
|
+
function removeProps({
|
|
1842
|
+
props,
|
|
1843
|
+
groups,
|
|
1844
|
+
propsToRemove
|
|
1845
|
+
}) {
|
|
1846
|
+
const allProps = Object.fromEntries(
|
|
1847
|
+
Object.entries(props).filter(([, prop]) => !propsToRemove.includes(prop))
|
|
1848
|
+
);
|
|
1849
|
+
const overrideKeysToRemove = propsToRemove.map((prop) => prop.overrideKey);
|
|
1850
|
+
const allGroupItems = Object.fromEntries(
|
|
1851
|
+
Object.entries(groups.items).map(([groupId, group]) => [
|
|
1852
|
+
groupId,
|
|
1853
|
+
{
|
|
1854
|
+
...group,
|
|
1855
|
+
props: group.props.filter((prop) => !overrideKeysToRemove.includes(prop))
|
|
1856
|
+
}
|
|
1857
|
+
])
|
|
1858
|
+
);
|
|
1859
|
+
return {
|
|
1860
|
+
props: allProps,
|
|
1861
|
+
groups: {
|
|
1862
|
+
items: allGroupItems,
|
|
1863
|
+
order: groups.order.filter((groupId) => !overrideKeysToRemove.includes(groupId))
|
|
1864
|
+
}
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// src/components/overridable-props/indicator.tsx
|
|
1869
|
+
import * as React14 from "react";
|
|
1870
|
+
import { forwardRef } from "react";
|
|
1871
|
+
import { CheckIcon, PlusIcon } from "@elementor/icons";
|
|
1872
|
+
import { Box as Box8, styled as styled2 } from "@elementor/ui";
|
|
1873
|
+
import { __ as __12 } from "@wordpress/i18n";
|
|
1874
|
+
var SIZE = "tiny";
|
|
1875
|
+
var IconContainer = styled2(Box8)`
|
|
1876
|
+
pointer-events: none;
|
|
1877
|
+
opacity: 0;
|
|
1878
|
+
transition: opacity 0.2s ease-in-out;
|
|
1879
|
+
|
|
1880
|
+
& > svg {
|
|
1881
|
+
position: absolute;
|
|
1882
|
+
top: 50%;
|
|
1883
|
+
left: 50%;
|
|
1884
|
+
transform: translate( -50%, -50% );
|
|
1885
|
+
width: 10px;
|
|
1886
|
+
height: 10px;
|
|
1887
|
+
fill: ${({ theme }) => theme.palette.primary.contrastText};
|
|
1888
|
+
stroke: ${({ theme }) => theme.palette.primary.contrastText};
|
|
1889
|
+
stroke-width: 2px;
|
|
1890
|
+
}
|
|
1891
|
+
`;
|
|
1892
|
+
var Content = styled2(Box8)`
|
|
1893
|
+
position: relative;
|
|
1894
|
+
display: flex;
|
|
1895
|
+
align-items: center;
|
|
1896
|
+
justify-content: center;
|
|
1897
|
+
cursor: pointer;
|
|
1898
|
+
width: 16px;
|
|
1899
|
+
height: 16px;
|
|
1900
|
+
margin-inline: ${({ theme }) => theme.spacing(0.5)};
|
|
1901
|
+
|
|
1902
|
+
&:before {
|
|
1903
|
+
content: '';
|
|
1904
|
+
display: block;
|
|
1905
|
+
position: absolute;
|
|
1906
|
+
top: 50%;
|
|
1907
|
+
left: 50%;
|
|
1908
|
+
transform: translate( -50%, -50% ) rotate( 45deg );
|
|
1909
|
+
width: 5px;
|
|
1910
|
+
height: 5px;
|
|
1911
|
+
border-radius: 1px;
|
|
1912
|
+
background-color: ${({ theme }) => theme.palette.primary.main};
|
|
1913
|
+
transition: all 0.1s ease-in-out;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
&:hover,
|
|
1917
|
+
&.enlarged {
|
|
1918
|
+
&:before {
|
|
1919
|
+
width: 12px;
|
|
1920
|
+
height: 12px;
|
|
1921
|
+
border-radius: 2px;
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
.icon {
|
|
1925
|
+
opacity: 1;
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
`;
|
|
1929
|
+
var Indicator = forwardRef(({ isOpen, isOverridable, ...props }, ref) => /* @__PURE__ */ React14.createElement(Content, { ref, ...props, className: isOpen || isOverridable ? "enlarged" : "" }, /* @__PURE__ */ React14.createElement(
|
|
1930
|
+
IconContainer,
|
|
1931
|
+
{
|
|
1932
|
+
className: "icon",
|
|
1933
|
+
"aria-label": isOverridable ? __12("Overridable property", "elementor") : __12("Make prop overridable", "elementor")
|
|
1934
|
+
},
|
|
1935
|
+
isOverridable ? /* @__PURE__ */ React14.createElement(CheckIcon, { fontSize: SIZE }) : /* @__PURE__ */ React14.createElement(PlusIcon, { fontSize: SIZE })
|
|
1936
|
+
)));
|
|
1937
|
+
|
|
1938
|
+
// src/components/overridable-props/overridable-prop-form.tsx
|
|
1939
|
+
import * as React15 from "react";
|
|
1940
|
+
import { useState as useState4 } from "react";
|
|
1941
|
+
import { Form as Form2, MenuListItem as MenuListItem2 } from "@elementor/editor-ui";
|
|
1942
|
+
import { Button as Button3, FormLabel as FormLabel2, Grid as Grid2, Select, Stack as Stack7, TextField as TextField3, Typography as Typography6 } from "@elementor/ui";
|
|
1943
|
+
import { __ as __13 } from "@wordpress/i18n";
|
|
1944
|
+
var SIZE2 = "tiny";
|
|
1945
|
+
var DEFAULT_GROUP = { value: null, label: __13("Default", "elementor") };
|
|
1946
|
+
function OverridablePropForm({ onSubmit, groups, currentValue }) {
|
|
1947
|
+
const [propLabel, setPropLabel] = useState4(currentValue?.label ?? null);
|
|
1948
|
+
const [group, setGroup] = useState4(currentValue?.groupId ?? groups?.[0]?.value ?? null);
|
|
1949
|
+
const name = __13("Name", "elementor");
|
|
1950
|
+
const groupName = __13("Group Name", "elementor");
|
|
1951
|
+
const isCreate = currentValue === void 0;
|
|
1952
|
+
const title = isCreate ? __13("Create new property", "elementor") : __13("Update property", "elementor");
|
|
1953
|
+
const ctaLabel = isCreate ? __13("Create", "elementor") : __13("Update", "elementor");
|
|
1954
|
+
return /* @__PURE__ */ React15.createElement(Form2, { onSubmit: () => onSubmit({ label: propLabel ?? "", group }) }, /* @__PURE__ */ React15.createElement(Stack7, { alignItems: "start", width: "268px" }, /* @__PURE__ */ React15.createElement(
|
|
1955
|
+
Stack7,
|
|
1956
|
+
{
|
|
1957
|
+
direction: "row",
|
|
1958
|
+
alignItems: "center",
|
|
1959
|
+
py: 1,
|
|
1960
|
+
px: 1.5,
|
|
1961
|
+
sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%", mb: 1.5 }
|
|
1962
|
+
},
|
|
1963
|
+
/* @__PURE__ */ React15.createElement(Typography6, { variant: "caption", sx: { color: "text.primary", fontWeight: "500", lineHeight: 1 } }, title)
|
|
1964
|
+
), /* @__PURE__ */ React15.createElement(Grid2, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React15.createElement(Grid2, { item: true, xs: 12 }, /* @__PURE__ */ React15.createElement(FormLabel2, { size: "tiny" }, name)), /* @__PURE__ */ React15.createElement(Grid2, { item: true, xs: 12 }, /* @__PURE__ */ React15.createElement(
|
|
1965
|
+
TextField3,
|
|
1966
|
+
{
|
|
1967
|
+
name,
|
|
1968
|
+
size: SIZE2,
|
|
1969
|
+
fullWidth: true,
|
|
1970
|
+
placeholder: __13("Enter value", "elementor"),
|
|
1971
|
+
value: propLabel ?? "",
|
|
1972
|
+
onChange: (e) => setPropLabel(e.target.value)
|
|
1973
|
+
}
|
|
1974
|
+
))), /* @__PURE__ */ React15.createElement(Grid2, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React15.createElement(Grid2, { item: true, xs: 12 }, /* @__PURE__ */ React15.createElement(FormLabel2, { size: "tiny" }, groupName)), /* @__PURE__ */ React15.createElement(Grid2, { item: true, xs: 12 }, /* @__PURE__ */ React15.createElement(
|
|
1975
|
+
Select,
|
|
1976
|
+
{
|
|
1977
|
+
name: groupName,
|
|
1978
|
+
size: SIZE2,
|
|
1979
|
+
fullWidth: true,
|
|
1980
|
+
value: group ?? null,
|
|
1981
|
+
onChange: setGroup,
|
|
1982
|
+
displayEmpty: true,
|
|
1983
|
+
renderValue: (selectedValue) => {
|
|
1984
|
+
if (!selectedValue || selectedValue === "") {
|
|
1985
|
+
const [firstGroup = DEFAULT_GROUP] = groups ?? [];
|
|
1986
|
+
return firstGroup.label;
|
|
1987
|
+
}
|
|
1988
|
+
return groups?.find(({ value }) => value === selectedValue)?.label ?? selectedValue;
|
|
1989
|
+
}
|
|
1990
|
+
},
|
|
1991
|
+
(groups ?? [DEFAULT_GROUP]).map(({ label: groupLabel, ...props }) => /* @__PURE__ */ React15.createElement(MenuListItem2, { key: props.value, ...props, value: props.value ?? "" }, groupLabel))
|
|
1992
|
+
))), /* @__PURE__ */ React15.createElement(Stack7, { direction: "row", justifyContent: "flex-end", alignSelf: "end", mt: 1.5, py: 1, px: 1.5 }, /* @__PURE__ */ React15.createElement(Button3, { type: "submit", disabled: !propLabel, variant: "contained", color: "primary", size: "small" }, ctaLabel))));
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
// src/components/overridable-props/utils/get-overridable-prop.ts
|
|
1996
|
+
import { __getState as getState8 } from "@elementor/store";
|
|
1997
|
+
function getOverridableProp({
|
|
1998
|
+
componentId,
|
|
1999
|
+
overrideKey
|
|
2000
|
+
}) {
|
|
2001
|
+
const overridableProps = selectOverridableProps(getState8(), componentId);
|
|
2002
|
+
if (!overridableProps) {
|
|
2003
|
+
return void 0;
|
|
2004
|
+
}
|
|
2005
|
+
return overridableProps.props[overrideKey];
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
// src/components/overridable-props/overridable-prop-indicator.tsx
|
|
2009
|
+
var FORBIDDEN_KEYS = ["_cssid", "attributes"];
|
|
2010
|
+
function OverridablePropIndicator() {
|
|
2011
|
+
const { bind } = useBoundProp2();
|
|
2012
|
+
const currentDocument = getV1CurrentDocument();
|
|
2013
|
+
if (currentDocument.config.type !== COMPONENT_DOCUMENT_TYPE || !currentDocument.id) {
|
|
2014
|
+
return null;
|
|
2015
|
+
}
|
|
2016
|
+
if (!isPropAllowed(bind)) {
|
|
2017
|
+
return null;
|
|
2018
|
+
}
|
|
2019
|
+
const overridableProps = selectOverridableProps(getState9(), currentDocument.id);
|
|
2020
|
+
return /* @__PURE__ */ React16.createElement(Content2, { componentId: currentDocument.id, overridableProps });
|
|
2021
|
+
}
|
|
2022
|
+
function Content2({ componentId, overridableProps }) {
|
|
2023
|
+
const {
|
|
2024
|
+
element: { id: elementId },
|
|
2025
|
+
elementType
|
|
2026
|
+
} = useElement2();
|
|
2027
|
+
const { value, bind, propType } = useBoundProp2();
|
|
2028
|
+
const { value: overridableValue, setValue: setOverridableValue } = useBoundProp2(componentOverridablePropTypeUtil);
|
|
2029
|
+
const popupState = usePopupState2({
|
|
2030
|
+
variant: "popover"
|
|
2031
|
+
});
|
|
2032
|
+
const triggerProps = bindTrigger2(popupState);
|
|
2033
|
+
const popoverProps = bindPopover(popupState);
|
|
2034
|
+
const { elType } = getWidgetsCache()?.[elementType.key] ?? { elType: "widget" };
|
|
2035
|
+
const handleSubmit = ({ label, group }) => {
|
|
2036
|
+
const originValue = !overridableValue ? value ?? propType.default : overridableValue?.origin_value ?? {};
|
|
2037
|
+
const overridablePropConfig = setOverridableProp({
|
|
2038
|
+
componentId,
|
|
2039
|
+
overrideKey: overridableValue?.override_key ?? null,
|
|
2040
|
+
elementId,
|
|
2041
|
+
label,
|
|
2042
|
+
groupId: group,
|
|
2043
|
+
propKey: bind,
|
|
2044
|
+
elType: elType ?? "widget",
|
|
2045
|
+
widgetType: elementType.key,
|
|
2046
|
+
originValue
|
|
2047
|
+
});
|
|
2048
|
+
if (!overridableValue && overridablePropConfig) {
|
|
2049
|
+
setOverridableValue({
|
|
2050
|
+
override_key: overridablePropConfig.overrideKey,
|
|
2051
|
+
origin_value: originValue
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
popupState.close();
|
|
2055
|
+
};
|
|
2056
|
+
const overridableConfig = overridableValue ? getOverridableProp({ componentId, overrideKey: overridableValue.override_key }) : void 0;
|
|
2057
|
+
return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Tooltip2, { placement: "top", title: __14("Override Property", "elementor") }, /* @__PURE__ */ React16.createElement(Indicator, { ...triggerProps, isOpen: !!popoverProps.open, isOverridable: !!overridableValue })), /* @__PURE__ */ React16.createElement(
|
|
2058
|
+
Popover2,
|
|
2059
|
+
{
|
|
2060
|
+
disableScrollLock: true,
|
|
2061
|
+
anchorOrigin: {
|
|
2062
|
+
vertical: "bottom",
|
|
2063
|
+
horizontal: "right"
|
|
2064
|
+
},
|
|
2065
|
+
transformOrigin: {
|
|
2066
|
+
vertical: "top",
|
|
2067
|
+
horizontal: "right"
|
|
2068
|
+
},
|
|
2069
|
+
PaperProps: {
|
|
2070
|
+
sx: { my: 2.5 }
|
|
2071
|
+
},
|
|
2072
|
+
...popoverProps
|
|
2073
|
+
},
|
|
2074
|
+
/* @__PURE__ */ React16.createElement(
|
|
2075
|
+
OverridablePropForm,
|
|
2076
|
+
{
|
|
2077
|
+
onSubmit: handleSubmit,
|
|
2078
|
+
groups: overridableProps?.groups.order.map((groupId) => ({
|
|
2079
|
+
value: groupId,
|
|
2080
|
+
label: overridableProps.groups.items[groupId].label
|
|
2081
|
+
})),
|
|
2082
|
+
currentValue: overridableConfig
|
|
2083
|
+
}
|
|
2084
|
+
)
|
|
2085
|
+
));
|
|
2086
|
+
}
|
|
2087
|
+
function isPropAllowed(bind) {
|
|
2088
|
+
return !FORBIDDEN_KEYS.includes(bind);
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
// src/mcp/index.ts
|
|
2092
|
+
import { getMCPByDomain as getMCPByDomain2 } from "@elementor/editor-mcp";
|
|
2093
|
+
|
|
2094
|
+
// src/mcp/save-as-component-tool.ts
|
|
2095
|
+
import { getContainer as getContainer2 } from "@elementor/editor-elements";
|
|
2096
|
+
import { getMCPByDomain } from "@elementor/editor-mcp";
|
|
2097
|
+
import { z as z3 } from "@elementor/schema";
|
|
2098
|
+
var InputSchema = {
|
|
2099
|
+
element_id: z3.string().describe(
|
|
2100
|
+
'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.'
|
|
2101
|
+
),
|
|
2102
|
+
component_name: z3.string().describe("The name for the new component. Should be descriptive and unique among existing components.")
|
|
2103
|
+
};
|
|
2104
|
+
var OutputSchema = {
|
|
2105
|
+
message: z3.string().optional().describe("Additional information about the operation result"),
|
|
2106
|
+
component_uid: z3.string().optional().describe("The unique identifier of the newly created component (only present on success)")
|
|
2107
|
+
};
|
|
2108
|
+
var VALID_ELEMENT_TYPES = ["e-div-block", "e-flexbox", "e-tabs"];
|
|
2109
|
+
var ERROR_MESSAGES = {
|
|
2110
|
+
ELEMENT_NOT_FOUND: "Element not found. Use 'list-elements' to get valid element IDs.",
|
|
2111
|
+
ELEMENT_NOT_ONE_OF_TYPES: `Element is not one of the following types: ${VALID_ELEMENT_TYPES.join(", ")}`,
|
|
2112
|
+
ELEMENT_IS_LOCKED: "Cannot save a locked element as a component."
|
|
2113
|
+
};
|
|
2114
|
+
var handleSaveAsComponent = async (params) => {
|
|
2115
|
+
const { element_id: elementId, component_name: componentName } = params;
|
|
2116
|
+
const container = getContainer2(elementId);
|
|
2117
|
+
if (!container) {
|
|
2118
|
+
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_FOUND);
|
|
2119
|
+
}
|
|
2120
|
+
const elType = container.model.get("elType");
|
|
2121
|
+
if (!VALID_ELEMENT_TYPES.includes(elType)) {
|
|
2122
|
+
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_ONE_OF_TYPES);
|
|
2123
|
+
}
|
|
2124
|
+
const element = container.model.toJSON({ remove: ["default"] });
|
|
2125
|
+
if (element?.isLocked) {
|
|
2126
|
+
throw new Error(ERROR_MESSAGES.ELEMENT_IS_LOCKED);
|
|
2127
|
+
}
|
|
2128
|
+
const uid = createUnpublishedComponent(componentName, element, null);
|
|
2129
|
+
return {
|
|
2130
|
+
status: "ok",
|
|
2131
|
+
message: `Component "${componentName}" created successfully.`,
|
|
2132
|
+
component_uid: uid
|
|
2133
|
+
};
|
|
2134
|
+
};
|
|
2135
|
+
var initSaveAsComponentTool = () => {
|
|
2136
|
+
return getMCPByDomain("components").addTool({
|
|
2137
|
+
name: "save-as-component",
|
|
2138
|
+
schema: InputSchema,
|
|
2139
|
+
outputSchema: OutputSchema,
|
|
2140
|
+
description: `Save an existing element as a reusable component in the Elementor editor.
|
|
2141
|
+
|
|
2142
|
+
## When NOT to use this tool:
|
|
2143
|
+
- Do not use for elements that are already components (widgetType: 'e-component').
|
|
2144
|
+
- Do not use for locked elements.
|
|
2145
|
+
- Do not guess element IDs. Always use "list-elements" first to get valid IDs.
|
|
2146
|
+
|
|
2147
|
+
## Prerequisites:
|
|
2148
|
+
- **Verify element type**: Ensure the element is not already a component (widgetType should not be 'e-component').
|
|
2149
|
+
- **Check if element is unlocked**: Locked elements cannot be saved as components.
|
|
2150
|
+
- **Check that the element is one of the following types**: ${VALID_ELEMENT_TYPES.join(", ")}
|
|
2151
|
+
|
|
2152
|
+
## Required parameters:
|
|
2153
|
+
- **element_id**: The unique ID of the element to save.
|
|
2154
|
+
- **component_name**: A descriptive name for the component (2-50 characters).
|
|
2155
|
+
|
|
2156
|
+
## Example tool call:
|
|
2157
|
+
\`\`\`json
|
|
2158
|
+
{ "element_id": "abc123", "component_name": "Hero Section" }
|
|
2159
|
+
\`\`\`
|
|
2160
|
+
`,
|
|
2161
|
+
handler: handleSaveAsComponent
|
|
2162
|
+
});
|
|
2163
|
+
};
|
|
2164
|
+
|
|
2165
|
+
// src/mcp/index.ts
|
|
2166
|
+
function initMcp() {
|
|
2167
|
+
const { setMCPDescription } = getMCPByDomain2("components");
|
|
2168
|
+
setMCPDescription(
|
|
2169
|
+
`Elementor Editor Components MCP - Tools for creating and managing reusable components.
|
|
2170
|
+
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.`
|
|
2171
|
+
);
|
|
2172
|
+
initSaveAsComponentTool();
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
// src/populate-store.ts
|
|
2176
|
+
import { useEffect as useEffect6 } from "react";
|
|
2177
|
+
import { __dispatch as dispatch6 } from "@elementor/store";
|
|
2178
|
+
function PopulateStore() {
|
|
2179
|
+
useEffect6(() => {
|
|
2180
|
+
dispatch6(loadComponents());
|
|
2181
|
+
}, []);
|
|
2182
|
+
return null;
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
// src/store/actions/remove-component-styles.ts
|
|
2186
|
+
import { __dispatch as dispatch7 } from "@elementor/store";
|
|
2187
|
+
function removeComponentStyles(id) {
|
|
2188
|
+
apiClient.invalidateComponentConfigCache(id);
|
|
2189
|
+
dispatch7(slice.actions.removeStyles({ id }));
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
// src/store/components-styles-provider.ts
|
|
2193
|
+
import { createStylesProvider } from "@elementor/editor-styles-repository";
|
|
2194
|
+
import { __getState as getState10, __subscribeWithSelector as subscribeWithSelector } from "@elementor/store";
|
|
2195
|
+
var componentsStylesProvider = createStylesProvider({
|
|
2196
|
+
key: "components-styles",
|
|
2197
|
+
priority: 100,
|
|
2198
|
+
subscribe: (cb) => subscribeWithSelector(
|
|
2199
|
+
(state) => state[SLICE_NAME],
|
|
2200
|
+
() => {
|
|
2201
|
+
cb();
|
|
2202
|
+
}
|
|
2203
|
+
),
|
|
2204
|
+
actions: {
|
|
2205
|
+
all: () => {
|
|
2206
|
+
return selectFlatStyles(getState10());
|
|
2207
|
+
},
|
|
2208
|
+
get: (id) => {
|
|
2209
|
+
return selectFlatStyles(getState10()).find((style) => style.id === id) ?? null;
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
});
|
|
2213
|
+
|
|
2214
|
+
// src/sync/create-components-before-save.ts
|
|
2215
|
+
import { updateElementSettings } from "@elementor/editor-elements";
|
|
2216
|
+
import { __dispatch as dispatch8, __getState as getState11 } from "@elementor/store";
|
|
2217
|
+
async function createComponentsBeforeSave({
|
|
2218
|
+
elements,
|
|
2219
|
+
status
|
|
2220
|
+
}) {
|
|
2221
|
+
const unpublishedComponents = selectUnpublishedComponents(getState11());
|
|
2222
|
+
if (!unpublishedComponents.length) {
|
|
2223
|
+
return;
|
|
2224
|
+
}
|
|
2225
|
+
try {
|
|
2226
|
+
const uidToComponentId = await createComponents(unpublishedComponents, status);
|
|
2227
|
+
updateComponentInstances(elements, uidToComponentId);
|
|
2228
|
+
dispatch8(
|
|
2229
|
+
slice.actions.add(
|
|
2230
|
+
unpublishedComponents.map((component) => ({
|
|
2231
|
+
id: uidToComponentId.get(component.uid),
|
|
2232
|
+
name: component.name,
|
|
2233
|
+
uid: component.uid
|
|
2234
|
+
}))
|
|
2235
|
+
)
|
|
2236
|
+
);
|
|
2237
|
+
dispatch8(slice.actions.resetUnpublished());
|
|
2238
|
+
} catch (error) {
|
|
2239
|
+
throw new Error(`Failed to publish components and update component instances: ${error}`);
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
async function createComponents(components, status) {
|
|
2243
|
+
const response = await apiClient.create({
|
|
2244
|
+
status,
|
|
2245
|
+
items: components.map((component) => ({
|
|
2246
|
+
uid: component.uid,
|
|
2247
|
+
title: component.name,
|
|
2248
|
+
elements: component.elements
|
|
2249
|
+
}))
|
|
2250
|
+
});
|
|
2251
|
+
const map = /* @__PURE__ */ new Map();
|
|
2252
|
+
Object.entries(response).forEach(([key, value]) => {
|
|
2253
|
+
map.set(key, value);
|
|
2254
|
+
});
|
|
2255
|
+
return map;
|
|
2256
|
+
}
|
|
2257
|
+
function updateComponentInstances(elements, uidToComponentId) {
|
|
2258
|
+
elements.forEach((element) => {
|
|
2259
|
+
const { shouldUpdate, newComponentId } = shouldUpdateElement(element, uidToComponentId);
|
|
2260
|
+
if (shouldUpdate) {
|
|
2261
|
+
updateElementComponentId(element.id, newComponentId);
|
|
2262
|
+
}
|
|
2263
|
+
if (element.elements) {
|
|
2264
|
+
updateComponentInstances(element.elements, uidToComponentId);
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
function shouldUpdateElement(element, uidToComponentId) {
|
|
2269
|
+
if (element.widgetType === "e-component") {
|
|
2270
|
+
const currentComponentId = element.settings?.component_instance?.value?.component_id;
|
|
2271
|
+
if (currentComponentId && uidToComponentId.has(currentComponentId)) {
|
|
2272
|
+
return { shouldUpdate: true, newComponentId: uidToComponentId.get(currentComponentId) };
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
return { shouldUpdate: false, newComponentId: null };
|
|
2276
|
+
}
|
|
2277
|
+
function updateElementComponentId(elementId, componentId) {
|
|
2278
|
+
updateElementSettings({
|
|
2279
|
+
id: elementId,
|
|
2280
|
+
props: {
|
|
2281
|
+
component_instance: {
|
|
2282
|
+
$$type: "component-instance",
|
|
2283
|
+
value: { component_id: componentId }
|
|
2284
|
+
}
|
|
2285
|
+
},
|
|
2286
|
+
withHistory: false
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
// src/sync/set-component-overridable-props-settings-before-save.ts
|
|
2291
|
+
import { __getState as getState12 } from "@elementor/store";
|
|
2292
|
+
var setComponentOverridablePropsSettingsBeforeSave = ({
|
|
2293
|
+
container
|
|
2294
|
+
}) => {
|
|
2295
|
+
const currentDocument = container.document;
|
|
2296
|
+
if (!currentDocument || currentDocument.config.type !== COMPONENT_DOCUMENT_TYPE) {
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
const overridableProps = selectOverridableProps(getState12(), currentDocument.id);
|
|
2300
|
+
if (overridableProps) {
|
|
2301
|
+
container.settings.set("overridable_props", overridableProps);
|
|
2302
|
+
}
|
|
2303
|
+
};
|
|
2304
|
+
|
|
2305
|
+
// src/sync/update-archived-component-before-save.ts
|
|
2306
|
+
import { notify } from "@elementor/editor-notifications";
|
|
2307
|
+
import { __getState as getState13 } from "@elementor/store";
|
|
2308
|
+
var failedNotification = (message) => ({
|
|
2309
|
+
type: "error",
|
|
2310
|
+
message: `Failed to archive components: ${message}`,
|
|
2311
|
+
id: "failed-archived-components-notification"
|
|
2312
|
+
});
|
|
2313
|
+
var successNotification = (message) => ({
|
|
2314
|
+
type: "success",
|
|
2315
|
+
message: `Successfully archived components: ${message}`,
|
|
2316
|
+
id: "success-archived-components-notification"
|
|
2317
|
+
});
|
|
2318
|
+
var updateArchivedComponentBeforeSave = async () => {
|
|
2319
|
+
try {
|
|
2320
|
+
const archivedComponents = selectArchivedComponents(getState13());
|
|
2321
|
+
if (!archivedComponents.length) {
|
|
2322
|
+
return;
|
|
2323
|
+
}
|
|
2324
|
+
const result = await apiClient.updateArchivedComponents(
|
|
2325
|
+
archivedComponents.map((component) => component.id)
|
|
2326
|
+
);
|
|
2327
|
+
const failedIds = result.failedIds.join(", ");
|
|
2328
|
+
const successIds = result.successIds.join(", ");
|
|
2329
|
+
if (failedIds) {
|
|
2330
|
+
notify(failedNotification(failedIds));
|
|
2331
|
+
}
|
|
2332
|
+
if (successIds) {
|
|
2333
|
+
notify(successNotification(successIds));
|
|
2334
|
+
}
|
|
2335
|
+
} catch (error) {
|
|
2336
|
+
throw new Error(`Failed to update archived components: ${error}`);
|
|
2337
|
+
}
|
|
2338
|
+
};
|
|
2339
|
+
|
|
2340
|
+
// src/sync/update-components-before-save.ts
|
|
2341
|
+
import { isDocumentDirty as isDocumentDirty2 } from "@elementor/editor-documents";
|
|
2342
|
+
async function updateComponentsBeforeSave({ status, elements }) {
|
|
2343
|
+
if (status !== "publish") {
|
|
2344
|
+
return;
|
|
2345
|
+
}
|
|
2346
|
+
const componentIds = await getComponentIds(elements);
|
|
2347
|
+
const componentDocumentData = await Promise.all(componentIds.map(getComponentDocumentData));
|
|
2348
|
+
const draftIds = componentDocumentData.filter((document) => !!document).filter(isDocumentDirty2).map((document) => document.id);
|
|
2349
|
+
if (draftIds.length === 0) {
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
await apiClient.updateStatuses(draftIds, "publish");
|
|
2353
|
+
draftIds.forEach((id) => invalidateComponentDocumentData(id));
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
// src/sync/before-save.ts
|
|
2357
|
+
var beforeSave = ({ container, status }) => {
|
|
2358
|
+
const elements = container.model.get("elements")?.toJSON() ?? [];
|
|
2359
|
+
return Promise.all([
|
|
2360
|
+
updateArchivedComponentBeforeSave(),
|
|
2361
|
+
createComponentsBeforeSave({ elements, status }),
|
|
2362
|
+
updateComponentsBeforeSave({ elements, status }),
|
|
2363
|
+
setComponentOverridablePropsSettingsBeforeSave({ container })
|
|
2364
|
+
]);
|
|
287
2365
|
};
|
|
288
2366
|
|
|
289
2367
|
// src/init.ts
|
|
290
2368
|
function init() {
|
|
2369
|
+
stylesRepository.register(componentsStylesProvider);
|
|
2370
|
+
registerSlice(slice);
|
|
2371
|
+
registerElementType(
|
|
2372
|
+
TYPE,
|
|
2373
|
+
(options) => createComponentType({ ...options, showLockedByModal: openEditModeDialog })
|
|
2374
|
+
);
|
|
2375
|
+
registerDataHook("dependency", "editor/documents/close", (args) => {
|
|
2376
|
+
const document = getV1CurrentDocument2();
|
|
2377
|
+
if (document.config.type === COMPONENT_DOCUMENT_TYPE) {
|
|
2378
|
+
args.mode = "autosave";
|
|
2379
|
+
}
|
|
2380
|
+
return true;
|
|
2381
|
+
});
|
|
2382
|
+
registerDataHook("after", "preview/drop", onElementDrop);
|
|
2383
|
+
window.elementorCommon.__beforeSave = beforeSave;
|
|
291
2384
|
injectTab({
|
|
292
2385
|
id: "components",
|
|
293
|
-
label:
|
|
294
|
-
component:
|
|
2386
|
+
label: __15("Components", "elementor"),
|
|
2387
|
+
component: Components
|
|
295
2388
|
});
|
|
296
2389
|
injectIntoTop({
|
|
297
2390
|
id: "create-component-popup",
|
|
298
2391
|
component: CreateComponentForm
|
|
299
2392
|
});
|
|
2393
|
+
injectIntoLogic({
|
|
2394
|
+
id: "components-populate-store",
|
|
2395
|
+
component: PopulateStore
|
|
2396
|
+
});
|
|
2397
|
+
injectIntoTop({
|
|
2398
|
+
id: "edit-component",
|
|
2399
|
+
component: EditComponent
|
|
2400
|
+
});
|
|
2401
|
+
injectIntoPanelHeaderTop({
|
|
2402
|
+
id: "component-panel-header",
|
|
2403
|
+
component: ComponentPanelHeader
|
|
2404
|
+
});
|
|
2405
|
+
registerDataHook("after", "editor/documents/attach-preview", async () => {
|
|
2406
|
+
const { id, config } = getV1CurrentDocument2();
|
|
2407
|
+
if (id) {
|
|
2408
|
+
removeComponentStyles(id);
|
|
2409
|
+
}
|
|
2410
|
+
await loadComponentsAssets(config?.elements ?? []);
|
|
2411
|
+
});
|
|
2412
|
+
registerFieldIndicator({
|
|
2413
|
+
fieldType: FIELD_TYPE.SETTINGS,
|
|
2414
|
+
id: "component-overridable-prop",
|
|
2415
|
+
priority: 1,
|
|
2416
|
+
indicator: OverridablePropIndicator
|
|
2417
|
+
});
|
|
2418
|
+
registerControlReplacement({
|
|
2419
|
+
component: OverridablePropControl,
|
|
2420
|
+
condition: ({ value }) => componentOverridablePropTypeUtil.isValid(value)
|
|
2421
|
+
});
|
|
2422
|
+
settingsTransformersRegistry2.register("component-instance", componentInstanceTransformer);
|
|
2423
|
+
settingsTransformersRegistry2.register("overridable", componentOverridableTransformer);
|
|
2424
|
+
initMcp();
|
|
300
2425
|
}
|
|
301
2426
|
export {
|
|
302
2427
|
init
|