@elementor/editor-components 3.33.0-98 → 3.34.2
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 +1860 -123
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1863 -110
- package/dist/index.mjs.map +1 -1
- package/package.json +21 -11
- package/src/api.ts +57 -11
- package/src/component-instance-transformer.ts +24 -0
- package/src/component-overridable-transformer.ts +28 -0
- package/src/components/components-tab/component-search.tsx +32 -0
- package/src/components/components-tab/components-item.tsx +67 -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 +134 -0
- package/src/components/in-edit-mode.tsx +43 -0
- package/src/components/overridable-props/indicator.tsx +81 -0
- package/src/components/overridable-props/overridable-prop-form.tsx +98 -0
- package/src/components/overridable-props/overridable-prop-indicator.tsx +128 -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/init.ts +82 -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.ts +21 -0
- package/src/store/components-styles-provider.ts +24 -0
- package/src/store/create-unpublished-component.ts +40 -0
- package/src/store/load-components-assets.ts +26 -0
- package/src/store/load-components-styles.ts +44 -0
- package/src/store/remove-component-styles.ts +9 -0
- package/src/store/set-overridable-prop.ts +161 -0
- package/src/store/store.ts +168 -0
- package/src/store/thunks.ts +10 -0
- package/src/sync/before-save.ts +15 -0
- package/src/sync/create-components-before-save.ts +108 -0
- package/src/sync/update-components-before-save.ts +36 -0
- package/src/types.ts +91 -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.js
CHANGED
|
@@ -36,62 +36,860 @@ module.exports = __toCommonJS(index_exports);
|
|
|
36
36
|
|
|
37
37
|
// src/init.ts
|
|
38
38
|
var import_editor = require("@elementor/editor");
|
|
39
|
+
var import_editor_canvas6 = require("@elementor/editor-canvas");
|
|
40
|
+
var import_editor_documents7 = require("@elementor/editor-documents");
|
|
41
|
+
var import_editor_editing_panel2 = require("@elementor/editor-editing-panel");
|
|
39
42
|
var import_editor_elements_panel = require("@elementor/editor-elements-panel");
|
|
40
|
-
var
|
|
43
|
+
var import_editor_styles_repository2 = require("@elementor/editor-styles-repository");
|
|
44
|
+
var import_editor_v1_adapters6 = require("@elementor/editor-v1-adapters");
|
|
45
|
+
var import_store30 = require("@elementor/store");
|
|
46
|
+
var import_i18n12 = require("@wordpress/i18n");
|
|
41
47
|
|
|
42
|
-
// src/
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
function ComponentsTab() {
|
|
46
|
-
return /* @__PURE__ */ React.createElement(import_ui.Box, { px: 2 }, "This is the Components tab.");
|
|
47
|
-
}
|
|
48
|
+
// src/component-instance-transformer.ts
|
|
49
|
+
var import_editor_canvas = require("@elementor/editor-canvas");
|
|
50
|
+
var import_store3 = require("@elementor/store");
|
|
48
51
|
|
|
49
|
-
// src/
|
|
50
|
-
var
|
|
51
|
-
var import_react2 = require("react");
|
|
52
|
-
var import_editor_elements2 = require("@elementor/editor-elements");
|
|
53
|
-
var import_editor_ui = require("@elementor/editor-ui");
|
|
54
|
-
var import_icons = require("@elementor/icons");
|
|
55
|
-
var import_ui2 = require("@elementor/ui");
|
|
56
|
-
var import_i18n2 = require("@wordpress/i18n");
|
|
52
|
+
// src/store/store.ts
|
|
53
|
+
var import_store2 = require("@elementor/store");
|
|
57
54
|
|
|
58
|
-
// src/
|
|
59
|
-
var
|
|
55
|
+
// src/store/thunks.ts
|
|
56
|
+
var import_store = require("@elementor/store");
|
|
60
57
|
|
|
61
58
|
// src/api.ts
|
|
59
|
+
var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
|
|
62
60
|
var import_http_client = require("@elementor/http-client");
|
|
63
61
|
var BASE_URL = "elementor/v1/components";
|
|
62
|
+
var LOCK_COMPONENT = `${BASE_URL}/lock`;
|
|
63
|
+
var UNLOCK_COMPONENT = `${BASE_URL}/unlock`;
|
|
64
|
+
var BASE_URL_LOCK_STATUS = `${BASE_URL}/lock-status`;
|
|
65
|
+
var getParams = (id) => ({
|
|
66
|
+
action: "get_document_config",
|
|
67
|
+
unique_id: `document-config-${id}`,
|
|
68
|
+
data: { id }
|
|
69
|
+
});
|
|
64
70
|
var apiClient = {
|
|
65
71
|
get: () => (0, import_http_client.httpService)().get(`${BASE_URL}`).then((res) => res.data.data),
|
|
66
|
-
create: (payload) => (0, import_http_client.httpService)().post(`${BASE_URL}`, payload).then((res) => res.data.data)
|
|
72
|
+
create: (payload) => (0, import_http_client.httpService)().post(`${BASE_URL}`, payload).then((res) => res.data.data),
|
|
73
|
+
updateStatuses: (ids, status) => (0, import_http_client.httpService)().put(`${BASE_URL}/status`, {
|
|
74
|
+
ids,
|
|
75
|
+
status
|
|
76
|
+
}),
|
|
77
|
+
getComponentConfig: (id) => import_editor_v1_adapters.ajax.load(getParams(id)),
|
|
78
|
+
invalidateComponentConfigCache: (id) => import_editor_v1_adapters.ajax.invalidateCache(getParams(id)),
|
|
79
|
+
getComponentLockStatus: async (componentId) => await (0, import_http_client.httpService)().get(`${BASE_URL_LOCK_STATUS}`, {
|
|
80
|
+
params: {
|
|
81
|
+
componentId
|
|
82
|
+
}
|
|
83
|
+
}).then((res) => {
|
|
84
|
+
const { is_current_user_allow_to_edit: isAllowedToSwitchDocument, locked_by: lockedBy } = res.data.data;
|
|
85
|
+
return { isAllowedToSwitchDocument, lockedBy: lockedBy || "" };
|
|
86
|
+
}),
|
|
87
|
+
lockComponent: async (componentId) => await (0, import_http_client.httpService)().post(LOCK_COMPONENT, {
|
|
88
|
+
componentId
|
|
89
|
+
}).then((res) => res.data),
|
|
90
|
+
unlockComponent: async (componentId) => await (0, import_http_client.httpService)().post(UNLOCK_COMPONENT, {
|
|
91
|
+
componentId
|
|
92
|
+
}).then((res) => res.data)
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// src/store/thunks.ts
|
|
96
|
+
var loadComponents = (0, import_store.__createAsyncThunk)("components/load", async () => {
|
|
97
|
+
const response = await apiClient.get();
|
|
98
|
+
return response;
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// src/store/store.ts
|
|
102
|
+
var initialState = {
|
|
103
|
+
data: [],
|
|
104
|
+
unpublishedData: [],
|
|
105
|
+
loadStatus: "idle",
|
|
106
|
+
styles: {},
|
|
107
|
+
createdThisSession: [],
|
|
108
|
+
path: [],
|
|
109
|
+
currentComponentId: null
|
|
110
|
+
};
|
|
111
|
+
var SLICE_NAME = "components";
|
|
112
|
+
var slice = (0, import_store2.__createSlice)({
|
|
113
|
+
name: SLICE_NAME,
|
|
114
|
+
initialState,
|
|
115
|
+
reducers: {
|
|
116
|
+
add: (state, { payload }) => {
|
|
117
|
+
if (Array.isArray(payload)) {
|
|
118
|
+
state.data = [...state.data, ...payload];
|
|
119
|
+
} else {
|
|
120
|
+
state.data.unshift(payload);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
load: (state, { payload }) => {
|
|
124
|
+
state.data = payload;
|
|
125
|
+
},
|
|
126
|
+
addUnpublished: (state, { payload }) => {
|
|
127
|
+
state.unpublishedData.unshift(payload);
|
|
128
|
+
},
|
|
129
|
+
resetUnpublished: (state) => {
|
|
130
|
+
state.unpublishedData = [];
|
|
131
|
+
},
|
|
132
|
+
removeStyles(state, { payload }) {
|
|
133
|
+
const { [payload.id]: _, ...rest } = state.styles;
|
|
134
|
+
state.styles = rest;
|
|
135
|
+
},
|
|
136
|
+
addStyles: (state, { payload }) => {
|
|
137
|
+
state.styles = { ...state.styles, ...payload };
|
|
138
|
+
},
|
|
139
|
+
addCreatedThisSession: (state, { payload }) => {
|
|
140
|
+
state.createdThisSession.push(payload);
|
|
141
|
+
},
|
|
142
|
+
setCurrentComponentId: (state, { payload }) => {
|
|
143
|
+
state.currentComponentId = payload;
|
|
144
|
+
},
|
|
145
|
+
setPath: (state, { payload }) => {
|
|
146
|
+
state.path = payload;
|
|
147
|
+
},
|
|
148
|
+
setOverridableProps: (state, { payload }) => {
|
|
149
|
+
const component = state.data.find((comp) => comp.id === payload.componentId);
|
|
150
|
+
if (!component) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
component.overridableProps = payload.overridableProps;
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
extraReducers: (builder) => {
|
|
157
|
+
builder.addCase(loadComponents.fulfilled, (state, { payload }) => {
|
|
158
|
+
state.data = payload;
|
|
159
|
+
state.loadStatus = "idle";
|
|
160
|
+
});
|
|
161
|
+
builder.addCase(loadComponents.pending, (state) => {
|
|
162
|
+
state.loadStatus = "pending";
|
|
163
|
+
});
|
|
164
|
+
builder.addCase(loadComponents.rejected, (state) => {
|
|
165
|
+
state.loadStatus = "error";
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
var selectData = (state) => state[SLICE_NAME].data;
|
|
170
|
+
var selectLoadStatus = (state) => state[SLICE_NAME].loadStatus;
|
|
171
|
+
var selectStylesDefinitions = (state) => state[SLICE_NAME].styles ?? {};
|
|
172
|
+
var selectUnpublishedData = (state) => state[SLICE_NAME].unpublishedData;
|
|
173
|
+
var getCreatedThisSession = (state) => state[SLICE_NAME].createdThisSession;
|
|
174
|
+
var getPath = (state) => state[SLICE_NAME].path;
|
|
175
|
+
var getCurrentComponentId = (state) => state[SLICE_NAME].currentComponentId;
|
|
176
|
+
var selectComponent = (state, componentId) => state[SLICE_NAME].data.find((component) => component.id === componentId);
|
|
177
|
+
var selectComponents = (0, import_store2.__createSelector)(
|
|
178
|
+
selectData,
|
|
179
|
+
selectUnpublishedData,
|
|
180
|
+
(data, unpublishedData) => [
|
|
181
|
+
...unpublishedData.map((item) => ({ uid: item.uid, name: item.name })),
|
|
182
|
+
...data
|
|
183
|
+
]
|
|
184
|
+
);
|
|
185
|
+
var selectUnpublishedComponents = (0, import_store2.__createSelector)(
|
|
186
|
+
selectUnpublishedData,
|
|
187
|
+
(unpublishedData) => unpublishedData
|
|
188
|
+
);
|
|
189
|
+
var selectLoadIsPending = (0, import_store2.__createSelector)(selectLoadStatus, (status) => status === "pending");
|
|
190
|
+
var selectLoadIsError = (0, import_store2.__createSelector)(selectLoadStatus, (status) => status === "error");
|
|
191
|
+
var selectStyles = (state) => state[SLICE_NAME].styles ?? {};
|
|
192
|
+
var selectFlatStyles = (0, import_store2.__createSelector)(selectStylesDefinitions, (data) => Object.values(data).flat());
|
|
193
|
+
var selectCreatedThisSession = (0, import_store2.__createSelector)(
|
|
194
|
+
getCreatedThisSession,
|
|
195
|
+
(createdThisSession) => createdThisSession
|
|
196
|
+
);
|
|
197
|
+
var DEFAULT_OVERRIDABLE_PROPS = {
|
|
198
|
+
props: {},
|
|
199
|
+
groups: {
|
|
200
|
+
items: {},
|
|
201
|
+
order: []
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
var selectOverridableProps = (0, import_store2.__createSelector)(
|
|
205
|
+
selectComponent,
|
|
206
|
+
(component) => {
|
|
207
|
+
if (!component) {
|
|
208
|
+
return void 0;
|
|
209
|
+
}
|
|
210
|
+
return component.overridableProps ?? DEFAULT_OVERRIDABLE_PROPS;
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
var selectPath = (0, import_store2.__createSelector)(getPath, (path) => path);
|
|
214
|
+
var selectCurrentComponentId = (0, import_store2.__createSelector)(
|
|
215
|
+
getCurrentComponentId,
|
|
216
|
+
(currentComponentId) => currentComponentId
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
// src/utils/component-document-data.ts
|
|
220
|
+
var import_editor_documents = require("@elementor/editor-documents");
|
|
221
|
+
var getComponentDocumentData = async (id) => {
|
|
222
|
+
const documentManager = (0, import_editor_documents.getV1DocumentsManager)();
|
|
223
|
+
try {
|
|
224
|
+
return await documentManager.request(id);
|
|
225
|
+
} catch {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
var invalidateComponentDocumentData = (id) => {
|
|
230
|
+
const documentManager = (0, import_editor_documents.getV1DocumentsManager)();
|
|
231
|
+
documentManager.invalidateCache(id);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// src/component-instance-transformer.ts
|
|
235
|
+
var componentInstanceTransformer = (0, import_editor_canvas.createTransformer)(
|
|
236
|
+
async ({ component_id: id }) => {
|
|
237
|
+
const unpublishedComponents = selectUnpublishedComponents((0, import_store3.__getState)());
|
|
238
|
+
const unpublishedComponent = unpublishedComponents.find(({ uid }) => uid === id);
|
|
239
|
+
if (unpublishedComponent) {
|
|
240
|
+
return structuredClone(unpublishedComponent.elements);
|
|
241
|
+
}
|
|
242
|
+
if (typeof id !== "number") {
|
|
243
|
+
throw new Error(`Component ID "${id}" not found.`);
|
|
244
|
+
}
|
|
245
|
+
const data = await getComponentDocumentData(id);
|
|
246
|
+
return data?.elements ?? [];
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
// src/component-overridable-transformer.ts
|
|
251
|
+
var import_editor_canvas2 = require("@elementor/editor-canvas");
|
|
252
|
+
var componentOverridableTransformer = (0, import_editor_canvas2.createTransformer)(
|
|
253
|
+
async (value, options) => {
|
|
254
|
+
return await transformOriginValue(value, options);
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
async function transformOriginValue(value, options) {
|
|
258
|
+
if (!value.origin_value || !value.origin_value.value || !value.origin_value.$$type) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const transformer = import_editor_canvas2.settingsTransformersRegistry.get(value.origin_value.$$type);
|
|
262
|
+
if (!transformer) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
return await transformer(value.origin_value.value, options);
|
|
267
|
+
} catch {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/components/components-tab/components.tsx
|
|
273
|
+
var React6 = __toESM(require("react"));
|
|
274
|
+
var import_editor_ui = require("@elementor/editor-ui");
|
|
275
|
+
|
|
276
|
+
// src/components/components-tab/component-search.tsx
|
|
277
|
+
var React2 = __toESM(require("react"));
|
|
278
|
+
var import_icons = require("@elementor/icons");
|
|
279
|
+
var import_ui = require("@elementor/ui");
|
|
280
|
+
var import_i18n = require("@wordpress/i18n");
|
|
281
|
+
|
|
282
|
+
// src/components/components-tab/search-provider.tsx
|
|
283
|
+
var React = __toESM(require("react"));
|
|
284
|
+
var import_react = require("react");
|
|
285
|
+
var import_utils = require("@elementor/utils");
|
|
286
|
+
var SearchContext = (0, import_react.createContext)(void 0);
|
|
287
|
+
var SearchProvider = ({
|
|
288
|
+
children,
|
|
289
|
+
localStorageKey
|
|
290
|
+
}) => {
|
|
291
|
+
const { debouncedValue, handleChange, inputValue } = (0, import_utils.useSearchState)({ localStorageKey });
|
|
292
|
+
const clearSearch = () => {
|
|
293
|
+
handleChange("");
|
|
294
|
+
};
|
|
295
|
+
return /* @__PURE__ */ React.createElement(SearchContext.Provider, { value: { handleChange, clearSearch, searchValue: debouncedValue, inputValue } }, children);
|
|
296
|
+
};
|
|
297
|
+
var useSearch = () => {
|
|
298
|
+
const context = (0, import_react.useContext)(SearchContext);
|
|
299
|
+
if (!context) {
|
|
300
|
+
throw new Error("useSearch must be used within a SearchProvider");
|
|
301
|
+
}
|
|
302
|
+
return context;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// src/components/components-tab/component-search.tsx
|
|
306
|
+
var ComponentSearch = () => {
|
|
307
|
+
const { inputValue, handleChange } = useSearch();
|
|
308
|
+
return /* @__PURE__ */ React2.createElement(import_ui.Stack, { direction: "row", gap: 0.5, sx: { width: "100%", px: 2, py: 1.5 } }, /* @__PURE__ */ React2.createElement(import_ui.Box, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React2.createElement(
|
|
309
|
+
import_ui.TextField,
|
|
310
|
+
{
|
|
311
|
+
role: "search",
|
|
312
|
+
fullWidth: true,
|
|
313
|
+
size: "tiny",
|
|
314
|
+
value: inputValue,
|
|
315
|
+
placeholder: (0, import_i18n.__)("Search", "elementor"),
|
|
316
|
+
onChange: (e) => handleChange(e.target.value),
|
|
317
|
+
InputProps: {
|
|
318
|
+
startAdornment: /* @__PURE__ */ React2.createElement(import_ui.InputAdornment, { position: "start" }, /* @__PURE__ */ React2.createElement(import_icons.SearchIcon, { fontSize: "tiny" }))
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
)));
|
|
67
322
|
};
|
|
68
323
|
|
|
324
|
+
// src/components/components-tab/components-list.tsx
|
|
325
|
+
var React5 = __toESM(require("react"));
|
|
326
|
+
var import_icons3 = require("@elementor/icons");
|
|
327
|
+
var import_ui4 = require("@elementor/ui");
|
|
328
|
+
var import_i18n3 = require("@wordpress/i18n");
|
|
329
|
+
|
|
69
330
|
// src/hooks/use-components.ts
|
|
70
|
-
var
|
|
331
|
+
var import_store5 = require("@elementor/store");
|
|
71
332
|
var useComponents = () => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
333
|
+
const components = (0, import_store5.__useSelector)(selectComponents);
|
|
334
|
+
const isLoading = (0, import_store5.__useSelector)(selectLoadIsPending);
|
|
335
|
+
return { components, isLoading };
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// src/components/components-tab/components-item.tsx
|
|
339
|
+
var React3 = __toESM(require("react"));
|
|
340
|
+
var import_editor_canvas4 = require("@elementor/editor-canvas");
|
|
341
|
+
var import_editor_elements3 = require("@elementor/editor-elements");
|
|
342
|
+
var import_icons2 = require("@elementor/icons");
|
|
343
|
+
var import_ui2 = require("@elementor/ui");
|
|
344
|
+
|
|
345
|
+
// src/store/load-components-assets.ts
|
|
346
|
+
var import_editor_documents3 = require("@elementor/editor-documents");
|
|
347
|
+
|
|
348
|
+
// src/create-component-type.ts
|
|
349
|
+
var import_editor_canvas3 = require("@elementor/editor-canvas");
|
|
350
|
+
var import_editor_documents2 = require("@elementor/editor-documents");
|
|
351
|
+
var import_editor_v1_adapters2 = require("@elementor/editor-v1-adapters");
|
|
352
|
+
var import_i18n2 = require("@wordpress/i18n");
|
|
353
|
+
|
|
354
|
+
// src/utils/tracking.ts
|
|
355
|
+
var import_mixpanel = require("@elementor/mixpanel");
|
|
356
|
+
var import_store7 = require("@elementor/store");
|
|
357
|
+
var trackComponentEvent = ({ action, ...data }) => {
|
|
358
|
+
const { dispatchEvent, config } = (0, import_mixpanel.getMixpanel)();
|
|
359
|
+
if (!config?.names?.components?.[action]) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
const name = config.names.components[action];
|
|
363
|
+
dispatchEvent?.(name, data);
|
|
364
|
+
};
|
|
365
|
+
var onElementDrop = (_args, element) => {
|
|
366
|
+
if (!(element.model.get("widgetType") === "e-component")) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const editorSettings = element.model.get("editor_settings");
|
|
370
|
+
const componentName = editorSettings?.title;
|
|
371
|
+
const componentUID = editorSettings?.component_uid;
|
|
372
|
+
const instanceId = element.id;
|
|
373
|
+
const createdThisSession = selectCreatedThisSession((0, import_store7.__getState)());
|
|
374
|
+
const isSameSessionReuse = componentUID && createdThisSession.includes(componentUID);
|
|
375
|
+
const eventsManagerConfig = window.elementorCommon.eventsManager.config;
|
|
376
|
+
const { locations, secondaryLocations } = eventsManagerConfig;
|
|
377
|
+
trackComponentEvent({
|
|
378
|
+
action: "instanceAdded",
|
|
379
|
+
instance_id: instanceId,
|
|
380
|
+
component_uid: componentUID,
|
|
381
|
+
component_name: componentName,
|
|
382
|
+
is_same_session_reuse: isSameSessionReuse,
|
|
383
|
+
location: locations.widgetPanel,
|
|
384
|
+
secondary_location: secondaryLocations.componentsTab
|
|
76
385
|
});
|
|
77
386
|
};
|
|
78
387
|
|
|
79
|
-
// src/
|
|
80
|
-
var
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
return
|
|
84
|
-
|
|
85
|
-
|
|
388
|
+
// src/create-component-type.ts
|
|
389
|
+
var TYPE = "e-component";
|
|
390
|
+
function createComponentType(options) {
|
|
391
|
+
const legacyWindow = window;
|
|
392
|
+
return class extends legacyWindow.elementor.modules.elements.types.Widget {
|
|
393
|
+
getType() {
|
|
394
|
+
return options.type;
|
|
395
|
+
}
|
|
396
|
+
getView() {
|
|
397
|
+
return createComponentView(options);
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
function createComponentView(options) {
|
|
402
|
+
return class extends (0, import_editor_canvas3.createTemplatedElementView)(options) {
|
|
403
|
+
legacyWindow = window;
|
|
404
|
+
eventsManagerConfig = this.legacyWindow.elementorCommon.eventsManager.config;
|
|
405
|
+
isComponentCurrentlyEdited() {
|
|
406
|
+
const currentDocument = (0, import_editor_documents2.getCurrentDocument)();
|
|
407
|
+
return currentDocument?.id === this.getComponentId();
|
|
408
|
+
}
|
|
409
|
+
afterSettingsResolve(settings) {
|
|
410
|
+
if (settings.component_instance) {
|
|
411
|
+
this.collection = this.legacyWindow.elementor.createBackboneElementsCollection(
|
|
412
|
+
settings.component_instance
|
|
413
|
+
);
|
|
414
|
+
this.collection.models.forEach(setInactiveRecursively);
|
|
415
|
+
settings.component_instance = "<template data-children-placeholder></template>";
|
|
416
|
+
}
|
|
417
|
+
return settings;
|
|
418
|
+
}
|
|
419
|
+
getDomElement() {
|
|
420
|
+
return this.children.findByIndex(0)?.getDomElement() ?? this.$el;
|
|
421
|
+
}
|
|
422
|
+
attachBuffer(collectionView, buffer) {
|
|
423
|
+
const childrenPlaceholder = collectionView.$el.find("[data-children-placeholder]").get(0);
|
|
424
|
+
if (!childrenPlaceholder) {
|
|
425
|
+
super.attachBuffer(collectionView, buffer);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
childrenPlaceholder.replaceWith(buffer);
|
|
429
|
+
}
|
|
430
|
+
getComponentId() {
|
|
431
|
+
const componentInstance = this.options?.model?.get("settings")?.get("component_instance")?.value;
|
|
432
|
+
return componentInstance.component_id;
|
|
433
|
+
}
|
|
434
|
+
getContextMenuGroups() {
|
|
435
|
+
const filteredGroups = super.getContextMenuGroups().filter((group) => group.name !== "save");
|
|
436
|
+
const componentId = this.getComponentId();
|
|
437
|
+
if (!componentId) {
|
|
438
|
+
return filteredGroups;
|
|
439
|
+
}
|
|
440
|
+
const newGroup = [
|
|
441
|
+
{
|
|
442
|
+
name: "edit component",
|
|
443
|
+
actions: [
|
|
444
|
+
{
|
|
445
|
+
name: "edit component",
|
|
446
|
+
icon: "eicon-edit",
|
|
447
|
+
title: () => (0, import_i18n2.__)("Edit Component", "elementor"),
|
|
448
|
+
isEnabled: () => true,
|
|
449
|
+
callback: (_, eventData) => this.editComponent(eventData)
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
}
|
|
453
|
+
];
|
|
454
|
+
return [...filteredGroups, ...newGroup];
|
|
455
|
+
}
|
|
456
|
+
async switchDocument() {
|
|
457
|
+
const { isAllowedToSwitchDocument, lockedBy } = await apiClient.getComponentLockStatus(
|
|
458
|
+
this.getComponentId()
|
|
459
|
+
);
|
|
460
|
+
if (!isAllowedToSwitchDocument) {
|
|
461
|
+
options.showLockedByModal?.(lockedBy || "");
|
|
462
|
+
} else {
|
|
463
|
+
(0, import_editor_v1_adapters2.__privateRunCommand)("editor/documents/switch", {
|
|
464
|
+
id: this.getComponentId(),
|
|
465
|
+
mode: "autosave",
|
|
466
|
+
selector: `[data-id="${this.model.get("id")}"]`,
|
|
467
|
+
shouldScroll: false
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
editComponent({ trigger, location, secondaryLocation }) {
|
|
472
|
+
if (this.isComponentCurrentlyEdited()) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
this.switchDocument();
|
|
476
|
+
const editorSettings = this.model.get("editor_settings");
|
|
477
|
+
trackComponentEvent({
|
|
478
|
+
action: "edited",
|
|
479
|
+
component_uid: editorSettings?.component_uid,
|
|
480
|
+
component_name: editorSettings?.title,
|
|
481
|
+
location,
|
|
482
|
+
secondary_location: secondaryLocation,
|
|
483
|
+
trigger
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
handleDblClick(e) {
|
|
487
|
+
e.stopPropagation();
|
|
488
|
+
const { triggers, locations, secondaryLocations } = this.eventsManagerConfig;
|
|
489
|
+
this.editComponent({
|
|
490
|
+
trigger: triggers.doubleClick,
|
|
491
|
+
location: locations.canvas,
|
|
492
|
+
secondaryLocation: secondaryLocations.canvasElement
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
events() {
|
|
496
|
+
return {
|
|
497
|
+
...super.events(),
|
|
498
|
+
dblclick: this.handleDblClick
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
attributes() {
|
|
502
|
+
return {
|
|
503
|
+
...super.attributes(),
|
|
504
|
+
"data-elementor-id": this.getComponentId()
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function setInactiveRecursively(model) {
|
|
510
|
+
const editSettings = model.get("editSettings");
|
|
511
|
+
if (editSettings) {
|
|
512
|
+
editSettings.set("inactive", true);
|
|
513
|
+
}
|
|
514
|
+
const elements = model.get("elements");
|
|
515
|
+
if (elements) {
|
|
516
|
+
elements.forEach((childModel) => {
|
|
517
|
+
setInactiveRecursively(childModel);
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// src/utils/get-component-ids.ts
|
|
523
|
+
var getComponentIds = async (elements) => {
|
|
524
|
+
const components = elements.map(async ({ widgetType, elType, elements: childElements, settings }) => {
|
|
525
|
+
const ids = [];
|
|
526
|
+
const isComponent = [widgetType, elType].includes(TYPE);
|
|
527
|
+
if (isComponent) {
|
|
528
|
+
const componentId = settings?.component_instance?.value?.component_id;
|
|
529
|
+
const document = await getComponentDocumentData(componentId);
|
|
530
|
+
childElements = document?.elements;
|
|
531
|
+
if (Boolean(componentId)) {
|
|
532
|
+
ids.push(componentId);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (!!childElements?.length) {
|
|
536
|
+
ids.push(...await getComponentIds(childElements));
|
|
537
|
+
}
|
|
538
|
+
return ids;
|
|
539
|
+
});
|
|
540
|
+
const result = (await Promise.all(components)).flat();
|
|
541
|
+
return Array.from(new Set(result));
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// src/store/load-components-styles.ts
|
|
545
|
+
var import_store9 = require("@elementor/store");
|
|
546
|
+
async function loadComponentsStyles(componentIds) {
|
|
547
|
+
if (!componentIds.length) {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const knownComponents = selectStyles((0, import_store9.__getState)());
|
|
551
|
+
const unknownComponentIds = componentIds.filter((id) => !knownComponents[id]);
|
|
552
|
+
if (!unknownComponentIds.length) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
addComponentStyles(unknownComponentIds);
|
|
556
|
+
}
|
|
557
|
+
async function addComponentStyles(ids) {
|
|
558
|
+
const newComponents = await loadStyles(ids);
|
|
559
|
+
addStyles(newComponents);
|
|
560
|
+
}
|
|
561
|
+
async function loadStyles(ids) {
|
|
562
|
+
return Promise.all(ids.map(async (id) => [id, await apiClient.getComponentConfig(id)]));
|
|
563
|
+
}
|
|
564
|
+
function addStyles(data) {
|
|
565
|
+
const styles = Object.fromEntries(
|
|
566
|
+
data.map(([componentId, componentData]) => [componentId, extractStyles(componentData)])
|
|
567
|
+
);
|
|
568
|
+
(0, import_store9.__dispatch)(slice.actions.addStyles(styles));
|
|
569
|
+
}
|
|
570
|
+
function extractStyles(element) {
|
|
571
|
+
return [...Object.values(element.styles ?? {}), ...(element.elements ?? []).flatMap(extractStyles)];
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// src/store/load-components-assets.ts
|
|
575
|
+
async function loadComponentsAssets(elements) {
|
|
576
|
+
const componentIds = await getComponentIds(elements);
|
|
577
|
+
updateDocumentState(componentIds);
|
|
578
|
+
return loadComponentsStyles(componentIds);
|
|
579
|
+
}
|
|
580
|
+
async function updateDocumentState(componentIds) {
|
|
581
|
+
const components = (await Promise.all(componentIds.map(getComponentDocumentData))).filter(
|
|
582
|
+
(document) => !!document
|
|
583
|
+
);
|
|
584
|
+
const isDrafted = components.some(import_editor_documents3.isDocumentDirty);
|
|
585
|
+
if (isDrafted) {
|
|
586
|
+
(0, import_editor_documents3.setDocumentModifiedStatus)(true);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// src/utils/get-container-for-new-element.ts
|
|
591
|
+
var import_editor_elements = require("@elementor/editor-elements");
|
|
592
|
+
var getContainerForNewElement = () => {
|
|
593
|
+
const currentDocumentContainer = (0, import_editor_elements.getCurrentDocumentContainer)();
|
|
594
|
+
const selectedElement = getSelectedElementContainer();
|
|
595
|
+
let container, options;
|
|
596
|
+
if (selectedElement) {
|
|
597
|
+
switch (selectedElement.model.get("elType")) {
|
|
598
|
+
case "widget": {
|
|
599
|
+
container = selectedElement?.parent;
|
|
600
|
+
const selectedElIndex = selectedElement.view?._index ?? -1;
|
|
601
|
+
if (selectedElIndex > -1) {
|
|
602
|
+
options = { at: selectedElIndex + 1 };
|
|
603
|
+
}
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
case "section": {
|
|
607
|
+
container = selectedElement?.children?.[0];
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
default: {
|
|
611
|
+
container = selectedElement;
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return { container: container ?? currentDocumentContainer, options };
|
|
617
|
+
};
|
|
618
|
+
function getSelectedElementContainer() {
|
|
619
|
+
const selectedElements = (0, import_editor_elements.getSelectedElements)();
|
|
620
|
+
if (selectedElements.length !== 1) {
|
|
621
|
+
return void 0;
|
|
622
|
+
}
|
|
623
|
+
return (0, import_editor_elements.getContainer)(selectedElements[0].id);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// src/components/create-component-form/utils/replace-element-with-component.ts
|
|
627
|
+
var import_editor_elements2 = require("@elementor/editor-elements");
|
|
628
|
+
var replaceElementWithComponent = (element, component) => {
|
|
629
|
+
(0, import_editor_elements2.replaceElement)({
|
|
630
|
+
currentElement: element,
|
|
631
|
+
newElement: createComponentModel(component),
|
|
632
|
+
withHistory: false
|
|
633
|
+
});
|
|
634
|
+
};
|
|
635
|
+
var createComponentModel = (component) => {
|
|
636
|
+
return {
|
|
637
|
+
elType: "widget",
|
|
638
|
+
widgetType: "e-component",
|
|
639
|
+
settings: {
|
|
640
|
+
component_instance: {
|
|
641
|
+
$$type: "component-instance",
|
|
642
|
+
value: {
|
|
643
|
+
component_id: component.id ?? component.uid
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
editor_settings: {
|
|
648
|
+
title: component.name,
|
|
649
|
+
component_uid: component.uid
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
// src/components/components-tab/components-item.tsx
|
|
655
|
+
var ComponentItem = ({ component }) => {
|
|
656
|
+
const componentModel = createComponentModel(component);
|
|
657
|
+
const handleClick = () => {
|
|
658
|
+
addComponentToPage(componentModel);
|
|
659
|
+
};
|
|
660
|
+
const handleDragEnd = () => {
|
|
661
|
+
loadComponentsAssets([componentModel]);
|
|
662
|
+
(0, import_editor_canvas4.endDragElementFromPanel)();
|
|
663
|
+
};
|
|
664
|
+
return /* @__PURE__ */ React3.createElement(
|
|
665
|
+
import_ui2.ListItemButton,
|
|
666
|
+
{
|
|
667
|
+
draggable: true,
|
|
668
|
+
onDragStart: () => (0, import_editor_canvas4.startDragElementFromPanel)(componentModel),
|
|
669
|
+
onDragEnd: handleDragEnd,
|
|
670
|
+
shape: "rounded",
|
|
671
|
+
sx: { border: "solid 1px", borderColor: "divider", py: 0.5, px: 1 }
|
|
672
|
+
},
|
|
673
|
+
/* @__PURE__ */ React3.createElement(import_ui2.Box, { sx: { display: "flex", width: "100%", alignItems: "center", gap: 1 }, onClick: handleClick }, /* @__PURE__ */ React3.createElement(import_ui2.ListItemIcon, { size: "tiny" }, /* @__PURE__ */ React3.createElement(import_icons2.ComponentsIcon, { fontSize: "tiny" })), /* @__PURE__ */ React3.createElement(
|
|
674
|
+
import_ui2.ListItemText,
|
|
675
|
+
{
|
|
676
|
+
primary: /* @__PURE__ */ React3.createElement(import_ui2.Typography, { variant: "caption", sx: { color: "text.primary" } }, component.name)
|
|
677
|
+
}
|
|
678
|
+
))
|
|
679
|
+
);
|
|
680
|
+
};
|
|
681
|
+
var addComponentToPage = (model) => {
|
|
682
|
+
const { container, options } = getContainerForNewElement();
|
|
683
|
+
if (!container) {
|
|
684
|
+
throw new Error(`Can't find container to drop new component instance at`);
|
|
685
|
+
}
|
|
686
|
+
loadComponentsAssets([model]);
|
|
687
|
+
(0, import_editor_elements3.dropElement)({
|
|
688
|
+
containerId: container.id,
|
|
689
|
+
model,
|
|
690
|
+
options: { ...options, useHistory: false, scrollIntoView: true }
|
|
86
691
|
});
|
|
87
692
|
};
|
|
88
693
|
|
|
694
|
+
// src/components/components-tab/loading-components.tsx
|
|
695
|
+
var React4 = __toESM(require("react"));
|
|
696
|
+
var import_ui3 = require("@elementor/ui");
|
|
697
|
+
var ROWS_COUNT = 6;
|
|
698
|
+
var rows = Array.from({ length: ROWS_COUNT }, (_, index) => index);
|
|
699
|
+
var LoadingComponents = () => {
|
|
700
|
+
return /* @__PURE__ */ React4.createElement(
|
|
701
|
+
import_ui3.Stack,
|
|
702
|
+
{
|
|
703
|
+
"aria-label": "Loading components",
|
|
704
|
+
gap: 1,
|
|
705
|
+
sx: {
|
|
706
|
+
pointerEvents: "none",
|
|
707
|
+
position: "relative",
|
|
708
|
+
maxHeight: "300px",
|
|
709
|
+
overflow: "hidden",
|
|
710
|
+
"&:after": {
|
|
711
|
+
position: "absolute",
|
|
712
|
+
top: 0,
|
|
713
|
+
content: '""',
|
|
714
|
+
left: 0,
|
|
715
|
+
width: "100%",
|
|
716
|
+
height: "300px",
|
|
717
|
+
background: "linear-gradient(to top, white, transparent)",
|
|
718
|
+
pointerEvents: "none"
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
},
|
|
722
|
+
rows.map((row) => /* @__PURE__ */ React4.createElement(
|
|
723
|
+
import_ui3.ListItemButton,
|
|
724
|
+
{
|
|
725
|
+
key: row,
|
|
726
|
+
sx: { border: "solid 1px", borderColor: "divider", py: 0.5, px: 1 },
|
|
727
|
+
shape: "rounded"
|
|
728
|
+
},
|
|
729
|
+
/* @__PURE__ */ React4.createElement(import_ui3.Box, { display: "flex", gap: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(import_ui3.Skeleton, { variant: "text", width: "24px", height: "36px" }), /* @__PURE__ */ React4.createElement(import_ui3.Skeleton, { variant: "text", width: "100%", height: "36px" }))
|
|
730
|
+
))
|
|
731
|
+
);
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
// src/components/components-tab/components-list.tsx
|
|
735
|
+
function ComponentsList() {
|
|
736
|
+
const { components, isLoading, searchValue } = useFilteredComponents();
|
|
737
|
+
if (isLoading) {
|
|
738
|
+
return /* @__PURE__ */ React5.createElement(LoadingComponents, null);
|
|
739
|
+
}
|
|
740
|
+
const isEmpty = !components || components.length === 0;
|
|
741
|
+
if (isEmpty) {
|
|
742
|
+
if (searchValue.length > 0) {
|
|
743
|
+
return /* @__PURE__ */ React5.createElement(EmptySearchResult, null);
|
|
744
|
+
}
|
|
745
|
+
return /* @__PURE__ */ React5.createElement(EmptyState, null);
|
|
746
|
+
}
|
|
747
|
+
return /* @__PURE__ */ React5.createElement(import_ui4.List, { sx: { display: "flex", flexDirection: "column", gap: 1, px: 2 } }, components.map((component) => /* @__PURE__ */ React5.createElement(ComponentItem, { key: component.uid, component })));
|
|
748
|
+
}
|
|
749
|
+
var EmptyState = () => {
|
|
750
|
+
return /* @__PURE__ */ React5.createElement(
|
|
751
|
+
import_ui4.Stack,
|
|
752
|
+
{
|
|
753
|
+
alignItems: "center",
|
|
754
|
+
justifyContent: "center",
|
|
755
|
+
height: "100%",
|
|
756
|
+
sx: { px: 2.5, pt: 10 },
|
|
757
|
+
gap: 1.75,
|
|
758
|
+
overflow: "hidden"
|
|
759
|
+
},
|
|
760
|
+
/* @__PURE__ */ React5.createElement(import_ui4.Icon, { fontSize: "large" }, /* @__PURE__ */ React5.createElement(import_icons3.EyeIcon, { fontSize: "large" })),
|
|
761
|
+
/* @__PURE__ */ React5.createElement(import_ui4.Typography, { align: "center", variant: "subtitle2", color: "text.secondary", fontWeight: "bold" }, (0, import_i18n3.__)("Text that explains that there are no Components yet.", "elementor")),
|
|
762
|
+
/* @__PURE__ */ React5.createElement(import_ui4.Typography, { variant: "caption", align: "center", color: "text.secondary" }, (0, import_i18n3.__)(
|
|
763
|
+
"Once you have Components, this is where you can manage them\u2014rearrange, duplicate, rename and delete irrelevant classes.",
|
|
764
|
+
"elementor"
|
|
765
|
+
)),
|
|
766
|
+
/* @__PURE__ */ React5.createElement(import_ui4.Divider, { sx: { width: "100%" }, color: "text.secondary" }),
|
|
767
|
+
/* @__PURE__ */ React5.createElement(import_ui4.Typography, { align: "left", variant: "caption", color: "text.secondary" }, (0, import_i18n3.__)("To create a component, first design it, then choose one of three options:", "elementor")),
|
|
768
|
+
/* @__PURE__ */ React5.createElement(
|
|
769
|
+
import_ui4.Typography,
|
|
770
|
+
{
|
|
771
|
+
align: "left",
|
|
772
|
+
variant: "caption",
|
|
773
|
+
color: "text.secondary",
|
|
774
|
+
sx: { display: "flex", flexDirection: "column" }
|
|
775
|
+
},
|
|
776
|
+
/* @__PURE__ */ React5.createElement("span", null, (0, import_i18n3.__)("1. Right-click and select Create Component", "elementor")),
|
|
777
|
+
/* @__PURE__ */ React5.createElement("span", null, (0, import_i18n3.__)("2. Use the component icon in the Structure panel", "elementor")),
|
|
778
|
+
/* @__PURE__ */ React5.createElement("span", null, (0, import_i18n3.__)("3. Use the component icon in the Edit panel header", "elementor"))
|
|
779
|
+
)
|
|
780
|
+
);
|
|
781
|
+
};
|
|
782
|
+
var EmptySearchResult = () => {
|
|
783
|
+
const { searchValue, clearSearch } = useSearch();
|
|
784
|
+
return /* @__PURE__ */ React5.createElement(
|
|
785
|
+
import_ui4.Stack,
|
|
786
|
+
{
|
|
787
|
+
color: "text.secondary",
|
|
788
|
+
pt: 5,
|
|
789
|
+
alignItems: "center",
|
|
790
|
+
gap: 1,
|
|
791
|
+
overflow: "hidden",
|
|
792
|
+
justifySelf: "center"
|
|
793
|
+
},
|
|
794
|
+
/* @__PURE__ */ React5.createElement(import_icons3.ComponentsIcon, null),
|
|
795
|
+
/* @__PURE__ */ React5.createElement(
|
|
796
|
+
import_ui4.Box,
|
|
797
|
+
{
|
|
798
|
+
sx: {
|
|
799
|
+
width: "100%"
|
|
800
|
+
}
|
|
801
|
+
},
|
|
802
|
+
/* @__PURE__ */ React5.createElement(import_ui4.Typography, { align: "center", variant: "subtitle2", color: "inherit" }, (0, import_i18n3.__)("Sorry, nothing matched", "elementor")),
|
|
803
|
+
searchValue && /* @__PURE__ */ React5.createElement(
|
|
804
|
+
import_ui4.Typography,
|
|
805
|
+
{
|
|
806
|
+
variant: "subtitle2",
|
|
807
|
+
color: "inherit",
|
|
808
|
+
sx: {
|
|
809
|
+
display: "flex",
|
|
810
|
+
width: "100%",
|
|
811
|
+
justifyContent: "center"
|
|
812
|
+
}
|
|
813
|
+
},
|
|
814
|
+
/* @__PURE__ */ React5.createElement("span", null, "\u201C"),
|
|
815
|
+
/* @__PURE__ */ React5.createElement(
|
|
816
|
+
"span",
|
|
817
|
+
{
|
|
818
|
+
style: {
|
|
819
|
+
maxWidth: "80%",
|
|
820
|
+
overflow: "hidden",
|
|
821
|
+
textOverflow: "ellipsis"
|
|
822
|
+
}
|
|
823
|
+
},
|
|
824
|
+
searchValue
|
|
825
|
+
),
|
|
826
|
+
/* @__PURE__ */ React5.createElement("span", null, "\u201D.")
|
|
827
|
+
)
|
|
828
|
+
),
|
|
829
|
+
/* @__PURE__ */ React5.createElement(import_ui4.Typography, { align: "center", variant: "caption", color: "inherit" }, (0, import_i18n3.__)("Try something else.", "elementor")),
|
|
830
|
+
/* @__PURE__ */ React5.createElement(import_ui4.Typography, { align: "center", variant: "caption", color: "inherit" }, /* @__PURE__ */ React5.createElement(import_ui4.Link, { color: "secondary", variant: "caption", component: "button", onClick: clearSearch }, (0, import_i18n3.__)("Clear & try again", "elementor")))
|
|
831
|
+
);
|
|
832
|
+
};
|
|
833
|
+
var useFilteredComponents = () => {
|
|
834
|
+
const { components, isLoading } = useComponents();
|
|
835
|
+
const { searchValue } = useSearch();
|
|
836
|
+
return {
|
|
837
|
+
components: components.filter(
|
|
838
|
+
(component) => component.name.toLowerCase().includes(searchValue.toLowerCase())
|
|
839
|
+
),
|
|
840
|
+
isLoading,
|
|
841
|
+
searchValue
|
|
842
|
+
};
|
|
843
|
+
};
|
|
844
|
+
|
|
845
|
+
// src/components/components-tab/components.tsx
|
|
846
|
+
var Components = () => {
|
|
847
|
+
return /* @__PURE__ */ React6.createElement(import_editor_ui.ThemeProvider, null, /* @__PURE__ */ React6.createElement(SearchProvider, { localStorageKey: "elementor-components-search" }, /* @__PURE__ */ React6.createElement(ComponentSearch, null), /* @__PURE__ */ React6.createElement(ComponentsList, null)));
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
// src/components/consts.ts
|
|
851
|
+
var COMPONENT_DOCUMENT_TYPE = "elementor_component";
|
|
852
|
+
|
|
853
|
+
// src/components/create-component-form/create-component-form.tsx
|
|
854
|
+
var React7 = __toESM(require("react"));
|
|
855
|
+
var import_react3 = require("react");
|
|
856
|
+
var import_editor_elements4 = require("@elementor/editor-elements");
|
|
857
|
+
var import_editor_ui2 = require("@elementor/editor-ui");
|
|
858
|
+
var import_icons4 = require("@elementor/icons");
|
|
859
|
+
var import_ui5 = require("@elementor/ui");
|
|
860
|
+
var import_i18n5 = require("@wordpress/i18n");
|
|
861
|
+
|
|
862
|
+
// src/store/create-unpublished-component.ts
|
|
863
|
+
var import_editor_v1_adapters3 = require("@elementor/editor-v1-adapters");
|
|
864
|
+
var import_store11 = require("@elementor/store");
|
|
865
|
+
var import_utils2 = require("@elementor/utils");
|
|
866
|
+
function createUnpublishedComponent(name, element, eventData) {
|
|
867
|
+
const uid = (0, import_utils2.generateUniqueId)("component");
|
|
868
|
+
const componentBase = { uid, name };
|
|
869
|
+
(0, import_store11.__dispatch)(
|
|
870
|
+
slice.actions.addUnpublished({
|
|
871
|
+
...componentBase,
|
|
872
|
+
elements: [element]
|
|
873
|
+
})
|
|
874
|
+
);
|
|
875
|
+
(0, import_store11.__dispatch)(slice.actions.addCreatedThisSession(uid));
|
|
876
|
+
replaceElementWithComponent(element, componentBase);
|
|
877
|
+
trackComponentEvent({
|
|
878
|
+
action: "created",
|
|
879
|
+
component_uid: uid,
|
|
880
|
+
component_name: name,
|
|
881
|
+
...eventData
|
|
882
|
+
});
|
|
883
|
+
(0, import_editor_v1_adapters3.__privateRunCommand)("document/save/auto");
|
|
884
|
+
return uid;
|
|
885
|
+
}
|
|
886
|
+
|
|
89
887
|
// src/components/create-component-form/hooks/use-form.ts
|
|
90
|
-
var
|
|
888
|
+
var import_react2 = require("react");
|
|
91
889
|
var useForm = (initialValues) => {
|
|
92
|
-
const [values, setValues] = (0,
|
|
93
|
-
const [errors, setErrors] = (0,
|
|
94
|
-
const isValid = (0,
|
|
890
|
+
const [values, setValues] = (0, import_react2.useState)(initialValues);
|
|
891
|
+
const [errors, setErrors] = (0, import_react2.useState)({});
|
|
892
|
+
const isValid = (0, import_react2.useMemo)(() => {
|
|
95
893
|
return !Object.values(errors).some((error) => error);
|
|
96
894
|
}, [errors]);
|
|
97
895
|
const handleChange = (e, field, validationSchema) => {
|
|
@@ -137,16 +935,16 @@ var validateForm = (values, schema) => {
|
|
|
137
935
|
|
|
138
936
|
// src/components/create-component-form/utils/component-form-schema.ts
|
|
139
937
|
var import_schema = require("@elementor/schema");
|
|
140
|
-
var
|
|
938
|
+
var import_i18n4 = require("@wordpress/i18n");
|
|
141
939
|
var MIN_NAME_LENGTH = 2;
|
|
142
940
|
var MAX_NAME_LENGTH = 50;
|
|
143
941
|
var createBaseComponentSchema = (existingNames) => {
|
|
144
942
|
return import_schema.z.object({
|
|
145
943
|
componentName: import_schema.z.string().trim().max(
|
|
146
944
|
MAX_NAME_LENGTH,
|
|
147
|
-
(0,
|
|
945
|
+
(0, import_i18n4.__)("Component name is too long. Please keep it under 50 characters.", "elementor")
|
|
148
946
|
).refine((value) => !existingNames.includes(value), {
|
|
149
|
-
message: (0,
|
|
947
|
+
message: (0, import_i18n4.__)("Component name already exists", "elementor")
|
|
150
948
|
})
|
|
151
949
|
});
|
|
152
950
|
};
|
|
@@ -154,104 +952,115 @@ var createSubmitComponentSchema = (existingNames) => {
|
|
|
154
952
|
const baseSchema = createBaseComponentSchema(existingNames);
|
|
155
953
|
return baseSchema.extend({
|
|
156
954
|
componentName: baseSchema.shape.componentName.refine((value) => value.length > 0, {
|
|
157
|
-
message: (0,
|
|
955
|
+
message: (0, import_i18n4.__)("Component name is required.", "elementor")
|
|
158
956
|
}).refine((value) => value.length >= MIN_NAME_LENGTH, {
|
|
159
|
-
message: (0,
|
|
957
|
+
message: (0, import_i18n4.__)("Component name is too short. Please enter at least 2 characters.", "elementor")
|
|
160
958
|
})
|
|
161
959
|
});
|
|
162
960
|
};
|
|
163
961
|
|
|
164
|
-
// src/components/create-component-form/utils/
|
|
165
|
-
var
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
withHistory: false
|
|
178
|
-
});
|
|
962
|
+
// src/components/create-component-form/utils/get-component-event-data.ts
|
|
963
|
+
var getComponentEventData = (containerElement, options) => {
|
|
964
|
+
const { elementsCount, componentsCount } = countNestedElements(containerElement);
|
|
965
|
+
return {
|
|
966
|
+
nested_elements_count: elementsCount,
|
|
967
|
+
nested_components_count: componentsCount,
|
|
968
|
+
top_element_type: containerElement.elType,
|
|
969
|
+
location: options?.location,
|
|
970
|
+
secondary_location: options?.secondaryLocation,
|
|
971
|
+
trigger: options?.trigger
|
|
972
|
+
};
|
|
179
973
|
};
|
|
974
|
+
function countNestedElements(container) {
|
|
975
|
+
if (!container.elements || container.elements.length === 0) {
|
|
976
|
+
return { elementsCount: 0, componentsCount: 0 };
|
|
977
|
+
}
|
|
978
|
+
let elementsCount = container.elements.length;
|
|
979
|
+
let componentsCount = 0;
|
|
980
|
+
for (const element of container.elements) {
|
|
981
|
+
if (element.widgetType === "e-component") {
|
|
982
|
+
componentsCount++;
|
|
983
|
+
}
|
|
984
|
+
const { elementsCount: nestedElementsCount, componentsCount: nestedComponentsCount } = countNestedElements(element);
|
|
985
|
+
elementsCount += nestedElementsCount;
|
|
986
|
+
componentsCount += nestedComponentsCount;
|
|
987
|
+
}
|
|
988
|
+
return { elementsCount, componentsCount };
|
|
989
|
+
}
|
|
180
990
|
|
|
181
991
|
// src/components/create-component-form/create-component-form.tsx
|
|
182
992
|
function CreateComponentForm() {
|
|
183
|
-
const [element, setElement] = (0,
|
|
184
|
-
const [anchorPosition, setAnchorPosition] = (0,
|
|
185
|
-
const [resultNotification, setResultNotification] = (0,
|
|
186
|
-
const
|
|
187
|
-
(0,
|
|
993
|
+
const [element, setElement] = (0, import_react3.useState)(null);
|
|
994
|
+
const [anchorPosition, setAnchorPosition] = (0, import_react3.useState)();
|
|
995
|
+
const [resultNotification, setResultNotification] = (0, import_react3.useState)(null);
|
|
996
|
+
const eventData = (0, import_react3.useRef)(null);
|
|
997
|
+
(0, import_react3.useEffect)(() => {
|
|
188
998
|
const OPEN_SAVE_AS_COMPONENT_FORM_EVENT = "elementor/editor/open-save-as-component-form";
|
|
189
999
|
const openPopup = (event) => {
|
|
190
|
-
setElement({ element: event.detail.element, elementLabel: (0,
|
|
1000
|
+
setElement({ element: event.detail.element, elementLabel: (0, import_editor_elements4.getElementLabel)(event.detail.element.id) });
|
|
191
1001
|
setAnchorPosition(event.detail.anchorPosition);
|
|
1002
|
+
eventData.current = getComponentEventData(event.detail.element, event.detail.options);
|
|
1003
|
+
trackComponentEvent({
|
|
1004
|
+
action: "createClicked",
|
|
1005
|
+
...eventData.current
|
|
1006
|
+
});
|
|
192
1007
|
};
|
|
193
1008
|
window.addEventListener(OPEN_SAVE_AS_COMPONENT_FORM_EVENT, openPopup);
|
|
194
1009
|
return () => {
|
|
195
1010
|
window.removeEventListener(OPEN_SAVE_AS_COMPONENT_FORM_EVENT, openPopup);
|
|
196
1011
|
};
|
|
197
1012
|
}, []);
|
|
198
|
-
const handleSave =
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
createComponent(
|
|
203
|
-
{
|
|
204
|
-
name: values.componentName,
|
|
205
|
-
content: [element.element.model.toJSON({ remove: ["default"] })]
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
onSuccess: (result) => {
|
|
209
|
-
if (!element) {
|
|
210
|
-
throw new Error(`Can't replace element with component: element not found`);
|
|
211
|
-
}
|
|
212
|
-
replaceElementWithComponent(element.element, result.component_id);
|
|
213
|
-
setResultNotification({
|
|
214
|
-
show: true,
|
|
215
|
-
// Translators: %1$s: Component name, %2$s: Component ID
|
|
216
|
-
message: (0, import_i18n2.__)("Component saved successfully as: %1$s (ID: %2$s)", "elementor").replace("%1$s", values.componentName).replace("%2$s", result.component_id.toString()),
|
|
217
|
-
type: "success"
|
|
218
|
-
});
|
|
219
|
-
resetAndClosePopup();
|
|
220
|
-
},
|
|
221
|
-
onError: () => {
|
|
222
|
-
const errorMessage = (0, import_i18n2.__)("Failed to save component. Please try again.", "elementor");
|
|
223
|
-
setResultNotification({
|
|
224
|
-
show: true,
|
|
225
|
-
message: errorMessage,
|
|
226
|
-
type: "error"
|
|
227
|
-
});
|
|
228
|
-
}
|
|
1013
|
+
const handleSave = (values) => {
|
|
1014
|
+
try {
|
|
1015
|
+
if (!element) {
|
|
1016
|
+
throw new Error(`Can't save element as component: element not found`);
|
|
229
1017
|
}
|
|
230
|
-
|
|
1018
|
+
const uid = createUnpublishedComponent(values.componentName, element.element, eventData.current);
|
|
1019
|
+
setResultNotification({
|
|
1020
|
+
show: true,
|
|
1021
|
+
// Translators: %1$s: Component name, %2$s: Component UID
|
|
1022
|
+
message: (0, import_i18n5.__)("Component saved successfully as: %1$s (UID: %2$s)", "elementor").replace("%1$s", values.componentName).replace("%2$s", uid),
|
|
1023
|
+
type: "success"
|
|
1024
|
+
});
|
|
1025
|
+
resetAndClosePopup();
|
|
1026
|
+
} catch {
|
|
1027
|
+
const errorMessage = (0, import_i18n5.__)("Failed to save component. Please try again.", "elementor");
|
|
1028
|
+
setResultNotification({
|
|
1029
|
+
show: true,
|
|
1030
|
+
message: errorMessage,
|
|
1031
|
+
type: "error"
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
231
1034
|
};
|
|
232
1035
|
const resetAndClosePopup = () => {
|
|
233
1036
|
setElement(null);
|
|
234
1037
|
setAnchorPosition(void 0);
|
|
235
1038
|
};
|
|
236
|
-
|
|
237
|
-
|
|
1039
|
+
const cancelSave = () => {
|
|
1040
|
+
resetAndClosePopup();
|
|
1041
|
+
trackComponentEvent({
|
|
1042
|
+
action: "createCancelled",
|
|
1043
|
+
...eventData.current
|
|
1044
|
+
});
|
|
1045
|
+
};
|
|
1046
|
+
return /* @__PURE__ */ React7.createElement(import_editor_ui2.ThemeProvider, null, /* @__PURE__ */ React7.createElement(
|
|
1047
|
+
import_ui5.Popover,
|
|
238
1048
|
{
|
|
239
1049
|
open: element !== null,
|
|
240
|
-
onClose:
|
|
1050
|
+
onClose: cancelSave,
|
|
241
1051
|
anchorReference: "anchorPosition",
|
|
242
1052
|
anchorPosition
|
|
243
1053
|
},
|
|
244
|
-
element !== null && /* @__PURE__ */
|
|
1054
|
+
element !== null && /* @__PURE__ */ React7.createElement(
|
|
245
1055
|
Form,
|
|
246
1056
|
{
|
|
247
1057
|
initialValues: { componentName: element.elementLabel },
|
|
248
1058
|
handleSave,
|
|
249
|
-
|
|
250
|
-
closePopup: resetAndClosePopup
|
|
1059
|
+
closePopup: cancelSave
|
|
251
1060
|
}
|
|
252
1061
|
)
|
|
253
|
-
), /* @__PURE__ */
|
|
254
|
-
|
|
1062
|
+
), /* @__PURE__ */ React7.createElement(import_ui5.Snackbar, { open: resultNotification?.show, onClose: () => setResultNotification(null) }, /* @__PURE__ */ React7.createElement(
|
|
1063
|
+
import_ui5.Alert,
|
|
255
1064
|
{
|
|
256
1065
|
onClose: () => setResultNotification(null),
|
|
257
1066
|
severity: resultNotification?.type,
|
|
@@ -264,19 +1073,18 @@ var FONT_SIZE = "tiny";
|
|
|
264
1073
|
var Form = ({
|
|
265
1074
|
initialValues,
|
|
266
1075
|
handleSave,
|
|
267
|
-
isSubmitting,
|
|
268
1076
|
closePopup
|
|
269
1077
|
}) => {
|
|
270
1078
|
const { values, errors, isValid, handleChange, validateForm: validateForm2 } = useForm(initialValues);
|
|
271
|
-
const {
|
|
272
|
-
const existingComponentNames = (0,
|
|
1079
|
+
const { components } = useComponents();
|
|
1080
|
+
const existingComponentNames = (0, import_react3.useMemo)(() => {
|
|
273
1081
|
return components?.map((component) => component.name) ?? [];
|
|
274
1082
|
}, [components]);
|
|
275
|
-
const changeValidationSchema = (0,
|
|
1083
|
+
const changeValidationSchema = (0, import_react3.useMemo)(
|
|
276
1084
|
() => createBaseComponentSchema(existingComponentNames),
|
|
277
1085
|
[existingComponentNames]
|
|
278
1086
|
);
|
|
279
|
-
const submitValidationSchema = (0,
|
|
1087
|
+
const submitValidationSchema = (0, import_react3.useMemo)(
|
|
280
1088
|
() => createSubmitComponentSchema(existingComponentNames),
|
|
281
1089
|
[existingComponentNames]
|
|
282
1090
|
);
|
|
@@ -286,8 +1094,15 @@ var Form = ({
|
|
|
286
1094
|
handleSave(parsedValues);
|
|
287
1095
|
}
|
|
288
1096
|
};
|
|
289
|
-
|
|
290
|
-
|
|
1097
|
+
const texts = {
|
|
1098
|
+
heading: (0, import_i18n5.__)("Save as a component", "elementor"),
|
|
1099
|
+
name: (0, import_i18n5.__)("Name", "elementor"),
|
|
1100
|
+
cancel: (0, import_i18n5.__)("Cancel", "elementor"),
|
|
1101
|
+
create: (0, import_i18n5.__)("Create", "elementor")
|
|
1102
|
+
};
|
|
1103
|
+
const nameInputId = "component-name";
|
|
1104
|
+
return /* @__PURE__ */ React7.createElement(import_editor_ui2.Form, { onSubmit: handleSubmit }, /* @__PURE__ */ React7.createElement(import_ui5.Stack, { alignItems: "start", width: "268px" }, /* @__PURE__ */ React7.createElement(
|
|
1105
|
+
import_ui5.Stack,
|
|
291
1106
|
{
|
|
292
1107
|
direction: "row",
|
|
293
1108
|
alignItems: "center",
|
|
@@ -295,12 +1110,12 @@ var Form = ({
|
|
|
295
1110
|
px: 1.5,
|
|
296
1111
|
sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%" }
|
|
297
1112
|
},
|
|
298
|
-
/* @__PURE__ */
|
|
299
|
-
/* @__PURE__ */
|
|
300
|
-
), /* @__PURE__ */
|
|
301
|
-
|
|
1113
|
+
/* @__PURE__ */ React7.createElement(import_icons4.StarIcon, { fontSize: FONT_SIZE }),
|
|
1114
|
+
/* @__PURE__ */ React7.createElement(import_ui5.Typography, { variant: "caption", sx: { color: "text.primary", fontWeight: "500", lineHeight: 1 } }, texts.heading)
|
|
1115
|
+
), /* @__PURE__ */ React7.createElement(import_ui5.Grid, { container: true, gap: 0.75, alignItems: "start", p: 1.5 }, /* @__PURE__ */ React7.createElement(import_ui5.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React7.createElement(import_ui5.FormLabel, { htmlFor: nameInputId, size: "tiny" }, texts.name)), /* @__PURE__ */ React7.createElement(import_ui5.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React7.createElement(
|
|
1116
|
+
import_ui5.TextField,
|
|
302
1117
|
{
|
|
303
|
-
id:
|
|
1118
|
+
id: nameInputId,
|
|
304
1119
|
size: FONT_SIZE,
|
|
305
1120
|
fullWidth: true,
|
|
306
1121
|
value: values.componentName,
|
|
@@ -309,30 +1124,952 @@ var Form = ({
|
|
|
309
1124
|
error: Boolean(errors.componentName),
|
|
310
1125
|
helperText: errors.componentName
|
|
311
1126
|
}
|
|
312
|
-
))), /* @__PURE__ */
|
|
313
|
-
|
|
1127
|
+
))), /* @__PURE__ */ React7.createElement(import_ui5.Stack, { direction: "row", justifyContent: "flex-end", alignSelf: "end", py: 1, px: 1.5 }, /* @__PURE__ */ React7.createElement(import_ui5.Button, { onClick: closePopup, color: "secondary", variant: "text", size: "small" }, texts.cancel), /* @__PURE__ */ React7.createElement(import_ui5.Button, { type: "submit", disabled: !isValid, variant: "contained", color: "primary", size: "small" }, texts.create))));
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
// src/components/edit-component/edit-component.tsx
|
|
1131
|
+
var React9 = __toESM(require("react"));
|
|
1132
|
+
var import_react6 = require("react");
|
|
1133
|
+
var import_editor_documents4 = require("@elementor/editor-documents");
|
|
1134
|
+
var import_editor_v1_adapters5 = require("@elementor/editor-v1-adapters");
|
|
1135
|
+
var import_store15 = require("@elementor/store");
|
|
1136
|
+
|
|
1137
|
+
// src/store/actions.ts
|
|
1138
|
+
var import_store13 = require("@elementor/store");
|
|
1139
|
+
function updateCurrentComponent({
|
|
1140
|
+
path,
|
|
1141
|
+
currentComponentId
|
|
1142
|
+
}) {
|
|
1143
|
+
const dispatch7 = (0, import_store13.__getStore)()?.dispatch;
|
|
1144
|
+
if (!dispatch7) {
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
dispatch7(slice.actions.setPath(path));
|
|
1148
|
+
dispatch7(slice.actions.setCurrentComponentId(currentComponentId));
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
// src/components/edit-component/component-modal.tsx
|
|
1152
|
+
var React8 = __toESM(require("react"));
|
|
1153
|
+
var import_react5 = require("react");
|
|
1154
|
+
var import_react_dom = require("react-dom");
|
|
1155
|
+
var import_i18n6 = require("@wordpress/i18n");
|
|
1156
|
+
|
|
1157
|
+
// src/hooks/use-canvas-document.ts
|
|
1158
|
+
var import_editor_canvas5 = require("@elementor/editor-canvas");
|
|
1159
|
+
var import_editor_v1_adapters4 = require("@elementor/editor-v1-adapters");
|
|
1160
|
+
function useCanvasDocument() {
|
|
1161
|
+
return (0, import_editor_v1_adapters4.__privateUseListenTo)((0, import_editor_v1_adapters4.commandEndEvent)("editor/documents/attach-preview"), () => (0, import_editor_canvas5.getCanvasIframeDocument)());
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// src/hooks/use-element-rect.ts
|
|
1165
|
+
var import_react4 = require("react");
|
|
1166
|
+
var import_utils3 = require("@elementor/utils");
|
|
1167
|
+
function useElementRect(element) {
|
|
1168
|
+
const [rect, setRect] = (0, import_react4.useState)(new DOMRect(0, 0, 0, 0));
|
|
1169
|
+
const onChange = (0, import_utils3.throttle)(
|
|
1170
|
+
() => {
|
|
1171
|
+
setRect(element?.getBoundingClientRect() ?? new DOMRect(0, 0, 0, 0));
|
|
1172
|
+
},
|
|
1173
|
+
20,
|
|
1174
|
+
true
|
|
1175
|
+
);
|
|
1176
|
+
useScrollListener({ element, onChange });
|
|
1177
|
+
useResizeListener({ element, onChange });
|
|
1178
|
+
useMutationsListener({ element, onChange });
|
|
1179
|
+
(0, import_react4.useEffect)(
|
|
1180
|
+
() => () => {
|
|
1181
|
+
onChange.cancel();
|
|
1182
|
+
},
|
|
1183
|
+
[onChange]
|
|
1184
|
+
);
|
|
1185
|
+
return rect;
|
|
1186
|
+
}
|
|
1187
|
+
function useScrollListener({ element, onChange }) {
|
|
1188
|
+
(0, import_react4.useEffect)(() => {
|
|
1189
|
+
if (!element) {
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
const win = element.ownerDocument?.defaultView;
|
|
1193
|
+
win?.addEventListener("scroll", onChange, { passive: true });
|
|
1194
|
+
return () => {
|
|
1195
|
+
win?.removeEventListener("scroll", onChange);
|
|
1196
|
+
};
|
|
1197
|
+
}, [element, onChange]);
|
|
1198
|
+
}
|
|
1199
|
+
function useResizeListener({ element, onChange }) {
|
|
1200
|
+
(0, import_react4.useEffect)(() => {
|
|
1201
|
+
if (!element) {
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
const resizeObserver = new ResizeObserver(onChange);
|
|
1205
|
+
resizeObserver.observe(element);
|
|
1206
|
+
const win = element.ownerDocument?.defaultView;
|
|
1207
|
+
win?.addEventListener("resize", onChange, { passive: true });
|
|
1208
|
+
return () => {
|
|
1209
|
+
resizeObserver.disconnect();
|
|
1210
|
+
win?.removeEventListener("resize", onChange);
|
|
1211
|
+
};
|
|
1212
|
+
}, [element, onChange]);
|
|
1213
|
+
}
|
|
1214
|
+
function useMutationsListener({ element, onChange }) {
|
|
1215
|
+
(0, import_react4.useEffect)(() => {
|
|
1216
|
+
if (!element) {
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
const mutationObserver = new MutationObserver(onChange);
|
|
1220
|
+
mutationObserver.observe(element, { childList: true, subtree: true });
|
|
1221
|
+
return () => {
|
|
1222
|
+
mutationObserver.disconnect();
|
|
1223
|
+
};
|
|
1224
|
+
}, [element, onChange]);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// src/components/edit-component/component-modal.tsx
|
|
1228
|
+
function ComponentModal({ element, onClose }) {
|
|
1229
|
+
const canvasDocument = useCanvasDocument();
|
|
1230
|
+
(0, import_react5.useEffect)(() => {
|
|
1231
|
+
const handleEsc = (event) => {
|
|
1232
|
+
if (event.key === "Escape") {
|
|
1233
|
+
onClose();
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
canvasDocument?.body.addEventListener("keydown", handleEsc);
|
|
1237
|
+
return () => {
|
|
1238
|
+
canvasDocument?.body.removeEventListener("keydown", handleEsc);
|
|
1239
|
+
};
|
|
1240
|
+
}, [canvasDocument, onClose]);
|
|
1241
|
+
if (!canvasDocument?.body) {
|
|
1242
|
+
return null;
|
|
1243
|
+
}
|
|
1244
|
+
return (0, import_react_dom.createPortal)(
|
|
1245
|
+
/* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(BlockEditPage, null), /* @__PURE__ */ React8.createElement(Backdrop, { canvas: canvasDocument, element, onClose })),
|
|
1246
|
+
canvasDocument.body
|
|
1247
|
+
);
|
|
1248
|
+
}
|
|
1249
|
+
function Backdrop({ canvas, element, onClose }) {
|
|
1250
|
+
const rect = useElementRect(element);
|
|
1251
|
+
const backdropStyle = {
|
|
1252
|
+
position: "fixed",
|
|
1253
|
+
top: 0,
|
|
1254
|
+
left: 0,
|
|
1255
|
+
width: "100vw",
|
|
1256
|
+
height: "100vh",
|
|
1257
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
1258
|
+
zIndex: 999,
|
|
1259
|
+
pointerEvents: "painted",
|
|
1260
|
+
cursor: "pointer",
|
|
1261
|
+
clipPath: getRoundedRectPath(rect, canvas.defaultView, 5)
|
|
1262
|
+
};
|
|
1263
|
+
const handleKeyDown = (event) => {
|
|
1264
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1265
|
+
event.preventDefault();
|
|
1266
|
+
onClose();
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
return /* @__PURE__ */ React8.createElement(
|
|
1270
|
+
"div",
|
|
1271
|
+
{
|
|
1272
|
+
style: backdropStyle,
|
|
1273
|
+
onClick: onClose,
|
|
1274
|
+
onKeyDown: handleKeyDown,
|
|
1275
|
+
role: "button",
|
|
1276
|
+
tabIndex: 0,
|
|
1277
|
+
"aria-label": (0, import_i18n6.__)("Exit component editing mode", "elementor")
|
|
1278
|
+
}
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
function getRoundedRectPath(rect, viewport, borderRadius) {
|
|
1282
|
+
const padding = borderRadius / 2;
|
|
1283
|
+
const { x: originalX, y: originalY, width: originalWidth, height: originalHeight } = rect;
|
|
1284
|
+
const x = originalX - padding;
|
|
1285
|
+
const y = originalY - padding;
|
|
1286
|
+
const width = originalWidth + 2 * padding;
|
|
1287
|
+
const height = originalHeight + 2 * padding;
|
|
1288
|
+
const radius = Math.min(borderRadius, width / 2, height / 2);
|
|
1289
|
+
const { innerWidth: vw, innerHeight: vh } = viewport;
|
|
1290
|
+
const path = `path(evenodd, 'M 0 0
|
|
1291
|
+
L ${vw} 0
|
|
1292
|
+
L ${vw} ${vh}
|
|
1293
|
+
L 0 ${vh}
|
|
1294
|
+
Z
|
|
1295
|
+
M ${x + radius} ${y}
|
|
1296
|
+
L ${x + width - radius} ${y}
|
|
1297
|
+
A ${radius} ${radius} 0 0 1 ${x + width} ${y + radius}
|
|
1298
|
+
L ${x + width} ${y + height - radius}
|
|
1299
|
+
A ${radius} ${radius} 0 0 1 ${x + width - radius} ${y + height}
|
|
1300
|
+
L ${x + radius} ${y + height}
|
|
1301
|
+
A ${radius} ${radius} 0 0 1 ${x} ${y + height - radius}
|
|
1302
|
+
L ${x} ${y + radius}
|
|
1303
|
+
A ${radius} ${radius} 0 0 1 ${x + radius} ${y}
|
|
1304
|
+
Z'
|
|
1305
|
+
)`;
|
|
1306
|
+
return path.replace(/\s{2,}/g, " ");
|
|
1307
|
+
}
|
|
1308
|
+
function BlockEditPage() {
|
|
1309
|
+
const blockV3DocumentHandlesStyles = `
|
|
1310
|
+
.elementor-editor-active {
|
|
1311
|
+
& .elementor-section-wrap.ui-sortable {
|
|
1312
|
+
display: contents;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
& *[data-editable-elementor-document]:not(.elementor-edit-mode):hover {
|
|
1316
|
+
& .elementor-document-handle:not(.elementor-document-save-back-handle) {
|
|
1317
|
+
display: none;
|
|
1318
|
+
|
|
1319
|
+
&::before,
|
|
1320
|
+
& .elementor-document-handle__inner {
|
|
1321
|
+
display: none;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
`;
|
|
1327
|
+
return /* @__PURE__ */ React8.createElement("style", { "data-e-style-id": "e-block-v3-document-handles-styles" }, blockV3DocumentHandlesStyles);
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// src/components/edit-component/edit-component.tsx
|
|
1331
|
+
function EditComponent() {
|
|
1332
|
+
const { path, currentComponentId } = useCurrentComponent();
|
|
1333
|
+
useHandleDocumentSwitches();
|
|
1334
|
+
const onBack = useNavigateBack(path);
|
|
1335
|
+
const elementDom = getComponentDOMElement(currentComponentId ?? void 0);
|
|
1336
|
+
if (!elementDom) {
|
|
1337
|
+
return null;
|
|
1338
|
+
}
|
|
1339
|
+
return /* @__PURE__ */ React9.createElement(ComponentModal, { element: elementDom, onClose: onBack });
|
|
1340
|
+
}
|
|
1341
|
+
function useHandleDocumentSwitches() {
|
|
1342
|
+
const documentsManager = (0, import_editor_documents4.getV1DocumentsManager)();
|
|
1343
|
+
const { path, currentComponentId } = useCurrentComponent();
|
|
1344
|
+
(0, import_react6.useEffect)(() => {
|
|
1345
|
+
return (0, import_editor_v1_adapters5.__privateListenTo)((0, import_editor_v1_adapters5.commandEndEvent)("editor/documents/attach-preview"), () => {
|
|
1346
|
+
const nextDocument = documentsManager.getCurrent();
|
|
1347
|
+
if (nextDocument.id === currentComponentId) {
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
if (currentComponentId) {
|
|
1351
|
+
apiClient.unlockComponent(currentComponentId);
|
|
1352
|
+
}
|
|
1353
|
+
const isComponent = nextDocument.config.type === COMPONENT_DOCUMENT_TYPE;
|
|
1354
|
+
if (!isComponent) {
|
|
1355
|
+
updateCurrentComponent({ path: [], currentComponentId: null });
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
updateCurrentComponent({
|
|
1359
|
+
path: getUpdatedComponentPath(path, nextDocument),
|
|
1360
|
+
currentComponentId: nextDocument.id
|
|
1361
|
+
});
|
|
1362
|
+
});
|
|
1363
|
+
}, [path, documentsManager, currentComponentId]);
|
|
1364
|
+
}
|
|
1365
|
+
function getUpdatedComponentPath(path, nextDocument) {
|
|
1366
|
+
const componentIndex = path.findIndex(({ componentId }) => componentId === nextDocument.id);
|
|
1367
|
+
if (componentIndex >= 0) {
|
|
1368
|
+
return path.slice(0, componentIndex + 1);
|
|
1369
|
+
}
|
|
1370
|
+
return [
|
|
1371
|
+
...path,
|
|
314
1372
|
{
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
1373
|
+
instanceId: nextDocument?.container.view?.el?.dataset.id,
|
|
1374
|
+
componentId: nextDocument.id
|
|
1375
|
+
}
|
|
1376
|
+
];
|
|
1377
|
+
}
|
|
1378
|
+
function useNavigateBack(path) {
|
|
1379
|
+
const documentsManager = (0, import_editor_documents4.getV1DocumentsManager)();
|
|
1380
|
+
return (0, import_react6.useCallback)(() => {
|
|
1381
|
+
const { componentId: prevComponentId, instanceId: prevComponentInstanceId } = path.at(-2) ?? {};
|
|
1382
|
+
const switchToDocument = (id, selector) => {
|
|
1383
|
+
(0, import_editor_v1_adapters5.__privateRunCommand)("editor/documents/switch", {
|
|
1384
|
+
id,
|
|
1385
|
+
selector,
|
|
1386
|
+
mode: "autosave",
|
|
1387
|
+
setAsInitial: false,
|
|
1388
|
+
shouldScroll: false
|
|
1389
|
+
});
|
|
1390
|
+
};
|
|
1391
|
+
if (prevComponentId && prevComponentInstanceId) {
|
|
1392
|
+
switchToDocument(prevComponentId, `[data-id="${prevComponentInstanceId}"]`);
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
switchToDocument(documentsManager.getInitialId());
|
|
1396
|
+
}, [path, documentsManager]);
|
|
1397
|
+
}
|
|
1398
|
+
function useCurrentComponent() {
|
|
1399
|
+
const path = (0, import_store15.__useSelector)(selectPath);
|
|
1400
|
+
const currentComponentId = (0, import_store15.__useSelector)(selectCurrentComponentId);
|
|
1401
|
+
return {
|
|
1402
|
+
path,
|
|
1403
|
+
currentComponentId
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
function getComponentDOMElement(id) {
|
|
1407
|
+
if (!id) {
|
|
1408
|
+
return null;
|
|
1409
|
+
}
|
|
1410
|
+
const documentsManager = (0, import_editor_documents4.getV1DocumentsManager)();
|
|
1411
|
+
const currentComponent = documentsManager.get(id);
|
|
1412
|
+
const widget = currentComponent?.container;
|
|
1413
|
+
const elementDom = widget?.children?.[0].view?.el;
|
|
1414
|
+
return elementDom ?? null;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
// src/components/in-edit-mode.tsx
|
|
1418
|
+
var React10 = __toESM(require("react"));
|
|
1419
|
+
var import_editor_ui3 = require("@elementor/editor-ui");
|
|
1420
|
+
var import_icons5 = require("@elementor/icons");
|
|
1421
|
+
var import_ui6 = require("@elementor/ui");
|
|
1422
|
+
var import_i18n7 = require("@wordpress/i18n");
|
|
1423
|
+
var openEditModeDialog = (lockedBy) => {
|
|
1424
|
+
(0, import_editor_ui3.openDialog)({
|
|
1425
|
+
component: /* @__PURE__ */ React10.createElement(EditModeDialog, { lockedBy })
|
|
1426
|
+
});
|
|
1427
|
+
};
|
|
1428
|
+
var EditModeDialog = ({ lockedBy }) => {
|
|
1429
|
+
const content = (0, import_i18n7.__)("%s is currently editing this document", "elementor").replace("%s", lockedBy);
|
|
1430
|
+
return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(import_ui6.DialogHeader, { logo: false }, /* @__PURE__ */ React10.createElement(import_ui6.Box, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ React10.createElement(import_ui6.Icon, { color: "secondary" }, /* @__PURE__ */ React10.createElement(import_icons5.InfoCircleFilledIcon, { fontSize: "medium" })), /* @__PURE__ */ React10.createElement(import_ui6.Typography, { variant: "subtitle1" }, content))), /* @__PURE__ */ React10.createElement(import_ui6.DialogContent, null, /* @__PURE__ */ React10.createElement(import_ui6.Stack, { spacing: 2, direction: "column" }, /* @__PURE__ */ React10.createElement(import_ui6.Typography, { variant: "body2" }, (0, import_i18n7.__)(
|
|
1431
|
+
"You can wait for them to finish or reach out to coordinate your changes together.",
|
|
1432
|
+
"elementor"
|
|
1433
|
+
)), /* @__PURE__ */ React10.createElement(import_ui6.DialogActions, null, /* @__PURE__ */ React10.createElement(import_ui6.Button, { color: "secondary", variant: "contained", onClick: import_editor_ui3.closeDialog }, (0, import_i18n7.__)("Close", "elementor"))))));
|
|
1434
|
+
};
|
|
1435
|
+
|
|
1436
|
+
// src/components/overridable-props/overridable-prop-indicator.tsx
|
|
1437
|
+
var React13 = __toESM(require("react"));
|
|
1438
|
+
var import_editor_controls = require("@elementor/editor-controls");
|
|
1439
|
+
var import_editor_documents5 = require("@elementor/editor-documents");
|
|
1440
|
+
var import_editor_editing_panel = require("@elementor/editor-editing-panel");
|
|
1441
|
+
var import_editor_elements5 = require("@elementor/editor-elements");
|
|
1442
|
+
var import_store21 = require("@elementor/store");
|
|
1443
|
+
var import_ui9 = require("@elementor/ui");
|
|
1444
|
+
var import_i18n11 = require("@wordpress/i18n");
|
|
1445
|
+
|
|
1446
|
+
// src/prop-types/component-overridable-prop-type.ts
|
|
1447
|
+
var import_editor_props = require("@elementor/editor-props");
|
|
1448
|
+
var import_schema2 = require("@elementor/schema");
|
|
1449
|
+
var componentOverridablePropTypeUtil = (0, import_editor_props.createPropUtils)(
|
|
1450
|
+
"overridable",
|
|
1451
|
+
import_schema2.z.object({
|
|
1452
|
+
override_key: import_schema2.z.string(),
|
|
1453
|
+
origin_value: import_schema2.z.object({
|
|
1454
|
+
$$type: import_schema2.z.string(),
|
|
1455
|
+
value: import_schema2.z.unknown()
|
|
1456
|
+
}).nullable()
|
|
1457
|
+
})
|
|
1458
|
+
);
|
|
1459
|
+
|
|
1460
|
+
// src/store/set-overridable-prop.ts
|
|
1461
|
+
var import_store17 = require("@elementor/store");
|
|
1462
|
+
var import_utils4 = require("@elementor/utils");
|
|
1463
|
+
var import_i18n8 = require("@wordpress/i18n");
|
|
1464
|
+
function setOverridableProp({
|
|
1465
|
+
componentId,
|
|
1466
|
+
overrideKey,
|
|
1467
|
+
elementId,
|
|
1468
|
+
label,
|
|
1469
|
+
groupId,
|
|
1470
|
+
propKey,
|
|
1471
|
+
elType,
|
|
1472
|
+
widgetType,
|
|
1473
|
+
originValue
|
|
1474
|
+
}) {
|
|
1475
|
+
const overridableProps = selectOverridableProps((0, import_store17.__getState)(), componentId);
|
|
1476
|
+
if (!overridableProps) {
|
|
1477
|
+
return;
|
|
1478
|
+
}
|
|
1479
|
+
const existingOverridableProp = overrideKey ? overridableProps.props[overrideKey] : null;
|
|
1480
|
+
const { props: existingProps, groups: existingGroups } = { ...overridableProps };
|
|
1481
|
+
const { groups: updatedGroups, currentGroupId } = getUpdatedGroups(
|
|
1482
|
+
existingGroups,
|
|
1483
|
+
groupId || existingOverridableProp?.groupId
|
|
1484
|
+
);
|
|
1485
|
+
const overridableProp = {
|
|
1486
|
+
overrideKey: existingOverridableProp?.overrideKey || (0, import_utils4.generateUniqueId)("prop"),
|
|
1487
|
+
label,
|
|
1488
|
+
elementId,
|
|
1489
|
+
propKey,
|
|
1490
|
+
widgetType,
|
|
1491
|
+
elType,
|
|
1492
|
+
originValue,
|
|
1493
|
+
groupId: currentGroupId
|
|
1494
|
+
};
|
|
1495
|
+
const props = {
|
|
1496
|
+
...existingProps,
|
|
1497
|
+
[overridableProp.overrideKey]: overridableProp
|
|
1498
|
+
};
|
|
1499
|
+
const groups = {
|
|
1500
|
+
items: {
|
|
1501
|
+
...updatedGroups.items,
|
|
1502
|
+
[currentGroupId]: getGroupWithProp(updatedGroups, currentGroupId, overridableProp)
|
|
320
1503
|
},
|
|
321
|
-
|
|
322
|
-
|
|
1504
|
+
order: updatedGroups.order.includes(currentGroupId) ? updatedGroups.order : [...updatedGroups.order, currentGroupId]
|
|
1505
|
+
};
|
|
1506
|
+
const isChangingGroups = existingOverridableProp && existingOverridableProp.groupId !== currentGroupId;
|
|
1507
|
+
if (isChangingGroups) {
|
|
1508
|
+
groups.items[existingOverridableProp.groupId] = getGroupWithoutProp(
|
|
1509
|
+
updatedGroups,
|
|
1510
|
+
existingOverridableProp.groupId,
|
|
1511
|
+
overridableProp
|
|
1512
|
+
);
|
|
1513
|
+
}
|
|
1514
|
+
(0, import_store17.__dispatch)(
|
|
1515
|
+
slice.actions.setOverridableProps({
|
|
1516
|
+
componentId,
|
|
1517
|
+
overridableProps: {
|
|
1518
|
+
props,
|
|
1519
|
+
groups
|
|
1520
|
+
}
|
|
1521
|
+
})
|
|
1522
|
+
);
|
|
1523
|
+
return overridableProp;
|
|
1524
|
+
}
|
|
1525
|
+
function getUpdatedGroups(groups, groupId) {
|
|
1526
|
+
if (!groupId) {
|
|
1527
|
+
if (groups.order.length > 0) {
|
|
1528
|
+
return { groups, currentGroupId: groups.order[0] };
|
|
1529
|
+
}
|
|
1530
|
+
return addNewGroup(groups);
|
|
1531
|
+
}
|
|
1532
|
+
if (!groups.items[groupId]) {
|
|
1533
|
+
return addNewGroup(groups, groupId);
|
|
1534
|
+
}
|
|
1535
|
+
return { groups, currentGroupId: groupId };
|
|
1536
|
+
}
|
|
1537
|
+
function addNewGroup(groups, groupId) {
|
|
1538
|
+
const currentGroupId = groupId || (0, import_utils4.generateUniqueId)("group");
|
|
1539
|
+
const updatedGroups = {
|
|
1540
|
+
...groups,
|
|
1541
|
+
items: {
|
|
1542
|
+
...groups.items,
|
|
1543
|
+
[currentGroupId]: {
|
|
1544
|
+
id: currentGroupId,
|
|
1545
|
+
label: (0, import_i18n8.__)("Default", "elementor"),
|
|
1546
|
+
props: []
|
|
1547
|
+
}
|
|
1548
|
+
},
|
|
1549
|
+
order: [...groups.order, currentGroupId]
|
|
1550
|
+
};
|
|
1551
|
+
return { groups: updatedGroups, currentGroupId };
|
|
1552
|
+
}
|
|
1553
|
+
function getGroupWithProp(groups, groupId, overridableProp) {
|
|
1554
|
+
const group = { ...groups.items[groupId] };
|
|
1555
|
+
if (!group.props.includes(overridableProp.overrideKey)) {
|
|
1556
|
+
group.props = [...group.props, overridableProp.overrideKey];
|
|
1557
|
+
}
|
|
1558
|
+
return group;
|
|
1559
|
+
}
|
|
1560
|
+
function getGroupWithoutProp(groups, groupId, overridableProp) {
|
|
1561
|
+
const group = { ...groups.items[groupId] };
|
|
1562
|
+
if (group) {
|
|
1563
|
+
group.props = group.props.filter((key) => key !== overridableProp.overrideKey);
|
|
1564
|
+
}
|
|
1565
|
+
return group;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
// src/components/overridable-props/indicator.tsx
|
|
1569
|
+
var React11 = __toESM(require("react"));
|
|
1570
|
+
var import_react7 = require("react");
|
|
1571
|
+
var import_icons6 = require("@elementor/icons");
|
|
1572
|
+
var import_ui7 = require("@elementor/ui");
|
|
1573
|
+
var import_i18n9 = require("@wordpress/i18n");
|
|
1574
|
+
var SIZE = "tiny";
|
|
1575
|
+
var IconContainer = (0, import_ui7.styled)(import_ui7.Box)`
|
|
1576
|
+
pointer-events: none;
|
|
1577
|
+
opacity: 0;
|
|
1578
|
+
transition: opacity 0.2s ease-in-out;
|
|
1579
|
+
|
|
1580
|
+
& > svg {
|
|
1581
|
+
position: absolute;
|
|
1582
|
+
top: 50%;
|
|
1583
|
+
left: 50%;
|
|
1584
|
+
transform: translate( -50%, -50% );
|
|
1585
|
+
width: 10px;
|
|
1586
|
+
height: 10px;
|
|
1587
|
+
fill: ${({ theme }) => theme.palette.primary.contrastText};
|
|
1588
|
+
stroke: ${({ theme }) => theme.palette.primary.contrastText};
|
|
1589
|
+
stroke-width: 2px;
|
|
1590
|
+
}
|
|
1591
|
+
`;
|
|
1592
|
+
var Content = (0, import_ui7.styled)(import_ui7.Box)`
|
|
1593
|
+
position: relative;
|
|
1594
|
+
display: flex;
|
|
1595
|
+
align-items: center;
|
|
1596
|
+
justify-content: center;
|
|
1597
|
+
cursor: pointer;
|
|
1598
|
+
width: 16px;
|
|
1599
|
+
height: 16px;
|
|
1600
|
+
margin-inline: ${({ theme }) => theme.spacing(0.5)};
|
|
1601
|
+
|
|
1602
|
+
&:before {
|
|
1603
|
+
content: '';
|
|
1604
|
+
display: block;
|
|
1605
|
+
position: absolute;
|
|
1606
|
+
top: 50%;
|
|
1607
|
+
left: 50%;
|
|
1608
|
+
transform: translate( -50%, -50% ) rotate( 45deg );
|
|
1609
|
+
width: 5px;
|
|
1610
|
+
height: 5px;
|
|
1611
|
+
border-radius: 1px;
|
|
1612
|
+
background-color: ${({ theme }) => theme.palette.primary.main};
|
|
1613
|
+
transition: all 0.1s ease-in-out;
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
&:hover,
|
|
1617
|
+
&.enlarged {
|
|
1618
|
+
&:before {
|
|
1619
|
+
width: 12px;
|
|
1620
|
+
height: 12px;
|
|
1621
|
+
border-radius: 2px;
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
.icon {
|
|
1625
|
+
opacity: 1;
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
`;
|
|
1629
|
+
var Indicator = (0, import_react7.forwardRef)(({ triggerProps, isOpen, isOverridable }, ref) => /* @__PURE__ */ React11.createElement(Content, { ref, ...triggerProps, className: isOpen || isOverridable ? "enlarged" : "" }, /* @__PURE__ */ React11.createElement(
|
|
1630
|
+
IconContainer,
|
|
1631
|
+
{
|
|
1632
|
+
className: "icon",
|
|
1633
|
+
"aria-label": isOverridable ? (0, import_i18n9.__)("Overridable property", "elementor") : (0, import_i18n9.__)("Make prop overridable", "elementor")
|
|
1634
|
+
},
|
|
1635
|
+
isOverridable ? /* @__PURE__ */ React11.createElement(import_icons6.CheckIcon, { fontSize: SIZE }) : /* @__PURE__ */ React11.createElement(import_icons6.PlusIcon, { fontSize: SIZE })
|
|
1636
|
+
)));
|
|
1637
|
+
|
|
1638
|
+
// src/components/overridable-props/overridable-prop-form.tsx
|
|
1639
|
+
var React12 = __toESM(require("react"));
|
|
1640
|
+
var import_react8 = require("react");
|
|
1641
|
+
var import_editor_ui4 = require("@elementor/editor-ui");
|
|
1642
|
+
var import_ui8 = require("@elementor/ui");
|
|
1643
|
+
var import_i18n10 = require("@wordpress/i18n");
|
|
1644
|
+
var SIZE2 = "tiny";
|
|
1645
|
+
var DEFAULT_GROUP = { value: null, label: (0, import_i18n10.__)("Default", "elementor") };
|
|
1646
|
+
function OverridablePropForm({ onSubmit, groups, currentValue }) {
|
|
1647
|
+
const [propLabel, setPropLabel] = (0, import_react8.useState)(currentValue?.label ?? null);
|
|
1648
|
+
const [group, setGroup] = (0, import_react8.useState)(currentValue?.groupId ?? groups?.[0]?.value ?? null);
|
|
1649
|
+
const name = (0, import_i18n10.__)("Name", "elementor");
|
|
1650
|
+
const groupName = (0, import_i18n10.__)("Group Name", "elementor");
|
|
1651
|
+
const isCreate = currentValue === void 0;
|
|
1652
|
+
const title = isCreate ? (0, import_i18n10.__)("Create new property", "elementor") : (0, import_i18n10.__)("Update property", "elementor");
|
|
1653
|
+
const ctaLabel = isCreate ? (0, import_i18n10.__)("Create", "elementor") : (0, import_i18n10.__)("Update", "elementor");
|
|
1654
|
+
return /* @__PURE__ */ React12.createElement(import_editor_ui4.Form, { onSubmit: () => onSubmit({ label: propLabel ?? "", group }) }, /* @__PURE__ */ React12.createElement(import_ui8.Stack, { alignItems: "start", width: "268px" }, /* @__PURE__ */ React12.createElement(
|
|
1655
|
+
import_ui8.Stack,
|
|
1656
|
+
{
|
|
1657
|
+
direction: "row",
|
|
1658
|
+
alignItems: "center",
|
|
1659
|
+
py: 1,
|
|
1660
|
+
px: 1.5,
|
|
1661
|
+
sx: { columnGap: 0.5, borderBottom: "1px solid", borderColor: "divider", width: "100%", mb: 1.5 }
|
|
1662
|
+
},
|
|
1663
|
+
/* @__PURE__ */ React12.createElement(import_ui8.Typography, { variant: "caption", sx: { color: "text.primary", fontWeight: "500", lineHeight: 1 } }, title)
|
|
1664
|
+
), /* @__PURE__ */ React12.createElement(import_ui8.Grid, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React12.createElement(import_ui8.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React12.createElement(import_ui8.FormLabel, { size: "tiny" }, name)), /* @__PURE__ */ React12.createElement(import_ui8.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React12.createElement(
|
|
1665
|
+
import_ui8.TextField,
|
|
1666
|
+
{
|
|
1667
|
+
name,
|
|
1668
|
+
size: SIZE2,
|
|
1669
|
+
fullWidth: true,
|
|
1670
|
+
placeholder: (0, import_i18n10.__)("Enter value", "elementor"),
|
|
1671
|
+
value: propLabel ?? "",
|
|
1672
|
+
onChange: (e) => setPropLabel(e.target.value)
|
|
1673
|
+
}
|
|
1674
|
+
))), /* @__PURE__ */ React12.createElement(import_ui8.Grid, { container: true, gap: 0.75, alignItems: "start", px: 1.5, mb: 1.5 }, /* @__PURE__ */ React12.createElement(import_ui8.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React12.createElement(import_ui8.FormLabel, { size: "tiny" }, groupName)), /* @__PURE__ */ React12.createElement(import_ui8.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React12.createElement(
|
|
1675
|
+
import_ui8.Select,
|
|
1676
|
+
{
|
|
1677
|
+
name: groupName,
|
|
1678
|
+
size: SIZE2,
|
|
1679
|
+
fullWidth: true,
|
|
1680
|
+
value: group ?? null,
|
|
1681
|
+
onChange: setGroup,
|
|
1682
|
+
displayEmpty: true,
|
|
1683
|
+
renderValue: (selectedValue) => {
|
|
1684
|
+
if (!selectedValue || selectedValue === "") {
|
|
1685
|
+
const [firstGroup = DEFAULT_GROUP] = groups ?? [];
|
|
1686
|
+
return firstGroup.label;
|
|
1687
|
+
}
|
|
1688
|
+
return groups?.find(({ value }) => value === selectedValue)?.label ?? selectedValue;
|
|
1689
|
+
}
|
|
1690
|
+
},
|
|
1691
|
+
(groups ?? [DEFAULT_GROUP]).map(({ label: groupLabel, ...props }) => /* @__PURE__ */ React12.createElement(import_editor_ui4.MenuListItem, { key: props.value, ...props, value: props.value ?? "" }, groupLabel))
|
|
1692
|
+
))), /* @__PURE__ */ React12.createElement(import_ui8.Stack, { direction: "row", justifyContent: "flex-end", alignSelf: "end", mt: 1.5, py: 1, px: 1.5 }, /* @__PURE__ */ React12.createElement(import_ui8.Button, { type: "submit", disabled: !propLabel, variant: "contained", color: "primary", size: "small" }, ctaLabel))));
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
// src/components/overridable-props/utils/get-overridable-prop.ts
|
|
1696
|
+
var import_store19 = require("@elementor/store");
|
|
1697
|
+
function getOverridableProp({
|
|
1698
|
+
componentId,
|
|
1699
|
+
overrideKey
|
|
1700
|
+
}) {
|
|
1701
|
+
const overridableProps = selectOverridableProps((0, import_store19.__getState)(), componentId);
|
|
1702
|
+
if (!overridableProps) {
|
|
1703
|
+
return void 0;
|
|
1704
|
+
}
|
|
1705
|
+
return overridableProps.props[overrideKey];
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
// src/components/overridable-props/overridable-prop-indicator.tsx
|
|
1709
|
+
var FORBIDDEN_KEYS = ["_cssid", "attributes"];
|
|
1710
|
+
function OverridablePropIndicator() {
|
|
1711
|
+
const { bind } = (0, import_editor_controls.useBoundProp)();
|
|
1712
|
+
const currentDocument = (0, import_editor_documents5.getV1CurrentDocument)();
|
|
1713
|
+
if (currentDocument.config.type !== COMPONENT_DOCUMENT_TYPE || !currentDocument.id) {
|
|
1714
|
+
return null;
|
|
1715
|
+
}
|
|
1716
|
+
if (!isPropAllowed(bind)) {
|
|
1717
|
+
return null;
|
|
1718
|
+
}
|
|
1719
|
+
const overridableProps = selectOverridableProps((0, import_store21.__getState)(), currentDocument.id);
|
|
1720
|
+
return /* @__PURE__ */ React13.createElement(Content2, { componentId: currentDocument.id, overridableProps });
|
|
1721
|
+
}
|
|
1722
|
+
function Content2({ componentId, overridableProps }) {
|
|
1723
|
+
const {
|
|
1724
|
+
element: { id: elementId },
|
|
1725
|
+
elementType
|
|
1726
|
+
} = (0, import_editor_editing_panel.useElement)();
|
|
1727
|
+
const { value, bind } = (0, import_editor_controls.useBoundProp)();
|
|
1728
|
+
const { value: overridableValue, setValue: setOverridableValue } = (0, import_editor_controls.useBoundProp)(componentOverridablePropTypeUtil);
|
|
1729
|
+
const popupState = (0, import_ui9.usePopupState)({
|
|
1730
|
+
variant: "popover"
|
|
1731
|
+
});
|
|
1732
|
+
const triggerProps = (0, import_ui9.bindTrigger)(popupState);
|
|
1733
|
+
const popoverProps = (0, import_ui9.bindPopover)(popupState);
|
|
1734
|
+
const { elType } = (0, import_editor_elements5.getWidgetsCache)()?.[elementType.key] ?? { elType: "widget" };
|
|
1735
|
+
const handleSubmit = ({ label, group }) => {
|
|
1736
|
+
const originValue = !overridableValue ? value : overridableValue?.origin_value ?? {};
|
|
1737
|
+
const overridablePropConfig = setOverridableProp({
|
|
1738
|
+
componentId,
|
|
1739
|
+
overrideKey: overridableValue?.override_key ?? null,
|
|
1740
|
+
elementId,
|
|
1741
|
+
label,
|
|
1742
|
+
groupId: group,
|
|
1743
|
+
propKey: bind,
|
|
1744
|
+
elType: elType ?? "widget",
|
|
1745
|
+
widgetType: elementType.key,
|
|
1746
|
+
originValue
|
|
1747
|
+
});
|
|
1748
|
+
if (!overridableValue && overridablePropConfig) {
|
|
1749
|
+
setOverridableValue({
|
|
1750
|
+
override_key: overridablePropConfig.overrideKey,
|
|
1751
|
+
origin_value: originValue
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
popupState.close();
|
|
1755
|
+
};
|
|
1756
|
+
const overridableConfig = overridableValue ? getOverridableProp({ componentId, overrideKey: overridableValue.override_key }) : void 0;
|
|
1757
|
+
return /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(import_ui9.Tooltip, { placement: "top", title: (0, import_i18n11.__)("Override Property", "elementor") }, /* @__PURE__ */ React13.createElement(
|
|
1758
|
+
Indicator,
|
|
1759
|
+
{
|
|
1760
|
+
triggerProps,
|
|
1761
|
+
isOpen: !!popoverProps.open,
|
|
1762
|
+
isOverridable: !!overridableValue
|
|
1763
|
+
}
|
|
1764
|
+
)), /* @__PURE__ */ React13.createElement(
|
|
1765
|
+
import_ui9.Popover,
|
|
1766
|
+
{
|
|
1767
|
+
disableScrollLock: true,
|
|
1768
|
+
anchorOrigin: {
|
|
1769
|
+
vertical: "bottom",
|
|
1770
|
+
horizontal: "right"
|
|
1771
|
+
},
|
|
1772
|
+
transformOrigin: {
|
|
1773
|
+
vertical: "top",
|
|
1774
|
+
horizontal: "right"
|
|
1775
|
+
},
|
|
1776
|
+
PaperProps: {
|
|
1777
|
+
sx: { my: 2.5 }
|
|
1778
|
+
},
|
|
1779
|
+
...popoverProps
|
|
1780
|
+
},
|
|
1781
|
+
/* @__PURE__ */ React13.createElement(
|
|
1782
|
+
OverridablePropForm,
|
|
1783
|
+
{
|
|
1784
|
+
onSubmit: handleSubmit,
|
|
1785
|
+
groups: overridableProps?.groups.order.map((groupId) => ({
|
|
1786
|
+
value: groupId,
|
|
1787
|
+
label: overridableProps.groups.items[groupId].label
|
|
1788
|
+
})),
|
|
1789
|
+
currentValue: overridableConfig
|
|
1790
|
+
}
|
|
1791
|
+
)
|
|
1792
|
+
));
|
|
1793
|
+
}
|
|
1794
|
+
function isPropAllowed(bind) {
|
|
1795
|
+
return !FORBIDDEN_KEYS.includes(bind);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
// src/mcp/index.ts
|
|
1799
|
+
var import_editor_mcp2 = require("@elementor/editor-mcp");
|
|
1800
|
+
|
|
1801
|
+
// src/mcp/save-as-component-tool.ts
|
|
1802
|
+
var import_editor_elements6 = require("@elementor/editor-elements");
|
|
1803
|
+
var import_editor_mcp = require("@elementor/editor-mcp");
|
|
1804
|
+
var import_schema3 = require("@elementor/schema");
|
|
1805
|
+
var InputSchema = {
|
|
1806
|
+
element_id: import_schema3.z.string().describe(
|
|
1807
|
+
'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.'
|
|
1808
|
+
),
|
|
1809
|
+
component_name: import_schema3.z.string().describe("The name for the new component. Should be descriptive and unique among existing components.")
|
|
1810
|
+
};
|
|
1811
|
+
var OutputSchema = {
|
|
1812
|
+
message: import_schema3.z.string().optional().describe("Additional information about the operation result"),
|
|
1813
|
+
component_uid: import_schema3.z.string().optional().describe("The unique identifier of the newly created component (only present on success)")
|
|
1814
|
+
};
|
|
1815
|
+
var VALID_ELEMENT_TYPES = ["e-div-block", "e-flexbox", "e-tabs"];
|
|
1816
|
+
var ERROR_MESSAGES = {
|
|
1817
|
+
ELEMENT_NOT_FOUND: "Element not found. Use 'list-elements' to get valid element IDs.",
|
|
1818
|
+
ELEMENT_NOT_ONE_OF_TYPES: `Element is not one of the following types: ${VALID_ELEMENT_TYPES.join(", ")}`,
|
|
1819
|
+
ELEMENT_IS_LOCKED: "Cannot save a locked element as a component."
|
|
1820
|
+
};
|
|
1821
|
+
var handleSaveAsComponent = async (params) => {
|
|
1822
|
+
const { element_id: elementId, component_name: componentName } = params;
|
|
1823
|
+
const container = (0, import_editor_elements6.getContainer)(elementId);
|
|
1824
|
+
if (!container) {
|
|
1825
|
+
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_FOUND);
|
|
1826
|
+
}
|
|
1827
|
+
const elType = container.model.get("elType");
|
|
1828
|
+
if (!VALID_ELEMENT_TYPES.includes(elType)) {
|
|
1829
|
+
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_ONE_OF_TYPES);
|
|
1830
|
+
}
|
|
1831
|
+
const element = container.model.toJSON({ remove: ["default"] });
|
|
1832
|
+
if (element?.isLocked) {
|
|
1833
|
+
throw new Error(ERROR_MESSAGES.ELEMENT_IS_LOCKED);
|
|
1834
|
+
}
|
|
1835
|
+
const uid = createUnpublishedComponent(componentName, element, null);
|
|
1836
|
+
return {
|
|
1837
|
+
status: "ok",
|
|
1838
|
+
message: `Component "${componentName}" created successfully.`,
|
|
1839
|
+
component_uid: uid
|
|
1840
|
+
};
|
|
1841
|
+
};
|
|
1842
|
+
var initSaveAsComponentTool = () => {
|
|
1843
|
+
return (0, import_editor_mcp.getMCPByDomain)("components").addTool({
|
|
1844
|
+
name: "save-as-component",
|
|
1845
|
+
schema: InputSchema,
|
|
1846
|
+
outputSchema: OutputSchema,
|
|
1847
|
+
description: `Save an existing element as a reusable component in the Elementor editor.
|
|
1848
|
+
|
|
1849
|
+
## When NOT to use this tool:
|
|
1850
|
+
- Do not use for elements that are already components (widgetType: 'e-component').
|
|
1851
|
+
- Do not use for locked elements.
|
|
1852
|
+
- Do not guess element IDs. Always use "list-elements" first to get valid IDs.
|
|
1853
|
+
|
|
1854
|
+
## Prerequisites:
|
|
1855
|
+
- **Verify element type**: Ensure the element is not already a component (widgetType should not be 'e-component').
|
|
1856
|
+
- **Check if element is unlocked**: Locked elements cannot be saved as components.
|
|
1857
|
+
- **Check that the element is one of the following types**: ${VALID_ELEMENT_TYPES.join(", ")}
|
|
1858
|
+
|
|
1859
|
+
## Required parameters:
|
|
1860
|
+
- **element_id**: The unique ID of the element to save.
|
|
1861
|
+
- **component_name**: A descriptive name for the component (2-50 characters).
|
|
1862
|
+
|
|
1863
|
+
## Example tool call:
|
|
1864
|
+
\`\`\`json
|
|
1865
|
+
{ "element_id": "abc123", "component_name": "Hero Section" }
|
|
1866
|
+
\`\`\`
|
|
1867
|
+
`,
|
|
1868
|
+
handler: handleSaveAsComponent
|
|
1869
|
+
});
|
|
1870
|
+
};
|
|
1871
|
+
|
|
1872
|
+
// src/mcp/index.ts
|
|
1873
|
+
function initMcp() {
|
|
1874
|
+
const { setMCPDescription } = (0, import_editor_mcp2.getMCPByDomain)("components");
|
|
1875
|
+
setMCPDescription(
|
|
1876
|
+
`Elementor Editor Components MCP - Tools for creating and managing reusable components.
|
|
1877
|
+
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.`
|
|
1878
|
+
);
|
|
1879
|
+
initSaveAsComponentTool();
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
// src/populate-store.ts
|
|
1883
|
+
var import_react9 = require("react");
|
|
1884
|
+
var import_store23 = require("@elementor/store");
|
|
1885
|
+
function PopulateStore() {
|
|
1886
|
+
(0, import_react9.useEffect)(() => {
|
|
1887
|
+
(0, import_store23.__dispatch)(loadComponents());
|
|
1888
|
+
}, []);
|
|
1889
|
+
return null;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
// src/store/components-styles-provider.ts
|
|
1893
|
+
var import_editor_styles_repository = require("@elementor/editor-styles-repository");
|
|
1894
|
+
var import_store24 = require("@elementor/store");
|
|
1895
|
+
var componentsStylesProvider = (0, import_editor_styles_repository.createStylesProvider)({
|
|
1896
|
+
key: "components-styles",
|
|
1897
|
+
priority: 100,
|
|
1898
|
+
subscribe: (cb) => (0, import_store24.__subscribeWithSelector)(
|
|
1899
|
+
(state) => state[SLICE_NAME],
|
|
1900
|
+
() => {
|
|
1901
|
+
cb();
|
|
1902
|
+
}
|
|
1903
|
+
),
|
|
1904
|
+
actions: {
|
|
1905
|
+
all: () => {
|
|
1906
|
+
return selectFlatStyles((0, import_store24.__getState)());
|
|
1907
|
+
},
|
|
1908
|
+
get: (id) => {
|
|
1909
|
+
return selectFlatStyles((0, import_store24.__getState)()).find((style) => style.id === id) ?? null;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
});
|
|
1913
|
+
|
|
1914
|
+
// src/store/remove-component-styles.ts
|
|
1915
|
+
var import_store26 = require("@elementor/store");
|
|
1916
|
+
function removeComponentStyles(id) {
|
|
1917
|
+
apiClient.invalidateComponentConfigCache(id);
|
|
1918
|
+
(0, import_store26.__dispatch)(slice.actions.removeStyles({ id }));
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
// src/sync/create-components-before-save.ts
|
|
1922
|
+
var import_editor_elements7 = require("@elementor/editor-elements");
|
|
1923
|
+
var import_store28 = require("@elementor/store");
|
|
1924
|
+
async function createComponentsBeforeSave({
|
|
1925
|
+
container,
|
|
1926
|
+
status
|
|
1927
|
+
}) {
|
|
1928
|
+
const unpublishedComponents = selectUnpublishedComponents((0, import_store28.__getState)());
|
|
1929
|
+
if (!unpublishedComponents.length) {
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
try {
|
|
1933
|
+
const uidToComponentId = await createComponents(unpublishedComponents, status);
|
|
1934
|
+
const elements = container.model.get("elements").toJSON();
|
|
1935
|
+
updateComponentInstances(elements, uidToComponentId);
|
|
1936
|
+
(0, import_store28.__dispatch)(
|
|
1937
|
+
slice.actions.add(
|
|
1938
|
+
unpublishedComponents.map((component) => ({
|
|
1939
|
+
id: uidToComponentId.get(component.uid),
|
|
1940
|
+
name: component.name,
|
|
1941
|
+
uid: component.uid
|
|
1942
|
+
}))
|
|
1943
|
+
)
|
|
1944
|
+
);
|
|
1945
|
+
(0, import_store28.__dispatch)(slice.actions.resetUnpublished());
|
|
1946
|
+
} catch (error) {
|
|
1947
|
+
throw new Error(`Failed to publish components and update component instances: ${error}`);
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
async function createComponents(components, status) {
|
|
1951
|
+
const response = await apiClient.create({
|
|
1952
|
+
status,
|
|
1953
|
+
items: components.map((component) => ({
|
|
1954
|
+
uid: component.uid,
|
|
1955
|
+
title: component.name,
|
|
1956
|
+
elements: component.elements
|
|
1957
|
+
}))
|
|
1958
|
+
});
|
|
1959
|
+
const map = /* @__PURE__ */ new Map();
|
|
1960
|
+
Object.entries(response).forEach(([key, value]) => {
|
|
1961
|
+
map.set(key, value);
|
|
1962
|
+
});
|
|
1963
|
+
return map;
|
|
1964
|
+
}
|
|
1965
|
+
function updateComponentInstances(elements, uidToComponentId) {
|
|
1966
|
+
elements.forEach((element) => {
|
|
1967
|
+
const { shouldUpdate, newComponentId } = shouldUpdateElement(element, uidToComponentId);
|
|
1968
|
+
if (shouldUpdate) {
|
|
1969
|
+
updateElementComponentId(element.id, newComponentId);
|
|
1970
|
+
}
|
|
1971
|
+
if (element.elements) {
|
|
1972
|
+
updateComponentInstances(element.elements, uidToComponentId);
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
function shouldUpdateElement(element, uidToComponentId) {
|
|
1977
|
+
if (element.widgetType === "e-component") {
|
|
1978
|
+
const currentComponentId = element.settings?.component_instance?.value?.component_id;
|
|
1979
|
+
if (currentComponentId && uidToComponentId.has(currentComponentId)) {
|
|
1980
|
+
return { shouldUpdate: true, newComponentId: uidToComponentId.get(currentComponentId) };
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
return { shouldUpdate: false, newComponentId: null };
|
|
1984
|
+
}
|
|
1985
|
+
function updateElementComponentId(elementId, componentId) {
|
|
1986
|
+
(0, import_editor_elements7.updateElementSettings)({
|
|
1987
|
+
id: elementId,
|
|
1988
|
+
props: {
|
|
1989
|
+
component_instance: {
|
|
1990
|
+
$$type: "component-instance",
|
|
1991
|
+
value: { component_id: componentId }
|
|
1992
|
+
}
|
|
1993
|
+
},
|
|
1994
|
+
withHistory: false
|
|
1995
|
+
});
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
// src/sync/update-components-before-save.ts
|
|
1999
|
+
var import_editor_documents6 = require("@elementor/editor-documents");
|
|
2000
|
+
async function updateComponentsBeforeSave({ status, container }) {
|
|
2001
|
+
if (status !== "publish") {
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
const elements = container.model.get("elements").toJSON();
|
|
2005
|
+
const componentIds = await getComponentIds(elements);
|
|
2006
|
+
const componentDocumentData = await Promise.all(componentIds.map(getComponentDocumentData));
|
|
2007
|
+
const draftIds = componentDocumentData.filter((document) => !!document).filter(import_editor_documents6.isDocumentDirty).map((document) => document.id);
|
|
2008
|
+
if (draftIds.length === 0) {
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
await apiClient.updateStatuses(draftIds, "publish");
|
|
2012
|
+
draftIds.forEach((id) => invalidateComponentDocumentData(id));
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
// src/sync/before-save.ts
|
|
2016
|
+
var beforeSave = ({ container, status }) => {
|
|
2017
|
+
return Promise.all([
|
|
2018
|
+
createComponentsBeforeSave({ container, status }),
|
|
2019
|
+
updateComponentsBeforeSave({ container, status })
|
|
2020
|
+
]);
|
|
323
2021
|
};
|
|
324
2022
|
|
|
325
2023
|
// src/init.ts
|
|
326
2024
|
function init() {
|
|
2025
|
+
import_editor_styles_repository2.stylesRepository.register(componentsStylesProvider);
|
|
2026
|
+
(0, import_store30.__registerSlice)(slice);
|
|
2027
|
+
(0, import_editor_canvas6.registerElementType)(
|
|
2028
|
+
TYPE,
|
|
2029
|
+
(options) => createComponentType({ ...options, showLockedByModal: openEditModeDialog })
|
|
2030
|
+
);
|
|
2031
|
+
(0, import_editor_v1_adapters6.registerDataHook)("dependency", "editor/documents/close", (args) => {
|
|
2032
|
+
const document = (0, import_editor_documents7.getV1CurrentDocument)();
|
|
2033
|
+
if (document.config.type === COMPONENT_DOCUMENT_TYPE) {
|
|
2034
|
+
args.mode = "autosave";
|
|
2035
|
+
}
|
|
2036
|
+
return true;
|
|
2037
|
+
});
|
|
2038
|
+
(0, import_editor_v1_adapters6.registerDataHook)("after", "preview/drop", onElementDrop);
|
|
2039
|
+
window.elementorCommon.__beforeSave = beforeSave;
|
|
327
2040
|
(0, import_editor_elements_panel.injectTab)({
|
|
328
2041
|
id: "components",
|
|
329
|
-
label: (0,
|
|
330
|
-
component:
|
|
2042
|
+
label: (0, import_i18n12.__)("Components", "elementor"),
|
|
2043
|
+
component: Components
|
|
331
2044
|
});
|
|
332
2045
|
(0, import_editor.injectIntoTop)({
|
|
333
2046
|
id: "create-component-popup",
|
|
334
2047
|
component: CreateComponentForm
|
|
335
2048
|
});
|
|
2049
|
+
(0, import_editor.injectIntoLogic)({
|
|
2050
|
+
id: "components-populate-store",
|
|
2051
|
+
component: PopulateStore
|
|
2052
|
+
});
|
|
2053
|
+
(0, import_editor.injectIntoTop)({
|
|
2054
|
+
id: "edit-component",
|
|
2055
|
+
component: EditComponent
|
|
2056
|
+
});
|
|
2057
|
+
(0, import_editor_v1_adapters6.registerDataHook)("after", "editor/documents/attach-preview", async () => {
|
|
2058
|
+
const { id, config } = (0, import_editor_documents7.getV1CurrentDocument)();
|
|
2059
|
+
if (id) {
|
|
2060
|
+
removeComponentStyles(id);
|
|
2061
|
+
}
|
|
2062
|
+
await loadComponentsAssets(config?.elements ?? []);
|
|
2063
|
+
});
|
|
2064
|
+
(0, import_editor_editing_panel2.registerFieldIndicator)({
|
|
2065
|
+
fieldType: import_editor_editing_panel2.FIELD_TYPE.SETTINGS,
|
|
2066
|
+
id: "component-overridable-prop",
|
|
2067
|
+
priority: 1,
|
|
2068
|
+
indicator: OverridablePropIndicator
|
|
2069
|
+
});
|
|
2070
|
+
import_editor_canvas6.settingsTransformersRegistry.register("component-instance", componentInstanceTransformer);
|
|
2071
|
+
import_editor_canvas6.settingsTransformersRegistry.register("overridable", componentOverridableTransformer);
|
|
2072
|
+
initMcp();
|
|
336
2073
|
}
|
|
337
2074
|
// Annotate the CommonJS export names for ESM import in node:
|
|
338
2075
|
0 && (module.exports = {
|