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