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