@elementor/editor-global-classes 0.20.4 → 0.21.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 +45 -0
- package/dist/index.js +145 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +154 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -11
- package/src/components/class-manager/class-manager-panel.tsx +27 -5
- package/src/components/class-manager/global-classes-list.tsx +19 -1
- package/src/components/class-manager/save-changes-dialog.tsx +13 -5
- package/src/global-classes-styles-provider.ts +3 -1
- package/src/init.ts +7 -2
- package/src/store.ts +39 -0
- package/src/utils/snapshot-history.ts +73 -0
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/init.ts
|
|
2
2
|
import { injectIntoLogic } from "@elementor/editor";
|
|
3
|
-
import { injectIntoClassSelectorActions } from "@elementor/editor-editing-panel";
|
|
3
|
+
import { injectIntoClassSelectorActions, registerStyleProviderToColors } from "@elementor/editor-editing-panel";
|
|
4
4
|
import { __registerPanel as registerPanel } from "@elementor/editor-panels";
|
|
5
5
|
import { stylesRepository } from "@elementor/editor-styles-repository";
|
|
6
6
|
import { __privateListenTo as listenTo, v1ReadyEvent } from "@elementor/editor-v1-adapters";
|
|
@@ -63,6 +63,69 @@ import {
|
|
|
63
63
|
__createSelector as createSelector,
|
|
64
64
|
__createSlice as createSlice
|
|
65
65
|
} from "@elementor/store";
|
|
66
|
+
|
|
67
|
+
// src/utils/snapshot-history.ts
|
|
68
|
+
function createLink({ value, next, prev }) {
|
|
69
|
+
return {
|
|
70
|
+
value,
|
|
71
|
+
prev: prev || null,
|
|
72
|
+
next: next || null
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
var SnapshotHistory = class _SnapshotHistory {
|
|
76
|
+
constructor(namespace) {
|
|
77
|
+
this.namespace = namespace;
|
|
78
|
+
}
|
|
79
|
+
static registry = {};
|
|
80
|
+
static get(namespace) {
|
|
81
|
+
if (!_SnapshotHistory.registry[namespace]) {
|
|
82
|
+
_SnapshotHistory.registry[namespace] = new _SnapshotHistory(namespace);
|
|
83
|
+
}
|
|
84
|
+
return _SnapshotHistory.registry[namespace];
|
|
85
|
+
}
|
|
86
|
+
first = null;
|
|
87
|
+
current = null;
|
|
88
|
+
transform(item) {
|
|
89
|
+
return JSON.parse(JSON.stringify(item));
|
|
90
|
+
}
|
|
91
|
+
reset() {
|
|
92
|
+
this.first = this.current = null;
|
|
93
|
+
}
|
|
94
|
+
prev() {
|
|
95
|
+
if (!this.current || this.current === this.first) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
this.current = this.current.prev;
|
|
99
|
+
return this.current?.value || null;
|
|
100
|
+
}
|
|
101
|
+
isLast() {
|
|
102
|
+
return !this.current || !this.current.next;
|
|
103
|
+
}
|
|
104
|
+
next(value) {
|
|
105
|
+
if (value) {
|
|
106
|
+
if (!this.current) {
|
|
107
|
+
this.first = createLink({ value: this.transform(value) });
|
|
108
|
+
this.current = this.first;
|
|
109
|
+
return this.current.value;
|
|
110
|
+
}
|
|
111
|
+
const nextLink = createLink({
|
|
112
|
+
value: this.transform(value),
|
|
113
|
+
prev: this.current
|
|
114
|
+
});
|
|
115
|
+
this.current.next = nextLink;
|
|
116
|
+
this.current = nextLink;
|
|
117
|
+
return this.current.value;
|
|
118
|
+
}
|
|
119
|
+
if (!this.current || !this.current.next) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
this.current = this.current.next;
|
|
123
|
+
return this.current.value;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// src/store.ts
|
|
128
|
+
var localHistory = SnapshotHistory.get("global-classes");
|
|
66
129
|
var initialState = {
|
|
67
130
|
data: { items: {}, order: [] },
|
|
68
131
|
initialData: {
|
|
@@ -85,11 +148,13 @@ var slice = createSlice({
|
|
|
85
148
|
state.isDirty = false;
|
|
86
149
|
},
|
|
87
150
|
add(state, { payload }) {
|
|
151
|
+
localHistory.next(state.data);
|
|
88
152
|
state.data.items[payload.id] = payload;
|
|
89
153
|
state.data.order.unshift(payload.id);
|
|
90
154
|
state.isDirty = true;
|
|
91
155
|
},
|
|
92
156
|
delete(state, { payload }) {
|
|
157
|
+
localHistory.next(state.data);
|
|
93
158
|
state.data.items = Object.fromEntries(
|
|
94
159
|
Object.entries(state.data.items).filter(([id2]) => id2 !== payload)
|
|
95
160
|
);
|
|
@@ -97,10 +162,12 @@ var slice = createSlice({
|
|
|
97
162
|
state.isDirty = true;
|
|
98
163
|
},
|
|
99
164
|
setOrder(state, { payload }) {
|
|
165
|
+
localHistory.next(state.data);
|
|
100
166
|
state.data.order = payload;
|
|
101
167
|
state.isDirty = true;
|
|
102
168
|
},
|
|
103
169
|
update(state, { payload }) {
|
|
170
|
+
localHistory.next(state.data);
|
|
104
171
|
const style = state.data.items[payload.style.id];
|
|
105
172
|
const mergedData = {
|
|
106
173
|
...style,
|
|
@@ -116,6 +183,7 @@ var slice = createSlice({
|
|
|
116
183
|
if (!style) {
|
|
117
184
|
throw new GlobalClassNotFoundError({ context: { styleId: payload.id } });
|
|
118
185
|
}
|
|
186
|
+
localHistory.next(state.data);
|
|
119
187
|
const variant = getVariantByMeta(style, payload.meta);
|
|
120
188
|
if (variant) {
|
|
121
189
|
variant.props = mergeProps(variant.props, payload.props);
|
|
@@ -129,10 +197,38 @@ var slice = createSlice({
|
|
|
129
197
|
},
|
|
130
198
|
reset(state, { payload: { context: context2 } }) {
|
|
131
199
|
if (context2 === "frontend") {
|
|
200
|
+
localHistory.reset();
|
|
132
201
|
state.initialData.frontend = state.data;
|
|
133
202
|
state.isDirty = false;
|
|
134
203
|
}
|
|
135
204
|
state.initialData.preview = state.data;
|
|
205
|
+
},
|
|
206
|
+
undo(state) {
|
|
207
|
+
if (localHistory.isLast()) {
|
|
208
|
+
localHistory.next(state.data);
|
|
209
|
+
}
|
|
210
|
+
const data = localHistory.prev();
|
|
211
|
+
if (data) {
|
|
212
|
+
state.data = data;
|
|
213
|
+
state.isDirty = true;
|
|
214
|
+
} else {
|
|
215
|
+
state.data = state.initialData.preview;
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
resetToInitialState(state, { payload: { context: context2 } }) {
|
|
219
|
+
localHistory.reset();
|
|
220
|
+
state.data = state.initialData[context2];
|
|
221
|
+
state.isDirty = false;
|
|
222
|
+
},
|
|
223
|
+
redo(state) {
|
|
224
|
+
const data = localHistory.next();
|
|
225
|
+
if (localHistory.isLast()) {
|
|
226
|
+
localHistory.prev();
|
|
227
|
+
}
|
|
228
|
+
if (data) {
|
|
229
|
+
state.data = data;
|
|
230
|
+
state.isDirty = true;
|
|
231
|
+
}
|
|
136
232
|
}
|
|
137
233
|
}
|
|
138
234
|
});
|
|
@@ -151,8 +247,9 @@ var selectClass = (state, id2) => state[SLICE_NAME].data.items[id2] ?? null;
|
|
|
151
247
|
|
|
152
248
|
// src/global-classes-styles-provider.ts
|
|
153
249
|
var MAX_CLASSES = 50;
|
|
250
|
+
var GLOBAL_CLASSES_PROVIDER_KEY = "global-classes";
|
|
154
251
|
var globalClassesStylesProvider = createStylesProvider({
|
|
155
|
-
key:
|
|
252
|
+
key: GLOBAL_CLASSES_PROVIDER_KEY,
|
|
156
253
|
priority: 30,
|
|
157
254
|
limit: MAX_CLASSES,
|
|
158
255
|
labels: {
|
|
@@ -212,7 +309,7 @@ var globalClassesStylesProvider = createStylesProvider({
|
|
|
212
309
|
|
|
213
310
|
// src/components/class-manager/class-manager-panel.tsx
|
|
214
311
|
import * as React7 from "react";
|
|
215
|
-
import { useEffect } from "react";
|
|
312
|
+
import { useEffect as useEffect2 } from "react";
|
|
216
313
|
import { setDocumentModifiedStatus } from "@elementor/editor-documents";
|
|
217
314
|
import {
|
|
218
315
|
__createPanel as createPanel,
|
|
@@ -226,7 +323,16 @@ import { ThemeProvider } from "@elementor/editor-ui";
|
|
|
226
323
|
import { changeEditMode } from "@elementor/editor-v1-adapters";
|
|
227
324
|
import { XIcon } from "@elementor/icons";
|
|
228
325
|
import { useMutation } from "@elementor/query";
|
|
229
|
-
import {
|
|
326
|
+
import { __dispatch as dispatch4 } from "@elementor/store";
|
|
327
|
+
import {
|
|
328
|
+
Alert,
|
|
329
|
+
Box as Box4,
|
|
330
|
+
Button as Button3,
|
|
331
|
+
DialogHeader,
|
|
332
|
+
ErrorBoundary,
|
|
333
|
+
IconButton as IconButton2,
|
|
334
|
+
Stack as Stack2
|
|
335
|
+
} from "@elementor/ui";
|
|
230
336
|
import { __ as __5 } from "@wordpress/i18n";
|
|
231
337
|
|
|
232
338
|
// src/hooks/use-dirty-state.ts
|
|
@@ -375,7 +481,7 @@ var FlippedColorSwatchIcon = ({ sx, ...props }) => /* @__PURE__ */ React2.create
|
|
|
375
481
|
|
|
376
482
|
// src/components/class-manager/global-classes-list.tsx
|
|
377
483
|
import * as React5 from "react";
|
|
378
|
-
import { useRef } from "react";
|
|
484
|
+
import { useEffect, useRef } from "react";
|
|
379
485
|
import { validateStyleLabel } from "@elementor/editor-styles-repository";
|
|
380
486
|
import { EditableField, EllipsisWithTooltip, MenuListItem, useEditable, WarningInfotip } from "@elementor/editor-ui";
|
|
381
487
|
import { DotsVerticalIcon } from "@elementor/icons";
|
|
@@ -522,14 +628,31 @@ var SortableItemIndicator = styled(Box2)`
|
|
|
522
628
|
// src/components/class-manager/global-classes-list.tsx
|
|
523
629
|
var GlobalClassesList = ({ disabled }) => {
|
|
524
630
|
const cssClasses = useOrderedClasses();
|
|
525
|
-
const
|
|
631
|
+
const dispatch5 = useDispatch();
|
|
526
632
|
const [classesOrder, reorderClasses] = useReorder();
|
|
633
|
+
useEffect(() => {
|
|
634
|
+
const handler = (event) => {
|
|
635
|
+
if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
|
|
636
|
+
event.stopImmediatePropagation();
|
|
637
|
+
event.preventDefault();
|
|
638
|
+
if (event.shiftKey) {
|
|
639
|
+
dispatch5(slice.actions.redo());
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
dispatch5(slice.actions.undo());
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
window.addEventListener("keydown", handler, {
|
|
646
|
+
capture: true
|
|
647
|
+
});
|
|
648
|
+
return () => window.removeEventListener("keydown", handler);
|
|
649
|
+
}, [dispatch5]);
|
|
527
650
|
if (!cssClasses?.length) {
|
|
528
651
|
return /* @__PURE__ */ React5.createElement(EmptyState, null);
|
|
529
652
|
}
|
|
530
653
|
return /* @__PURE__ */ React5.createElement(DeleteConfirmationProvider, null, /* @__PURE__ */ React5.createElement(List, { sx: { display: "flex", flexDirection: "column", gap: 0.5 } }, /* @__PURE__ */ React5.createElement(SortableProvider, { value: classesOrder, onChange: reorderClasses }, cssClasses?.map(({ id: id2, label }) => {
|
|
531
654
|
const renameClass = (newLabel) => {
|
|
532
|
-
|
|
655
|
+
dispatch5(
|
|
533
656
|
slice.actions.update({
|
|
534
657
|
style: {
|
|
535
658
|
id: id2,
|
|
@@ -552,10 +675,10 @@ var GlobalClassesList = ({ disabled }) => {
|
|
|
552
675
|
}))));
|
|
553
676
|
};
|
|
554
677
|
var useReorder = () => {
|
|
555
|
-
const
|
|
678
|
+
const dispatch5 = useDispatch();
|
|
556
679
|
const order = useClassesOrder();
|
|
557
680
|
const reorder = (newIds) => {
|
|
558
|
-
|
|
681
|
+
dispatch5(slice.actions.setOrder(newIds));
|
|
559
682
|
};
|
|
560
683
|
return [order, reorder];
|
|
561
684
|
};
|
|
@@ -748,13 +871,13 @@ var SaveChangesDialogContent = ({ children }) => /* @__PURE__ */ React6.createEl
|
|
|
748
871
|
var SaveChangesDialogContentText = (props) => /* @__PURE__ */ React6.createElement(DialogContentText2, { variant: "body2", color: "textPrimary", display: "flex", flexDirection: "column", ...props });
|
|
749
872
|
var SaveChangesDialogActions = ({ actions }) => {
|
|
750
873
|
const [isConfirming, setIsConfirming] = useState3(false);
|
|
751
|
-
const { cancel, confirm } = actions;
|
|
874
|
+
const { cancel, confirm, discard } = actions;
|
|
752
875
|
const onConfirm = async () => {
|
|
753
876
|
setIsConfirming(true);
|
|
754
877
|
await confirm.action();
|
|
755
878
|
setIsConfirming(false);
|
|
756
879
|
};
|
|
757
|
-
return /* @__PURE__ */ React6.createElement(DialogActions2, null, /* @__PURE__ */ React6.createElement(Button2, { variant: "text", color: "secondary", onClick: cancel.action }, cancel.label), /* @__PURE__ */ React6.createElement(Button2, { variant: "contained", color: "secondary", onClick: onConfirm, loading: isConfirming }, confirm.label));
|
|
880
|
+
return /* @__PURE__ */ React6.createElement(DialogActions2, null, cancel && /* @__PURE__ */ React6.createElement(Button2, { variant: "text", color: "secondary", onClick: cancel.action }, cancel.label), discard && /* @__PURE__ */ React6.createElement(Button2, { variant: "text", color: "secondary", onClick: discard.action }, discard.label), /* @__PURE__ */ React6.createElement(Button2, { variant: "contained", color: "secondary", onClick: onConfirm, loading: isConfirming }, confirm.label));
|
|
758
881
|
};
|
|
759
882
|
SaveChangesDialog.Title = SaveChangesDialogTitle;
|
|
760
883
|
SaveChangesDialog.Content = SaveChangesDialogContent;
|
|
@@ -787,6 +910,10 @@ function ClassManagerPanel() {
|
|
|
787
910
|
const { close: closePanel } = usePanelActions();
|
|
788
911
|
const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
|
|
789
912
|
const { mutateAsync: publish, isPending: isPublishing } = usePublish();
|
|
913
|
+
const resetAndClosePanel = () => {
|
|
914
|
+
dispatch4(slice.actions.resetToInitialState({ context: "frontend" }));
|
|
915
|
+
closeSaveChangesDialog();
|
|
916
|
+
};
|
|
790
917
|
usePreventUnload();
|
|
791
918
|
return /* @__PURE__ */ React7.createElement(ThemeProvider, null, /* @__PURE__ */ React7.createElement(ErrorBoundary, { fallback: /* @__PURE__ */ React7.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React7.createElement(Panel, null, /* @__PURE__ */ React7.createElement(PanelHeader, null, /* @__PURE__ */ React7.createElement(Stack2, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React7.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React7.createElement(FlippedColorSwatchIcon, { fontSize: "inherit" }), __5("Class Manager", "elementor")), /* @__PURE__ */ React7.createElement(
|
|
792
919
|
CloseButton,
|
|
@@ -813,13 +940,15 @@ function ClassManagerPanel() {
|
|
|
813
940
|
loading: isPublishing
|
|
814
941
|
},
|
|
815
942
|
__5("Save changes", "elementor")
|
|
816
|
-
)))), /* @__PURE__ */ React7.createElement(ClassManagerIntroduction, null), isSaveChangesDialogOpen && /* @__PURE__ */ React7.createElement(SaveChangesDialog, null, /* @__PURE__ */ React7.createElement(SaveChangesDialog.Title, null, __5("You have unsaved changes", "elementor")), /* @__PURE__ */ React7.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React7.createElement(SaveChangesDialog.ContentText, null, __5("You have unsaved changes in the Class Manager.", "elementor")), /* @__PURE__ */ React7.createElement(SaveChangesDialog.ContentText, null, __5("To avoid losing your updates, save your changes before leaving.", "elementor"))), /* @__PURE__ */ React7.createElement(
|
|
943
|
+
)))), /* @__PURE__ */ React7.createElement(ClassManagerIntroduction, null), isSaveChangesDialogOpen && /* @__PURE__ */ React7.createElement(SaveChangesDialog, null, /* @__PURE__ */ React7.createElement(DialogHeader, { onClose: closeSaveChangesDialog, logo: false }, /* @__PURE__ */ React7.createElement(SaveChangesDialog.Title, null, __5("You have unsaved changes", "elementor"))), /* @__PURE__ */ React7.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React7.createElement(SaveChangesDialog.ContentText, null, __5("You have unsaved changes in the Class Manager.", "elementor")), /* @__PURE__ */ React7.createElement(SaveChangesDialog.ContentText, null, __5("To avoid losing your updates, save your changes before leaving.", "elementor"))), /* @__PURE__ */ React7.createElement(
|
|
817
944
|
SaveChangesDialog.Actions,
|
|
818
945
|
{
|
|
819
946
|
actions: {
|
|
820
|
-
|
|
821
|
-
label: __5("
|
|
822
|
-
action:
|
|
947
|
+
discard: {
|
|
948
|
+
label: __5("Discard", "elementor"),
|
|
949
|
+
action: () => {
|
|
950
|
+
resetAndClosePanel();
|
|
951
|
+
}
|
|
823
952
|
},
|
|
824
953
|
confirm: {
|
|
825
954
|
label: __5("Save & Continue", "elementor"),
|
|
@@ -837,7 +966,7 @@ var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React7.createElemen
|
|
|
837
966
|
var ErrorBoundaryFallback = () => /* @__PURE__ */ React7.createElement(Box4, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React7.createElement(Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React7.createElement("strong", null, __5("Something went wrong", "elementor"))));
|
|
838
967
|
var usePreventUnload = () => {
|
|
839
968
|
const isDirty2 = useDirtyState();
|
|
840
|
-
|
|
969
|
+
useEffect2(() => {
|
|
841
970
|
const handleBeforeUnload = (event) => {
|
|
842
971
|
if (isDirty2) {
|
|
843
972
|
event.preventDefault();
|
|
@@ -904,16 +1033,16 @@ var ClassManagerButton = () => {
|
|
|
904
1033
|
};
|
|
905
1034
|
|
|
906
1035
|
// src/components/populate-store.tsx
|
|
907
|
-
import { useEffect as
|
|
1036
|
+
import { useEffect as useEffect3 } from "react";
|
|
908
1037
|
import { __useDispatch as useDispatch2 } from "@elementor/store";
|
|
909
1038
|
function PopulateStore() {
|
|
910
|
-
const
|
|
911
|
-
|
|
1039
|
+
const dispatch5 = useDispatch2();
|
|
1040
|
+
useEffect3(() => {
|
|
912
1041
|
Promise.all([apiClient.all("preview"), apiClient.all("frontend")]).then(
|
|
913
1042
|
([previewRes, frontendRes]) => {
|
|
914
1043
|
const { data: previewData } = previewRes;
|
|
915
1044
|
const { data: frontendData } = frontendRes;
|
|
916
|
-
|
|
1045
|
+
dispatch5(
|
|
917
1046
|
slice.actions.load({
|
|
918
1047
|
preview: {
|
|
919
1048
|
items: previewData.data,
|
|
@@ -927,7 +1056,7 @@ function PopulateStore() {
|
|
|
927
1056
|
);
|
|
928
1057
|
}
|
|
929
1058
|
);
|
|
930
|
-
}, [
|
|
1059
|
+
}, [dispatch5]);
|
|
931
1060
|
return null;
|
|
932
1061
|
}
|
|
933
1062
|
|
|
@@ -972,6 +1101,10 @@ function init() {
|
|
|
972
1101
|
id: "global-classes-manager-button",
|
|
973
1102
|
component: ClassManagerButton
|
|
974
1103
|
});
|
|
1104
|
+
registerStyleProviderToColors(GLOBAL_CLASSES_PROVIDER_KEY, {
|
|
1105
|
+
name: "global",
|
|
1106
|
+
getThemeColor: (theme) => theme.palette.global.dark
|
|
1107
|
+
});
|
|
975
1108
|
listenTo(v1ReadyEvent(), () => {
|
|
976
1109
|
syncWithDocumentSave();
|
|
977
1110
|
});
|