@elementor/editor-global-classes 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +93 -0
- package/dist/index.js +480 -89
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +514 -86
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -8
- package/src/api.ts +6 -12
- package/src/components/class-manager/class-manager-button.tsx +8 -5
- package/src/components/class-manager/class-manager-panel.tsx +16 -9
- package/src/components/class-manager/delete-confirmation-dialog.tsx +96 -0
- package/src/components/class-manager/global-classes-list.tsx +261 -0
- package/src/components/class-manager/sortable.tsx +90 -0
- package/src/components/{logic-hooks.tsx → populate-store.tsx} +1 -1
- package/src/errors.ts +11 -0
- package/src/global-classes-styles-provider.ts +51 -25
- package/src/init.ts +10 -4
- package/src/store.ts +87 -14
- package/src/sync-with-document-save.ts +44 -0
package/dist/index.js
CHANGED
|
@@ -26,63 +26,55 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
var import_editor = require("@elementor/editor");
|
|
27
27
|
var import_editor_editing_panel = require("@elementor/editor-editing-panel");
|
|
28
28
|
var import_editor_panels2 = require("@elementor/editor-panels");
|
|
29
|
-
var
|
|
30
|
-
var
|
|
29
|
+
var import_editor_styles_repository2 = require("@elementor/editor-styles-repository");
|
|
30
|
+
var import_editor_v1_adapters2 = require("@elementor/editor-v1-adapters");
|
|
31
|
+
var import_store9 = require("@elementor/store");
|
|
31
32
|
|
|
32
33
|
// src/components/class-manager/class-manager-button.tsx
|
|
33
|
-
var
|
|
34
|
-
var
|
|
35
|
-
var
|
|
34
|
+
var React5 = __toESM(require("react"));
|
|
35
|
+
var import_icons5 = require("@elementor/icons");
|
|
36
|
+
var import_ui5 = require("@elementor/ui");
|
|
37
|
+
var import_i18n5 = require("@wordpress/i18n");
|
|
36
38
|
|
|
37
39
|
// src/components/class-manager/class-manager-panel.tsx
|
|
38
|
-
var
|
|
40
|
+
var React4 = __toESM(require("react"));
|
|
39
41
|
var import_editor_panels = require("@elementor/editor-panels");
|
|
40
|
-
var
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
var { panel, usePanelActions, usePanelStatus } = (0, import_editor_panels.__createPanel)({
|
|
44
|
-
id: "class-manager-panel",
|
|
45
|
-
component: ClassManagerPanel
|
|
46
|
-
});
|
|
47
|
-
function ClassManagerPanel() {
|
|
48
|
-
return /* @__PURE__ */ React.createElement(import_ui.ErrorBoundary, { fallback: /* @__PURE__ */ React.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React.createElement(import_editor_panels.Panel, null, /* @__PURE__ */ React.createElement(import_editor_panels.PanelHeader, null, /* @__PURE__ */ React.createElement(import_ui.Stack, { p: 1, width: "100%", direction: "row", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React.createElement(import_editor_panels.PanelHeaderTitle, null, (0, import_i18n.__)("CSS Class manager")), /* @__PURE__ */ React.createElement(CloseButton, null))), /* @__PURE__ */ React.createElement(import_editor_panels.PanelBody, null)));
|
|
49
|
-
}
|
|
50
|
-
var CloseButton = () => {
|
|
51
|
-
const { close } = usePanelActions();
|
|
52
|
-
return /* @__PURE__ */ React.createElement(import_ui.IconButton, { size: "small", color: "secondary", onClick: close }, /* @__PURE__ */ React.createElement(import_icons.XIcon, { fontSize: "small" }));
|
|
53
|
-
};
|
|
54
|
-
var ErrorBoundaryFallback = () => /* @__PURE__ */ React.createElement(import_ui.Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React.createElement(import_ui.Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React.createElement("strong", null, (0, import_i18n.__)("Something went wrong", "elementor"))));
|
|
42
|
+
var import_icons4 = require("@elementor/icons");
|
|
43
|
+
var import_ui4 = require("@elementor/ui");
|
|
44
|
+
var import_i18n4 = require("@wordpress/i18n");
|
|
55
45
|
|
|
56
|
-
// src/components/class-manager/
|
|
57
|
-
var
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
46
|
+
// src/components/class-manager/global-classes-list.tsx
|
|
47
|
+
var React3 = __toESM(require("react"));
|
|
48
|
+
var import_editor_styles_repository = require("@elementor/editor-styles-repository");
|
|
49
|
+
var import_editor_ui = require("@elementor/editor-ui");
|
|
50
|
+
var import_icons3 = require("@elementor/icons");
|
|
51
|
+
var import_ui3 = require("@elementor/ui");
|
|
52
|
+
var import_i18n3 = require("@wordpress/i18n");
|
|
61
53
|
|
|
62
|
-
// src/
|
|
63
|
-
var
|
|
54
|
+
// src/global-classes-styles-provider.ts
|
|
55
|
+
var import_editor_styles2 = require("@elementor/editor-styles");
|
|
64
56
|
var import_store2 = require("@elementor/store");
|
|
57
|
+
var import_i18n = require("@wordpress/i18n");
|
|
65
58
|
|
|
66
|
-
// src/
|
|
67
|
-
var
|
|
68
|
-
var
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
put: async (id, data) => {
|
|
77
|
-
return (0, import_http.httpService)().put(`${RESOURCE_URL}/${id}`, data);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
59
|
+
// src/errors.ts
|
|
60
|
+
var import_utils = require("@elementor/utils");
|
|
61
|
+
var GlobalClassNotFoundError = (0, import_utils.createError)({
|
|
62
|
+
code: "global_class_not_found",
|
|
63
|
+
message: "Global class not found."
|
|
64
|
+
});
|
|
65
|
+
var GlobalClassLabelAlreadyExistsError = (0, import_utils.createError)({
|
|
66
|
+
code: "global_class_label_already_exists",
|
|
67
|
+
message: "Class with this name already exists."
|
|
68
|
+
});
|
|
80
69
|
|
|
81
70
|
// src/store.ts
|
|
71
|
+
var import_editor_props = require("@elementor/editor-props");
|
|
72
|
+
var import_editor_styles = require("@elementor/editor-styles");
|
|
82
73
|
var import_store = require("@elementor/store");
|
|
83
74
|
var initialState = {
|
|
84
75
|
items: {},
|
|
85
|
-
order: []
|
|
76
|
+
order: [],
|
|
77
|
+
isDirty: false
|
|
86
78
|
};
|
|
87
79
|
var SLICE_NAME = "globalClasses";
|
|
88
80
|
var slice = (0, import_store.__createSlice)({
|
|
@@ -92,91 +84,490 @@ var slice = (0, import_store.__createSlice)({
|
|
|
92
84
|
init(state, { payload }) {
|
|
93
85
|
state.items = payload.items;
|
|
94
86
|
state.order = payload.order;
|
|
87
|
+
state.isDirty = false;
|
|
95
88
|
},
|
|
96
89
|
add(state, { payload }) {
|
|
97
|
-
state.items[payload.
|
|
98
|
-
state.order
|
|
90
|
+
state.items[payload.id] = payload;
|
|
91
|
+
state.order.push(payload.id);
|
|
92
|
+
state.isDirty = true;
|
|
93
|
+
},
|
|
94
|
+
delete(state, { payload }) {
|
|
95
|
+
state.items = Object.fromEntries(Object.entries(state.items).filter(([id]) => id !== payload));
|
|
96
|
+
state.order = state.order.filter((id) => id !== payload);
|
|
97
|
+
state.isDirty = true;
|
|
98
|
+
},
|
|
99
|
+
setOrder(state, { payload }) {
|
|
100
|
+
state.order = payload;
|
|
99
101
|
},
|
|
100
102
|
update(state, { payload }) {
|
|
101
|
-
state.items[payload.style.id]
|
|
102
|
-
|
|
103
|
+
const style = state.items[payload.style.id];
|
|
104
|
+
const mergedData = {
|
|
105
|
+
...style,
|
|
106
|
+
...payload.style
|
|
107
|
+
};
|
|
108
|
+
state.items[payload.style.id] = mergedData;
|
|
109
|
+
state.isDirty = true;
|
|
110
|
+
},
|
|
111
|
+
updateProps(state, {
|
|
112
|
+
payload
|
|
113
|
+
}) {
|
|
114
|
+
const style = state.items[payload.id];
|
|
115
|
+
if (!style) {
|
|
116
|
+
throw new GlobalClassNotFoundError({ context: { styleId: payload.id } });
|
|
117
|
+
}
|
|
118
|
+
const variant = (0, import_editor_styles.getVariantByMeta)(style, payload.meta);
|
|
119
|
+
if (variant) {
|
|
120
|
+
variant.props = (0, import_editor_props.mergeProps)(variant.props, payload.props);
|
|
121
|
+
} else {
|
|
122
|
+
style.variants.push({ meta: payload.meta, props: payload.props });
|
|
123
|
+
}
|
|
124
|
+
state.isDirty = true;
|
|
125
|
+
},
|
|
126
|
+
setPristine(state) {
|
|
127
|
+
state.isDirty = false;
|
|
103
128
|
}
|
|
104
129
|
}
|
|
105
130
|
});
|
|
106
|
-
var selectItems = (state) => state[SLICE_NAME].items;
|
|
107
131
|
var selectOrder = (state) => state[SLICE_NAME].order;
|
|
132
|
+
var selectGlobalClasses = (state) => state[SLICE_NAME].items;
|
|
108
133
|
var selectOrderedGlobalClasses = (0, import_store.__createSelector)(
|
|
109
|
-
|
|
134
|
+
selectGlobalClasses,
|
|
110
135
|
selectOrder,
|
|
111
136
|
(items, order) => order.map((id) => items[id])
|
|
112
137
|
);
|
|
113
|
-
var selectClass = (state, id) => state[SLICE_NAME].items[id];
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const { data, meta } = res.data;
|
|
121
|
-
dispatch2(slice.actions.init({ items: data, order: meta.order }));
|
|
122
|
-
});
|
|
123
|
-
}, [dispatch2]);
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
138
|
+
var selectClass = (state, id) => state[SLICE_NAME].items[id] ?? null;
|
|
139
|
+
var selectIsDirty = (state) => state.globalClasses.isDirty;
|
|
140
|
+
var useOrderedGlobalClasses = () => {
|
|
141
|
+
const items = (0, import_store.__useSelector)(selectOrderedGlobalClasses);
|
|
142
|
+
return items;
|
|
143
|
+
};
|
|
144
|
+
var useGlobalClassesOrder = () => (0, import_store.__useSelector)(selectOrder);
|
|
126
145
|
|
|
127
146
|
// src/global-classes-styles-provider.ts
|
|
128
|
-
var import_store4 = require("@elementor/store");
|
|
129
|
-
var import_i18n2 = require("@wordpress/i18n");
|
|
130
147
|
var globalClassesStylesProvider = {
|
|
131
148
|
key: "global-classes",
|
|
132
149
|
priority: 30,
|
|
133
150
|
actions: {
|
|
134
|
-
get: () => selectOrderedGlobalClasses((0,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
(
|
|
151
|
+
get: () => selectOrderedGlobalClasses((0, import_store2.__getState)()),
|
|
152
|
+
getById: (id) => selectClass((0, import_store2.__getState)(), id),
|
|
153
|
+
create: (label) => {
|
|
154
|
+
const classes = selectGlobalClasses((0, import_store2.__getState)());
|
|
155
|
+
const existingLabels = Object.values(classes).map((style) => style.label);
|
|
156
|
+
if (existingLabels.includes(label)) {
|
|
157
|
+
throw new GlobalClassLabelAlreadyExistsError({ context: { label } });
|
|
158
|
+
}
|
|
159
|
+
const existingIds = Object.keys(classes);
|
|
160
|
+
const id = (0, import_editor_styles2.generateId)("g-", existingIds);
|
|
161
|
+
(0, import_store2.__dispatch)(
|
|
139
162
|
slice.actions.add({
|
|
140
|
-
|
|
141
|
-
|
|
163
|
+
id,
|
|
164
|
+
type: "class",
|
|
165
|
+
label,
|
|
166
|
+
variants: []
|
|
142
167
|
})
|
|
143
168
|
);
|
|
144
|
-
return
|
|
169
|
+
return id;
|
|
145
170
|
},
|
|
146
|
-
update:
|
|
147
|
-
|
|
148
|
-
const mergedData = { ...style, ...payload };
|
|
149
|
-
const res = await apiClient.put(payload.id, mergedData);
|
|
150
|
-
const { data, meta } = res.data;
|
|
151
|
-
(0, import_store4.__dispatch)(
|
|
171
|
+
update: (payload) => {
|
|
172
|
+
(0, import_store2.__dispatch)(
|
|
152
173
|
slice.actions.update({
|
|
153
|
-
style:
|
|
154
|
-
|
|
174
|
+
style: payload
|
|
175
|
+
})
|
|
176
|
+
);
|
|
177
|
+
},
|
|
178
|
+
delete: (id) => {
|
|
179
|
+
(0, import_store2.__dispatch)(slice.actions.delete(id));
|
|
180
|
+
},
|
|
181
|
+
setOrder: (order) => {
|
|
182
|
+
(0, import_store2.__dispatch)(slice.actions.setOrder(order));
|
|
183
|
+
},
|
|
184
|
+
updateProps: (args) => {
|
|
185
|
+
(0, import_store2.__dispatch)(
|
|
186
|
+
slice.actions.updateProps({
|
|
187
|
+
id: args.id,
|
|
188
|
+
meta: args.meta,
|
|
189
|
+
props: args.props
|
|
155
190
|
})
|
|
156
191
|
);
|
|
157
|
-
return data;
|
|
158
192
|
}
|
|
159
193
|
},
|
|
160
|
-
subscribe: (cb) => (0,
|
|
194
|
+
subscribe: (cb) => (0, import_store2.__subscribeWithSelector)((state) => state.globalClasses, cb),
|
|
161
195
|
labels: {
|
|
162
|
-
singular: (0,
|
|
163
|
-
plural: (0,
|
|
196
|
+
singular: (0, import_i18n.__)("Global class", "elementor"),
|
|
197
|
+
plural: (0, import_i18n.__)("Global CSS Classes", "elementor")
|
|
164
198
|
}
|
|
165
199
|
};
|
|
166
200
|
|
|
201
|
+
// src/components/class-manager/delete-confirmation-dialog.tsx
|
|
202
|
+
var React = __toESM(require("react"));
|
|
203
|
+
var import_react = require("react");
|
|
204
|
+
var import_icons = require("@elementor/icons");
|
|
205
|
+
var import_ui = require("@elementor/ui");
|
|
206
|
+
var import_i18n2 = require("@wordpress/i18n");
|
|
207
|
+
var context = (0, import_react.createContext)(null);
|
|
208
|
+
var DeleteConfirmationProvider = ({ children }) => {
|
|
209
|
+
const [dialogProps, setDialogProps] = (0, import_react.useState)(null);
|
|
210
|
+
const openDialog = (props) => {
|
|
211
|
+
setDialogProps(props);
|
|
212
|
+
};
|
|
213
|
+
const closeDialog = () => {
|
|
214
|
+
setDialogProps(null);
|
|
215
|
+
};
|
|
216
|
+
return /* @__PURE__ */ React.createElement(context.Provider, { value: { openDialog, closeDialog, dialogProps } }, children, !!dialogProps && /* @__PURE__ */ React.createElement(DeleteConfirmationDialog, { ...dialogProps }));
|
|
217
|
+
};
|
|
218
|
+
var TITLE_ID = "delete-class-dialog";
|
|
219
|
+
var DeleteConfirmationDialog = ({ label, id }) => {
|
|
220
|
+
const { closeDialog } = useDeleteConfirmation();
|
|
221
|
+
const onConfirm = () => {
|
|
222
|
+
globalClassesStylesProvider.actions.delete(id);
|
|
223
|
+
closeDialog();
|
|
224
|
+
};
|
|
225
|
+
return /* @__PURE__ */ React.createElement(import_ui.Dialog, { open: true, onClose: closeDialog, "aria-labelledby": TITLE_ID, maxWidth: "xs" }, /* @__PURE__ */ React.createElement(import_ui.DialogTitle, { id: TITLE_ID, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React.createElement(import_icons.AlertOctagonFilledIcon, { color: "error" }), (0, import_i18n2.__)("Delete global class", "elementor")), /* @__PURE__ */ React.createElement(import_ui.DialogContent, null, /* @__PURE__ */ React.createElement(import_ui.DialogContentText, { variant: "body2", color: "textPrimary" }, (0, import_i18n2.__)("Deleting", "elementor"), /* @__PURE__ */ React.createElement(import_ui.Typography, { variant: "subtitle2", component: "span" }, "\xA0", label, "\xA0"), (0, import_i18n2.__)(
|
|
226
|
+
"will permanently remove it from your project and may affect the design across all elements using it. This action cannot be undone.",
|
|
227
|
+
"elementor"
|
|
228
|
+
))), /* @__PURE__ */ React.createElement(import_ui.DialogActions, null, /* @__PURE__ */ React.createElement(import_ui.Button, { color: "secondary", onClick: closeDialog }, (0, import_i18n2.__)("Cancel", "elementor")), /* @__PURE__ */ React.createElement(import_ui.Button, { variant: "contained", color: "error", onClick: onConfirm }, (0, import_i18n2.__)("Delete", "elementor"))));
|
|
229
|
+
};
|
|
230
|
+
var useDeleteConfirmation = () => {
|
|
231
|
+
const contextValue = (0, import_react.useContext)(context);
|
|
232
|
+
if (!contextValue) {
|
|
233
|
+
throw new Error("useDeleteConfirmation must be used within a DeleteConfirmationProvider");
|
|
234
|
+
}
|
|
235
|
+
return contextValue;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// src/components/class-manager/sortable.tsx
|
|
239
|
+
var React2 = __toESM(require("react"));
|
|
240
|
+
var import_icons2 = require("@elementor/icons");
|
|
241
|
+
var import_ui2 = require("@elementor/ui");
|
|
242
|
+
var SortableProvider = (props) => /* @__PURE__ */ React2.createElement(import_ui2.UnstableSortableProvider, { restrictAxis: true, variant: "static", dragPlaceholderStyle: { opacity: "1" }, ...props });
|
|
243
|
+
var SortableTrigger = (props) => /* @__PURE__ */ React2.createElement("div", { ...props, role: "button", className: "class-item-sortable-trigger" }, /* @__PURE__ */ React2.createElement(import_icons2.GripVerticalIcon, { fontSize: "tiny" }));
|
|
244
|
+
var SortableItem = ({ children, id }) => {
|
|
245
|
+
return /* @__PURE__ */ React2.createElement(
|
|
246
|
+
import_ui2.UnstableSortableItem,
|
|
247
|
+
{
|
|
248
|
+
id,
|
|
249
|
+
render: ({
|
|
250
|
+
itemProps,
|
|
251
|
+
isDragged,
|
|
252
|
+
triggerProps,
|
|
253
|
+
itemStyle,
|
|
254
|
+
triggerStyle,
|
|
255
|
+
dropIndicationStyle,
|
|
256
|
+
showDropIndication
|
|
257
|
+
}) => {
|
|
258
|
+
return /* @__PURE__ */ React2.createElement(StyledSortableItem, { ...itemProps, elevation: 0, sx: itemStyle, role: "listitem" }, /* @__PURE__ */ React2.createElement(SortableTrigger, { ...triggerProps, style: triggerStyle }), children({
|
|
259
|
+
itemProps,
|
|
260
|
+
isDragged,
|
|
261
|
+
triggerProps,
|
|
262
|
+
itemStyle,
|
|
263
|
+
triggerStyle,
|
|
264
|
+
dropIndicationStyle,
|
|
265
|
+
showDropIndication
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
var StyledSortableItem = (0, import_ui2.styled)(import_ui2.Paper)`
|
|
272
|
+
position: relative;
|
|
273
|
+
|
|
274
|
+
&:hover {
|
|
275
|
+
& .class-item-sortable-trigger {
|
|
276
|
+
visibility: visible;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
& .class-item-sortable-trigger {
|
|
281
|
+
visibility: hidden;
|
|
282
|
+
position: absolute;
|
|
283
|
+
left: 0;
|
|
284
|
+
top: 50%;
|
|
285
|
+
transform: translate( -75%, -50% );
|
|
286
|
+
}
|
|
287
|
+
`;
|
|
288
|
+
var SortableItemIndicator = (0, import_ui2.styled)(import_ui2.Box)`
|
|
289
|
+
width: 100%;
|
|
290
|
+
height: 3px;
|
|
291
|
+
border-radius: ${({ theme }) => theme.spacing(0.5)};
|
|
292
|
+
background-color: ${({ theme }) => theme.palette.text.primary};
|
|
293
|
+
`;
|
|
294
|
+
|
|
295
|
+
// src/components/class-manager/global-classes-list.tsx
|
|
296
|
+
var GlobalClassesList = () => {
|
|
297
|
+
const cssClasses = useOrderedGlobalClasses();
|
|
298
|
+
const [classesOrder, reorderClasses] = useClassesOrder();
|
|
299
|
+
if (!cssClasses?.length) {
|
|
300
|
+
return /* @__PURE__ */ React3.createElement(EmptyState, null);
|
|
301
|
+
}
|
|
302
|
+
return /* @__PURE__ */ React3.createElement(DeleteConfirmationProvider, null, /* @__PURE__ */ React3.createElement(import_ui3.List, { sx: { display: "flex", flexDirection: "column", gap: 0.5 } }, /* @__PURE__ */ React3.createElement(SortableProvider, { value: classesOrder, onChange: reorderClasses }, cssClasses?.map(({ id, label }) => {
|
|
303
|
+
const renameClass = (newLabel) => {
|
|
304
|
+
globalClassesStylesProvider.actions.update({ label: newLabel, id });
|
|
305
|
+
};
|
|
306
|
+
return /* @__PURE__ */ React3.createElement(SortableItem, { key: id, id }, ({ isDragged, showDropIndication, dropIndicationStyle }) => /* @__PURE__ */ React3.createElement(
|
|
307
|
+
ClassItem,
|
|
308
|
+
{
|
|
309
|
+
id,
|
|
310
|
+
label,
|
|
311
|
+
renameClass,
|
|
312
|
+
selected: isDragged
|
|
313
|
+
},
|
|
314
|
+
showDropIndication && /* @__PURE__ */ React3.createElement(SortableItemIndicator, { style: dropIndicationStyle })
|
|
315
|
+
));
|
|
316
|
+
}))));
|
|
317
|
+
};
|
|
318
|
+
var useClassesOrder = () => {
|
|
319
|
+
const order = useGlobalClassesOrder();
|
|
320
|
+
const reorder = (newIds) => {
|
|
321
|
+
globalClassesStylesProvider.actions.setOrder(newIds);
|
|
322
|
+
};
|
|
323
|
+
return [order, reorder];
|
|
324
|
+
};
|
|
325
|
+
var ClassItem = ({
|
|
326
|
+
id,
|
|
327
|
+
label,
|
|
328
|
+
renameClass,
|
|
329
|
+
selected,
|
|
330
|
+
children
|
|
331
|
+
}) => {
|
|
332
|
+
const {
|
|
333
|
+
ref: editableRef,
|
|
334
|
+
openEditMode,
|
|
335
|
+
isEditing,
|
|
336
|
+
error,
|
|
337
|
+
getProps: getEditableProps
|
|
338
|
+
} = (0, import_editor_ui.useEditable)({
|
|
339
|
+
value: label,
|
|
340
|
+
onSubmit: renameClass,
|
|
341
|
+
validation: validateLabel
|
|
342
|
+
});
|
|
343
|
+
const { openDialog } = useDeleteConfirmation();
|
|
344
|
+
const popupState = (0, import_ui3.usePopupState)({
|
|
345
|
+
variant: "popover",
|
|
346
|
+
disableAutoFocus: true
|
|
347
|
+
});
|
|
348
|
+
return /* @__PURE__ */ React3.createElement(import_ui3.Stack, { direction: "row", alignItems: "center", gap: 1, flexGrow: 1, flexShrink: 0 }, /* @__PURE__ */ React3.createElement(
|
|
349
|
+
StyledListItem,
|
|
350
|
+
{
|
|
351
|
+
component: "div",
|
|
352
|
+
disablePadding: true,
|
|
353
|
+
disableGutters: true,
|
|
354
|
+
secondaryAction: /* @__PURE__ */ React3.createElement(
|
|
355
|
+
import_ui3.Tooltip,
|
|
356
|
+
{
|
|
357
|
+
placement: "top",
|
|
358
|
+
className: "class-item-more-actions",
|
|
359
|
+
title: (0, import_i18n3.__)("More actions", "elementor")
|
|
360
|
+
},
|
|
361
|
+
/* @__PURE__ */ React3.createElement(import_ui3.IconButton, { size: "tiny", ...(0, import_ui3.bindTrigger)(popupState), "aria-label": "More actions" }, /* @__PURE__ */ React3.createElement(import_icons3.DotsVerticalIcon, { fontSize: "tiny" }))
|
|
362
|
+
)
|
|
363
|
+
},
|
|
364
|
+
/* @__PURE__ */ React3.createElement(
|
|
365
|
+
import_ui3.ListItemButton,
|
|
366
|
+
{
|
|
367
|
+
dense: true,
|
|
368
|
+
disableGutters: true,
|
|
369
|
+
shape: "rounded",
|
|
370
|
+
onDoubleClick: openEditMode,
|
|
371
|
+
selected: selected || popupState.isOpen,
|
|
372
|
+
focusVisibleClassName: "visible-class-item",
|
|
373
|
+
sx: {
|
|
374
|
+
minHeight: "36px",
|
|
375
|
+
display: "flex",
|
|
376
|
+
"&.visible-class-item": {
|
|
377
|
+
boxShadow: "none !important"
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
/* @__PURE__ */ React3.createElement(Indicator, { isActive: isEditing, isError: !!error }, isEditing ? /* @__PURE__ */ React3.createElement(
|
|
382
|
+
import_editor_ui.EditableField,
|
|
383
|
+
{
|
|
384
|
+
ref: editableRef,
|
|
385
|
+
error,
|
|
386
|
+
as: import_ui3.Typography,
|
|
387
|
+
variant: "caption",
|
|
388
|
+
...getEditableProps()
|
|
389
|
+
}
|
|
390
|
+
) : /* @__PURE__ */ React3.createElement(import_editor_ui.EllipsisWithTooltip, { title: label, as: import_ui3.Typography, variant: "caption" }))
|
|
391
|
+
),
|
|
392
|
+
children,
|
|
393
|
+
/* @__PURE__ */ React3.createElement(
|
|
394
|
+
import_ui3.Menu,
|
|
395
|
+
{
|
|
396
|
+
...(0, import_ui3.bindMenu)(popupState),
|
|
397
|
+
anchorOrigin: {
|
|
398
|
+
vertical: "bottom",
|
|
399
|
+
horizontal: "right"
|
|
400
|
+
},
|
|
401
|
+
transformOrigin: {
|
|
402
|
+
vertical: "top",
|
|
403
|
+
horizontal: "right"
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
/* @__PURE__ */ React3.createElement(
|
|
407
|
+
import_ui3.MenuItem,
|
|
408
|
+
{
|
|
409
|
+
sx: { minWidth: "160px" },
|
|
410
|
+
onClick: () => {
|
|
411
|
+
popupState.close();
|
|
412
|
+
openEditMode();
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
/* @__PURE__ */ React3.createElement(import_ui3.ListItemText, { primary: (0, import_i18n3.__)("Rename", "elementor") })
|
|
416
|
+
),
|
|
417
|
+
/* @__PURE__ */ React3.createElement(
|
|
418
|
+
import_ui3.MenuItem,
|
|
419
|
+
{
|
|
420
|
+
onClick: () => {
|
|
421
|
+
popupState.close();
|
|
422
|
+
openDialog({ id, label });
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
/* @__PURE__ */ React3.createElement(import_ui3.ListItemText, { primary: (0, import_i18n3.__)("Delete", "elementor"), sx: { color: "error.light" } })
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
));
|
|
429
|
+
};
|
|
430
|
+
var StyledListItem = (0, import_ui3.styled)(import_ui3.ListItem)`
|
|
431
|
+
.class-item-more-actions {
|
|
432
|
+
visibility: hidden;
|
|
433
|
+
}
|
|
434
|
+
&:hover {
|
|
435
|
+
.class-item-more-actions {
|
|
436
|
+
visibility: visible;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
`;
|
|
440
|
+
var EmptyState = () => /* @__PURE__ */ React3.createElement(import_ui3.Stack, { alignItems: "center", gap: 3, pt: 4, px: 0.5 }, /* @__PURE__ */ React3.createElement(import_icons3.PhotoIcon, { fontSize: "large" }), /* @__PURE__ */ React3.createElement(StyledHeader, { variant: "subtitle2", component: "h2", color: "text.secondary" }, (0, import_i18n3.__)("No CSS classes created yet", "elementor")), /* @__PURE__ */ React3.createElement(import_ui3.Typography, { align: "center", variant: "caption", color: "text.secondary" }, (0, import_i18n3.__)(
|
|
441
|
+
"CSS classes created in the editor panel will appear here. Once they are available, you can arrange their hierarchy, rename them, or delete them as needed.",
|
|
442
|
+
"elementor"
|
|
443
|
+
)));
|
|
444
|
+
var StyledHeader = (0, import_ui3.styled)(import_ui3.Typography)(({ theme, variant }) => ({
|
|
445
|
+
"&.MuiTypography-root": {
|
|
446
|
+
...theme.typography[variant]
|
|
447
|
+
}
|
|
448
|
+
}));
|
|
449
|
+
var Indicator = (0, import_ui3.styled)(import_ui3.Box, {
|
|
450
|
+
shouldForwardProp: (prop) => !["isActive", "isError"].includes(prop)
|
|
451
|
+
})(({ theme, isActive, isError }) => ({
|
|
452
|
+
display: "flex",
|
|
453
|
+
width: "100%",
|
|
454
|
+
flexGrow: 1,
|
|
455
|
+
borderRadius: theme.spacing(0.5),
|
|
456
|
+
border: getIndicatorBorder({ isActive, isError, theme }),
|
|
457
|
+
padding: `0 ${theme.spacing(1)}`,
|
|
458
|
+
marginLeft: isActive ? theme.spacing(1) : 0
|
|
459
|
+
}));
|
|
460
|
+
var getIndicatorBorder = ({ isActive, isError, theme }) => {
|
|
461
|
+
if (isError) {
|
|
462
|
+
return `2px solid ${theme.palette.error.main}`;
|
|
463
|
+
}
|
|
464
|
+
if (isActive) {
|
|
465
|
+
return `2px solid ${theme.palette.secondary.main}`;
|
|
466
|
+
}
|
|
467
|
+
return "none";
|
|
468
|
+
};
|
|
469
|
+
var validateLabel = (newLabel) => {
|
|
470
|
+
if (!import_editor_styles_repository.stylesRepository.isLabelValid(newLabel)) {
|
|
471
|
+
return (0, import_i18n3.__)("Format is not valid", "elementor");
|
|
472
|
+
}
|
|
473
|
+
if (import_editor_styles_repository.stylesRepository.isLabelExist(newLabel)) {
|
|
474
|
+
return (0, import_i18n3.__)("Existing name", "elementor");
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// src/components/class-manager/class-manager-panel.tsx
|
|
479
|
+
var { panel, usePanelActions } = (0, import_editor_panels.__createPanel)({
|
|
480
|
+
id: "class-manager-panel",
|
|
481
|
+
component: ClassManagerPanel
|
|
482
|
+
});
|
|
483
|
+
function ClassManagerPanel() {
|
|
484
|
+
return /* @__PURE__ */ React4.createElement(import_ui4.ErrorBoundary, { fallback: /* @__PURE__ */ React4.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React4.createElement(import_editor_panels.Panel, null, /* @__PURE__ */ React4.createElement(import_editor_panels.PanelHeader, null, /* @__PURE__ */ React4.createElement(import_ui4.Stack, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React4.createElement(import_editor_panels.PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React4.createElement(import_icons4.ColorSwatchIcon, { fontSize: "inherit", sx: { transform: "rotate(90deg)" } }), (0, import_i18n4.__)("CSS Class manager")), /* @__PURE__ */ React4.createElement(CloseButton, { sx: { marginLeft: "auto" } }))), /* @__PURE__ */ React4.createElement(import_editor_panels.PanelBody, { px: 2 }, /* @__PURE__ */ React4.createElement(GlobalClassesList, null))));
|
|
485
|
+
}
|
|
486
|
+
var CloseButton = (props) => {
|
|
487
|
+
const { close } = usePanelActions();
|
|
488
|
+
return /* @__PURE__ */ React4.createElement(import_ui4.IconButton, { size: "small", color: "secondary", onClick: close, ...props }, /* @__PURE__ */ React4.createElement(import_icons4.XIcon, { fontSize: "small" }));
|
|
489
|
+
};
|
|
490
|
+
var ErrorBoundaryFallback = () => /* @__PURE__ */ React4.createElement(import_ui4.Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React4.createElement(import_ui4.Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React4.createElement("strong", null, (0, import_i18n4.__)("Something went wrong", "elementor"))));
|
|
491
|
+
|
|
492
|
+
// src/components/class-manager/class-manager-button.tsx
|
|
493
|
+
var ClassManagerButton = () => {
|
|
494
|
+
const { open } = usePanelActions();
|
|
495
|
+
return /* @__PURE__ */ React5.createElement(import_ui5.Tooltip, { title: (0, import_i18n5.__)("Class manager"), placement: "top" }, /* @__PURE__ */ React5.createElement(import_ui5.IconButton, { onClick: open }, /* @__PURE__ */ React5.createElement(import_icons5.ColorSwatchIcon, { fontSize: "tiny" })));
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
// src/components/populate-store.tsx
|
|
499
|
+
var import_react2 = require("react");
|
|
500
|
+
var import_store5 = require("@elementor/store");
|
|
501
|
+
|
|
502
|
+
// src/api.ts
|
|
503
|
+
var import_http = require("@elementor/http");
|
|
504
|
+
var RESOURCE_URL = "/global-classes";
|
|
505
|
+
var apiClient = {
|
|
506
|
+
all: () => (0, import_http.httpService)().get("elementor/v1" + RESOURCE_URL),
|
|
507
|
+
update: (payload) => (0, import_http.httpService)().put("elementor/v1" + RESOURCE_URL, payload)
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
// src/components/populate-store.tsx
|
|
511
|
+
function PopulateStore() {
|
|
512
|
+
const dispatch2 = (0, import_store5.__useDispatch)();
|
|
513
|
+
(0, import_react2.useEffect)(() => {
|
|
514
|
+
apiClient.all().then((res) => {
|
|
515
|
+
const { data, meta } = res.data;
|
|
516
|
+
dispatch2(slice.actions.init({ items: data, order: meta.order }));
|
|
517
|
+
});
|
|
518
|
+
}, [dispatch2]);
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// src/sync-with-document-save.ts
|
|
523
|
+
var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
|
|
524
|
+
var import_store7 = require("@elementor/store");
|
|
525
|
+
function syncWithDocumentSave() {
|
|
526
|
+
const unsubscribe = syncDirtyState();
|
|
527
|
+
bindSaveAction();
|
|
528
|
+
return unsubscribe;
|
|
529
|
+
}
|
|
530
|
+
function syncDirtyState() {
|
|
531
|
+
return (0, import_store7.__subscribeWithSelector)(selectIsDirty, () => {
|
|
532
|
+
if (!isDirty()) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
(0, import_editor_v1_adapters.__privateRunCommandSync)("document/save/set-is-modified", { status: true }, { internal: true });
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
function bindSaveAction() {
|
|
539
|
+
(0, import_editor_v1_adapters.registerDataHook)("after", "document/save/save", async () => {
|
|
540
|
+
if (!isDirty()) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const state = (0, import_store7.__getState)().globalClasses;
|
|
544
|
+
await apiClient.update({
|
|
545
|
+
items: state.items,
|
|
546
|
+
order: state.order
|
|
547
|
+
});
|
|
548
|
+
(0, import_store7.__dispatch)(slice.actions.setPristine());
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
function isDirty() {
|
|
552
|
+
return selectIsDirty((0, import_store7.__getState)());
|
|
553
|
+
}
|
|
554
|
+
|
|
167
555
|
// src/init.ts
|
|
168
556
|
function init() {
|
|
169
|
-
(0,
|
|
557
|
+
(0, import_store9.__registerSlice)(slice);
|
|
170
558
|
(0, import_editor_panels2.__registerPanel)(panel);
|
|
171
|
-
|
|
559
|
+
import_editor_styles_repository2.stylesRepository.register(globalClassesStylesProvider);
|
|
172
560
|
(0, import_editor.injectIntoLogic)({
|
|
173
|
-
id: "global-classes-
|
|
174
|
-
component:
|
|
561
|
+
id: "global-classes-populate-store",
|
|
562
|
+
component: PopulateStore
|
|
175
563
|
});
|
|
176
564
|
(0, import_editor_editing_panel.injectIntoClassSelectorActions)({
|
|
177
|
-
id: "global-classes",
|
|
565
|
+
id: "global-classes-manager-button",
|
|
178
566
|
component: ClassManagerButton
|
|
179
567
|
});
|
|
568
|
+
(0, import_editor_v1_adapters2.__privateListenTo)((0, import_editor_v1_adapters2.v1ReadyEvent)(), () => {
|
|
569
|
+
syncWithDocumentSave();
|
|
570
|
+
});
|
|
180
571
|
}
|
|
181
572
|
|
|
182
573
|
// src/index.ts
|