@elementor/editor-components 3.33.0-99 → 3.35.0-324

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