@elementor/editor-default-styles 4.3.0-1042

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.mjs ADDED
@@ -0,0 +1,802 @@
1
+ // src/init.ts
2
+ import { injectIntoLogic } from "@elementor/editor";
3
+ import { toolsMenu } from "@elementor/editor-app-bar";
4
+ import { registerElementPanelDefaults, STYLE_SECTION_NAMES } from "@elementor/editor-editing-panel";
5
+ import { __registerPanel as registerPanel } from "@elementor/editor-panels";
6
+ import { stylesRepository } from "@elementor/editor-styles-repository";
7
+ import { __registerSlice as registerSlice } from "@elementor/store";
8
+
9
+ // src/components/populate-store.tsx
10
+ import { useEffect } from "react";
11
+ import { __privateListenTo as listenTo, registerDataHook, routeCloseEvent } from "@elementor/editor-v1-adapters";
12
+ import { __getState as getState } from "@elementor/store";
13
+
14
+ // src/load-default-styles.ts
15
+ import { __dispatch as dispatch } from "@elementor/store";
16
+
17
+ // src/api.ts
18
+ import { httpService } from "@elementor/http-client";
19
+ var RESOURCE_URL = "/default-styles";
20
+ var BASE_URL = "elementor/v1";
21
+ var apiClient = {
22
+ all: () => httpService().get(`${BASE_URL}${RESOURCE_URL}`),
23
+ put: (tag, variants) => httpService().put(`${BASE_URL}${RESOURCE_URL}/${tag}`, {
24
+ type: "class",
25
+ variants
26
+ }),
27
+ delete: (tag) => httpService().delete(`${BASE_URL}${RESOURCE_URL}/${tag}`)
28
+ };
29
+
30
+ // src/store.ts
31
+ import {
32
+ getVariantByMeta
33
+ } from "@elementor/editor-styles";
34
+ import {
35
+ __createSelector as createSelector,
36
+ __createSlice as createSlice
37
+ } from "@elementor/store";
38
+ var initialState = {
39
+ data: {},
40
+ initialData: {},
41
+ isDirty: false
42
+ };
43
+ var SLICE_NAME = "defaultStyles";
44
+ var slice = createSlice({
45
+ name: SLICE_NAME,
46
+ initialState,
47
+ reducers: {
48
+ load(state, {
49
+ payload: { data }
50
+ }) {
51
+ state.initialData = structuredClone(data);
52
+ state.data = structuredClone(data);
53
+ state.isDirty = false;
54
+ },
55
+ update(state, { payload }) {
56
+ state.data[payload.style.id] = {
57
+ ...state.data[payload.style.id],
58
+ ...payload.style
59
+ };
60
+ state.isDirty = true;
61
+ },
62
+ updateProps(state, {
63
+ payload
64
+ }) {
65
+ const style = state.data[payload.id] ?? {
66
+ id: payload.id,
67
+ label: payload.id,
68
+ type: "class",
69
+ variants: []
70
+ };
71
+ const variant = getVariantByMeta(style, payload.meta);
72
+ let customCss = ("custom_css" in payload ? payload.custom_css : variant?.custom_css) ?? null;
73
+ customCss = customCss?.raw ? customCss : null;
74
+ if (variant) {
75
+ const payloadProps = JSON.parse(JSON.stringify(payload.props));
76
+ const mode = payload.mode ?? "merge";
77
+ if (mode === "replace") {
78
+ variant.props = payloadProps;
79
+ } else {
80
+ const variantProps = JSON.parse(JSON.stringify(variant.props));
81
+ variant.props = { ...variantProps, ...payloadProps };
82
+ }
83
+ variant.custom_css = customCss;
84
+ } else {
85
+ style.variants.push({
86
+ meta: payload.meta,
87
+ props: payload.props,
88
+ custom_css: customCss
89
+ });
90
+ }
91
+ state.data[payload.id] = style;
92
+ state.isDirty = true;
93
+ },
94
+ reset(state) {
95
+ state.data = structuredClone(state.initialData);
96
+ state.isDirty = false;
97
+ },
98
+ commit(state) {
99
+ state.initialData = structuredClone(state.data);
100
+ state.isDirty = false;
101
+ },
102
+ deleteTag(state, { payload }) {
103
+ delete state.data[payload];
104
+ state.isDirty = true;
105
+ }
106
+ }
107
+ });
108
+ var selectData = createSelector(
109
+ (state) => state.defaultStyles.data,
110
+ (data) => data
111
+ );
112
+ var selectIsDirty = createSelector(
113
+ (state) => state.defaultStyles.isDirty,
114
+ (isDirty) => isDirty
115
+ );
116
+ var selectInitialData = createSelector(
117
+ (state) => state.defaultStyles.initialData,
118
+ (initialData) => initialData
119
+ );
120
+ var selectTagStyle = createSelector(
121
+ [selectData, (_state, id) => id],
122
+ (data, id) => data[id]
123
+ );
124
+
125
+ // src/load-default-styles.ts
126
+ async function loadDefaultStyles() {
127
+ const response = await apiClient.all();
128
+ const items = response.data.data;
129
+ dispatch(
130
+ slice.actions.load({
131
+ data: items
132
+ })
133
+ );
134
+ }
135
+
136
+ // src/components/populate-store.tsx
137
+ var V2_PANEL_ROUTE = "panel/v2";
138
+ function PopulateStore() {
139
+ useEffect(() => {
140
+ void loadDefaultStyles();
141
+ registerDataHook("after", "editor/documents/attach-preview", async () => {
142
+ if (selectIsDirty(getState())) {
143
+ return;
144
+ }
145
+ await loadDefaultStyles();
146
+ });
147
+ const unsubscribe = listenTo(routeCloseEvent(V2_PANEL_ROUTE), () => {
148
+ if (selectIsDirty(getState())) {
149
+ return;
150
+ }
151
+ void loadDefaultStyles();
152
+ });
153
+ return unsubscribe;
154
+ }, []);
155
+ return null;
156
+ }
157
+
158
+ // src/default-styles-open-gate.tsx
159
+ import * as React5 from "react";
160
+ import { useCallback as useCallback2, useEffect as useEffect3, useRef } from "react";
161
+ import {
162
+ __useActiveDocument as useActiveDocument,
163
+ __useActiveDocumentActions as useActiveDocumentActions
164
+ } from "@elementor/editor-documents";
165
+ import { SaveChangesDialog as SaveChangesDialog2, ThemeProvider as ThemeProvider2, useDialog as useDialog2 } from "@elementor/editor-ui";
166
+ import { __ as __3 } from "@wordpress/i18n";
167
+
168
+ // src/default-styles-panel.tsx
169
+ import * as React4 from "react";
170
+ import { __createPanel as createPanel } from "@elementor/editor-panels";
171
+ import { changeEditMode } from "@elementor/editor-v1-adapters";
172
+
173
+ // src/components/default-styles-panel-content.tsx
174
+ import * as React3 from "react";
175
+ import { useCallback, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
176
+ import {
177
+ ControlActionsProvider,
178
+ ControlReplacementsProvider,
179
+ getControlReplacements
180
+ } from "@elementor/editor-controls";
181
+ import {
182
+ ClassesPropProvider,
183
+ CreatableAutocomplete,
184
+ ElementProvider,
185
+ SectionsList,
186
+ StyleInheritanceProvider,
187
+ StyleProvider,
188
+ StyleSections
189
+ } from "@elementor/editor-editing-panel";
190
+ import { Panel, PanelBody, PanelFooter, PanelHeader, PanelHeaderTitle } from "@elementor/editor-panels";
191
+ import { useActiveBreakpoint } from "@elementor/editor-responsive";
192
+ import { SaveChangesDialog, ThemeProvider, useDialog } from "@elementor/editor-ui";
193
+ import { controlActionsMenu } from "@elementor/menus";
194
+ import { useMutation } from "@elementor/query";
195
+ import { getSessionStorageItem, SessionStorageProvider, setSessionStorageItem } from "@elementor/session";
196
+ import { __dispatch as dispatch3, __useSelector as useSelector } from "@elementor/store";
197
+ import {
198
+ Box,
199
+ Button,
200
+ CloseButton,
201
+ ErrorBoundary,
202
+ FormControl,
203
+ FormLabel,
204
+ Stack as Stack2
205
+ } from "@elementor/ui";
206
+ import { __ as __2 } from "@wordpress/i18n";
207
+
208
+ // src/allowed-tags.ts
209
+ var getElementorConfig = () => window.elementor?.config ?? {};
210
+ var getAllowedDefaultStyleTags = () => {
211
+ const tags = getElementorConfig().atomic?.default_styles?.allowed_tags;
212
+ if (!tags?.length) {
213
+ return [];
214
+ }
215
+ return tags;
216
+ };
217
+ var getDefaultActiveTag = (tags) => {
218
+ if (tags.includes("h1")) {
219
+ return "h1";
220
+ }
221
+ return tags[0] ?? "";
222
+ };
223
+ var isAllowedDefaultStyleTag = (tag, tags = getAllowedDefaultStyleTags()) => tags.includes(tag);
224
+
225
+ // src/panel-interactions.ts
226
+ function blockPanelInteractions() {
227
+ const extendedWindow = window;
228
+ extendedWindow.$e?.components?.get?.("panel")?.blockUserInteractions?.();
229
+ }
230
+ function unblockPanelInteractions() {
231
+ const extendedWindow = window;
232
+ extendedWindow.$e?.components?.get?.("panel")?.unblockUserInteractions?.();
233
+ }
234
+
235
+ // src/save-default-styles.ts
236
+ import { __dispatch as dispatch2, __getState as getState2 } from "@elementor/store";
237
+ import { hash } from "@elementor/utils";
238
+ function getChangedTags(state) {
239
+ const current = selectData(state);
240
+ const initial = selectInitialData(state);
241
+ const changed = [];
242
+ Object.keys(current).forEach((tag) => {
243
+ const currentStyle = current[tag];
244
+ const initialStyle = initial[tag];
245
+ if (!initialStyle || hash(currentStyle) !== hash(initialStyle)) {
246
+ changed.push(tag);
247
+ }
248
+ });
249
+ Object.keys(initial).forEach((tag) => {
250
+ if (!current[tag]) {
251
+ changed.push(tag);
252
+ }
253
+ });
254
+ return changed;
255
+ }
256
+ async function saveDefaultStyles() {
257
+ const state = getState2();
258
+ if (!selectIsDirty(state)) {
259
+ return;
260
+ }
261
+ const data = selectData(state);
262
+ const changedTags = getChangedTags(state);
263
+ await Promise.all(
264
+ changedTags.map(async (tag) => {
265
+ const style = data[tag];
266
+ if (!style || style.variants.length === 0) {
267
+ await apiClient.delete(tag);
268
+ return;
269
+ }
270
+ await apiClient.put(tag, style.variants);
271
+ })
272
+ );
273
+ dispatch2(slice.actions.commit());
274
+ }
275
+
276
+ // src/components/tag-chip.tsx
277
+ import * as React2 from "react";
278
+ import { useState } from "react";
279
+ import { DotsVerticalIcon } from "@elementor/icons";
280
+ import {
281
+ bindTrigger,
282
+ Chip,
283
+ Stack,
284
+ Typography,
285
+ UnstableChipGroup,
286
+ usePopupState
287
+ } from "@elementor/ui";
288
+ import { __ } from "@wordpress/i18n";
289
+
290
+ // src/components/tag-state-menu.tsx
291
+ import * as React from "react";
292
+ import { DEFAULT_PSEUDO_STATES, PseudoStateMenuItems } from "@elementor/editor-editing-panel";
293
+ import { bindMenu, Menu } from "@elementor/ui";
294
+ function TagStateMenu({ popupState, anchorEl, activeState, onSelectState }) {
295
+ return /* @__PURE__ */ React.createElement(
296
+ Menu,
297
+ {
298
+ MenuListProps: { dense: true, sx: { minWidth: "160px" } },
299
+ ...bindMenu(popupState),
300
+ anchorEl,
301
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
302
+ transformOrigin: { horizontal: "left", vertical: -4 },
303
+ disableAutoFocusItem: true
304
+ },
305
+ /* @__PURE__ */ React.createElement(
306
+ PseudoStateMenuItems,
307
+ {
308
+ states: DEFAULT_PSEUDO_STATES,
309
+ activeState,
310
+ onSelectState,
311
+ onClose: popupState.close
312
+ }
313
+ )
314
+ );
315
+ }
316
+
317
+ // src/components/tag-chip.tsx
318
+ var CHIP_SIZE = "tiny";
319
+ function TagChip({ label, chipProps, activeState, onSelectState }) {
320
+ const popupState = usePopupState({
321
+ variant: "popover",
322
+ popupId: "tag-state-menu"
323
+ });
324
+ const [chipRef, setChipRef] = useState(null);
325
+ const { onDelete: _onDelete, ...chipGroupProps } = chipProps;
326
+ const isShowingState = Boolean(activeState);
327
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
328
+ UnstableChipGroup,
329
+ {
330
+ ref: setChipRef,
331
+ ...chipGroupProps,
332
+ "aria-label": `Edit ${label}`,
333
+ role: "group",
334
+ sx: (theme) => ({
335
+ "&.MuiChipGroup-root.MuiAutocomplete-tag": {
336
+ margin: theme.spacing(0.125)
337
+ }
338
+ })
339
+ },
340
+ /* @__PURE__ */ React2.createElement(
341
+ Chip,
342
+ {
343
+ size: CHIP_SIZE,
344
+ label,
345
+ variant: isShowingState ? "standard" : "filled",
346
+ shape: "rounded",
347
+ color: "default",
348
+ onClick: () => {
349
+ if (isShowingState) {
350
+ onSelectState(null);
351
+ }
352
+ },
353
+ sx: (theme) => ({
354
+ lineHeight: 1,
355
+ borderRadius: `${theme.shape.borderRadius * 0.75}px`
356
+ })
357
+ }
358
+ ),
359
+ /* @__PURE__ */ React2.createElement(
360
+ Chip,
361
+ {
362
+ icon: isShowingState ? void 0 : /* @__PURE__ */ React2.createElement(DotsVerticalIcon, { fontSize: "tiny" }),
363
+ size: CHIP_SIZE,
364
+ label: isShowingState ? /* @__PURE__ */ React2.createElement(Stack, { direction: "row", gap: 0.5, alignItems: "center" }, /* @__PURE__ */ React2.createElement(Typography, { variant: "inherit" }, activeState), /* @__PURE__ */ React2.createElement(DotsVerticalIcon, { fontSize: "tiny" })) : void 0,
365
+ variant: "filled",
366
+ shape: "rounded",
367
+ color: "default",
368
+ ...bindTrigger(popupState),
369
+ "aria-label": __("Open tag state menu", "elementor"),
370
+ sx: (theme) => ({
371
+ borderRadius: `${theme.shape.borderRadius * 0.75}px`,
372
+ paddingRight: 0,
373
+ ...!isShowingState ? { paddingLeft: 0 } : {},
374
+ ".MuiChip-label": isShowingState ? { paddingRight: 0 } : { padding: 0 }
375
+ })
376
+ }
377
+ )
378
+ ), /* @__PURE__ */ React2.createElement(
379
+ TagStateMenu,
380
+ {
381
+ popupState,
382
+ anchorEl: chipRef,
383
+ activeState,
384
+ onSelectState
385
+ }
386
+ ));
387
+ }
388
+
389
+ // src/components/default-styles-panel-content.tsx
390
+ var { useMenuItems } = controlActionsMenu;
391
+ var SHIM_ELEMENT_ID = "default-styles-editor-shim";
392
+ var SHIM_CLASSES_PROP = "__default_styles_classes__";
393
+ var TAG_SELECTOR_ID = "default-styles-tag-selector";
394
+ var LAST_ACTIVE_TAG_SESSION_PREFIX = "default-styles";
395
+ var LAST_ACTIVE_TAG_SESSION_KEY = "last-active-tag";
396
+ var LAST_ACTIVE_TAG_STORAGE_KEY = `${LAST_ACTIVE_TAG_SESSION_PREFIX}/${LAST_ACTIVE_TAG_SESSION_KEY}`;
397
+ function readStoredActiveTag(allowedTags) {
398
+ const storedTag = getSessionStorageItem(LAST_ACTIVE_TAG_STORAGE_KEY);
399
+ if (storedTag && isAllowedDefaultStyleTag(storedTag, allowedTags)) {
400
+ return storedTag;
401
+ }
402
+ return getDefaultActiveTag(allowedTags);
403
+ }
404
+ function toTagChip(tag) {
405
+ return { label: tag, value: tag, fixed: true };
406
+ }
407
+ var shimElement = {
408
+ id: SHIM_ELEMENT_ID,
409
+ type: "default-style"
410
+ };
411
+ var shimElementType = {
412
+ key: "default-style",
413
+ controls: [],
414
+ propsSchema: {},
415
+ title: __2("Default Style", "elementor")
416
+ };
417
+ function DefaultStylesPanelContent({ onRequestClose }) {
418
+ const allowedTags = useMemo(() => getAllowedDefaultStyleTags(), []);
419
+ const tagOptions = useMemo(
420
+ () => allowedTags.map((tag) => ({ label: tag, value: tag })),
421
+ [allowedTags]
422
+ );
423
+ const [selectedTag, setSelectedTagState] = useState2(() => readStoredActiveTag(allowedTags));
424
+ const [activeStyleState, setActiveStyleState] = useState2(null);
425
+ const breakpoint = useActiveBreakpoint();
426
+ const menuItems = useMenuItems().default;
427
+ const controlReplacements = getControlReplacements();
428
+ const isDirty = useSelector(selectIsDirty);
429
+ const { mutateAsync: save, isPending: isSaving } = useSave();
430
+ const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
431
+ const setSelectedTag = (tag) => {
432
+ setSelectedTagState(tag);
433
+ setSessionStorageItem(LAST_ACTIVE_TAG_STORAGE_KEY, tag);
434
+ };
435
+ const handleClosePanel = useCallback(() => {
436
+ if (isDirty) {
437
+ openSaveChangesDialog();
438
+ return;
439
+ }
440
+ onRequestClose();
441
+ }, [isDirty, onRequestClose, openSaveChangesDialog]);
442
+ useEffect2(() => {
443
+ blockPanelInteractions();
444
+ return () => {
445
+ unblockPanelInteractions();
446
+ };
447
+ }, []);
448
+ usePreventUnload(isDirty);
449
+ const handleTagSelect = (_selected, reason, option) => {
450
+ if (reason !== "selectOption" || !option.value) {
451
+ return;
452
+ }
453
+ setSelectedTag(option.value);
454
+ setActiveStyleState(null);
455
+ };
456
+ const resetAndClosePanel = () => {
457
+ dispatch3(slice.actions.reset());
458
+ closeSaveChangesDialog();
459
+ onRequestClose();
460
+ };
461
+ const handleSaveAndContinue = async () => {
462
+ try {
463
+ await save();
464
+ } catch {
465
+ return;
466
+ }
467
+ closeSaveChangesDialog();
468
+ onRequestClose();
469
+ };
470
+ return /* @__PURE__ */ React3.createElement(ErrorBoundary, { fallback: null }, /* @__PURE__ */ React3.createElement(ThemeProvider, null, /* @__PURE__ */ React3.createElement(ControlActionsProvider, { items: menuItems }, /* @__PURE__ */ React3.createElement(ControlReplacementsProvider, { replacements: controlReplacements }, /* @__PURE__ */ React3.createElement(Panel, null, /* @__PURE__ */ React3.createElement(PanelHeader, null, /* @__PURE__ */ React3.createElement(
471
+ Stack2,
472
+ {
473
+ p: 1,
474
+ pl: 2,
475
+ width: "100%",
476
+ direction: "row",
477
+ alignItems: "center",
478
+ justifyContent: "space-between",
479
+ spacing: 0.5
480
+ },
481
+ /* @__PURE__ */ React3.createElement(PanelHeaderTitle, { sx: { flex: 1, minWidth: 0 } }, __2("Default Styles", "elementor")),
482
+ /* @__PURE__ */ React3.createElement(
483
+ CloseButton,
484
+ {
485
+ "aria-label": __2("Close", "elementor"),
486
+ sx: { flexShrink: 0 },
487
+ onClick: handleClosePanel
488
+ }
489
+ )
490
+ )), /* @__PURE__ */ React3.createElement(PanelBody, null, /* @__PURE__ */ React3.createElement(Stack2, { sx: { px: 2, pt: 1, gap: 1 } }, /* @__PURE__ */ React3.createElement(FormControl, { fullWidth: true, size: "small" }, /* @__PURE__ */ React3.createElement(FormLabel, { htmlFor: TAG_SELECTOR_ID, size: "small", sx: { mb: 1 } }, __2("Tag", "elementor")), /* @__PURE__ */ React3.createElement(
491
+ CreatableAutocomplete,
492
+ {
493
+ id: TAG_SELECTOR_ID,
494
+ size: "tiny",
495
+ placeholder: __2("Type tag name", "elementor"),
496
+ options: tagOptions,
497
+ selected: [toTagChip(selectedTag)],
498
+ onSelect: handleTagSelect,
499
+ renderTags: (values, getTagProps) => values.map((value, index) => /* @__PURE__ */ React3.createElement(
500
+ TagChip,
501
+ {
502
+ key: value.value ?? value.label,
503
+ label: value.label,
504
+ chipProps: getTagProps({ index }),
505
+ activeState: activeStyleState,
506
+ onSelectState: setActiveStyleState
507
+ }
508
+ ))
509
+ }
510
+ ))), /* @__PURE__ */ React3.createElement(
511
+ ElementProvider,
512
+ {
513
+ element: shimElement,
514
+ elementType: shimElementType,
515
+ settings: {}
516
+ },
517
+ /* @__PURE__ */ React3.createElement(ClassesPropProvider, { prop: SHIM_CLASSES_PROP }, /* @__PURE__ */ React3.createElement(
518
+ StyleProvider,
519
+ {
520
+ meta: {
521
+ breakpoint,
522
+ state: activeStyleState
523
+ },
524
+ id: selectedTag,
525
+ setId: () => {
526
+ },
527
+ setMetaState: setActiveStyleState
528
+ },
529
+ /* @__PURE__ */ React3.createElement(SessionStorageProvider, { prefix: selectedTag }, /* @__PURE__ */ React3.createElement(StyleInheritanceProvider, null, /* @__PURE__ */ React3.createElement(SectionsList, null, /* @__PURE__ */ React3.createElement(StyleSections, null)), /* @__PURE__ */ React3.createElement(
530
+ Box,
531
+ {
532
+ sx: {
533
+ height: "150px"
534
+ }
535
+ }
536
+ )))
537
+ ))
538
+ )), /* @__PURE__ */ React3.createElement(PanelFooter, null, /* @__PURE__ */ React3.createElement(
539
+ Button,
540
+ {
541
+ fullWidth: true,
542
+ size: "small",
543
+ color: "global",
544
+ variant: "contained",
545
+ onClick: () => void save(),
546
+ disabled: !isDirty,
547
+ loading: isSaving
548
+ },
549
+ __2("Save changes", "elementor")
550
+ ))))), isSaveChangesDialogOpen && /* @__PURE__ */ React3.createElement(SaveChangesDialog, null, /* @__PURE__ */ React3.createElement(SaveChangesDialog.Title, { onClose: closeSaveChangesDialog }, __2("You have unsaved changes", "elementor")), /* @__PURE__ */ React3.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React3.createElement(SaveChangesDialog.ContentText, null, __2("You have unsaved changes in Default Styles.", "elementor")), /* @__PURE__ */ React3.createElement(SaveChangesDialog.ContentText, null, __2("To avoid losing your updates, save your changes before leaving.", "elementor"))), /* @__PURE__ */ React3.createElement(
551
+ SaveChangesDialog.Actions,
552
+ {
553
+ actions: {
554
+ discard: {
555
+ label: __2("Discard", "elementor"),
556
+ action: resetAndClosePanel
557
+ },
558
+ confirm: {
559
+ label: __2("Save & Continue", "elementor"),
560
+ action: handleSaveAndContinue
561
+ }
562
+ }
563
+ }
564
+ ))));
565
+ }
566
+ function useSave() {
567
+ return useMutation({
568
+ mutationFn: () => saveDefaultStyles()
569
+ });
570
+ }
571
+ function usePreventUnload(isDirty) {
572
+ useEffect2(() => {
573
+ const handleBeforeUnload = (event) => {
574
+ if (isDirty) {
575
+ event.preventDefault();
576
+ }
577
+ };
578
+ window.addEventListener("beforeunload", handleBeforeUnload);
579
+ return () => {
580
+ window.removeEventListener("beforeunload", handleBeforeUnload);
581
+ };
582
+ }, [isDirty]);
583
+ }
584
+
585
+ // src/default-styles-panel.tsx
586
+ var DEFAULT_STYLES_PANEL_ID = "default-styles";
587
+ var { panel, usePanelStatus, usePanelActions } = createPanel({
588
+ id: DEFAULT_STYLES_PANEL_ID,
589
+ component: DefaultStylesPanelRoot,
590
+ allowedEditModes: ["edit", DEFAULT_STYLES_PANEL_ID],
591
+ onOpen: () => {
592
+ changeEditMode(DEFAULT_STYLES_PANEL_ID);
593
+ },
594
+ onClose: async () => {
595
+ changeEditMode("edit");
596
+ },
597
+ isOpenPreviousElement: true
598
+ });
599
+ function DefaultStylesPanelRoot() {
600
+ const { close } = usePanelActions();
601
+ return /* @__PURE__ */ React4.createElement(
602
+ DefaultStylesPanelContent,
603
+ {
604
+ onRequestClose: () => {
605
+ void close();
606
+ }
607
+ }
608
+ );
609
+ }
610
+
611
+ // src/default-styles-open-gate.tsx
612
+ var EVENT_REQUEST_OPEN_DEFAULT_STYLES = "elementor/default-styles/request-open";
613
+ function DefaultStylesOpenGate() {
614
+ const { open } = usePanelActions();
615
+ const document = useActiveDocument();
616
+ const { save: saveDocument } = useActiveDocumentActions();
617
+ const { open: openSaveDialog, close: closeSaveDialog, isOpen: isSaveDialogOpen } = useDialog2();
618
+ const documentRef = useRef(document);
619
+ documentRef.current = document;
620
+ const pendingOpenRef = useRef(null);
621
+ const gatedOpen = useCallback2(
622
+ (onClean) => {
623
+ if (documentRef.current?.isDirty) {
624
+ pendingOpenRef.current = onClean;
625
+ openSaveDialog();
626
+ return;
627
+ }
628
+ onClean();
629
+ },
630
+ [openSaveDialog]
631
+ );
632
+ const handleSaveAndContinue = useCallback2(async () => {
633
+ try {
634
+ await saveDocument();
635
+ closeSaveDialog();
636
+ pendingOpenRef.current?.();
637
+ pendingOpenRef.current = null;
638
+ } catch {
639
+ }
640
+ }, [saveDocument, closeSaveDialog]);
641
+ const handleStayHere = useCallback2(() => {
642
+ closeSaveDialog();
643
+ pendingOpenRef.current = null;
644
+ }, [closeSaveDialog]);
645
+ useEffect3(() => {
646
+ const handler = () => {
647
+ gatedOpen(() => {
648
+ void open();
649
+ });
650
+ };
651
+ window.addEventListener(EVENT_REQUEST_OPEN_DEFAULT_STYLES, handler);
652
+ return () => {
653
+ window.removeEventListener(EVENT_REQUEST_OPEN_DEFAULT_STYLES, handler);
654
+ };
655
+ }, [gatedOpen, open]);
656
+ if (!isSaveDialogOpen) {
657
+ return null;
658
+ }
659
+ return /* @__PURE__ */ React5.createElement(ThemeProvider2, null, /* @__PURE__ */ React5.createElement(SaveChangesDialog2, null, /* @__PURE__ */ React5.createElement(SaveChangesDialog2.Title, null, __3("You have unsaved changes", "elementor")), /* @__PURE__ */ React5.createElement(SaveChangesDialog2.Content, null, /* @__PURE__ */ React5.createElement(SaveChangesDialog2.ContentText, { sx: { mb: 2 } }, __3(
660
+ "To open Default Styles, save your page first. You can't continue without saving.",
661
+ "elementor"
662
+ ))), /* @__PURE__ */ React5.createElement(
663
+ SaveChangesDialog2.Actions,
664
+ {
665
+ actions: {
666
+ cancel: {
667
+ label: __3("Stay here", "elementor"),
668
+ action: handleStayHere
669
+ },
670
+ confirm: {
671
+ label: __3("Save & Continue", "elementor"),
672
+ action: handleSaveAndContinue
673
+ }
674
+ }
675
+ }
676
+ )));
677
+ }
678
+
679
+ // src/default-styles-provider.ts
680
+ import { createStylesProvider } from "@elementor/editor-styles-repository";
681
+ import {
682
+ __dispatch as dispatch4,
683
+ __getState as getState3,
684
+ __subscribeWithSelector as subscribeWithSelector
685
+ } from "@elementor/store";
686
+ import { __ as __4 } from "@wordpress/i18n";
687
+ var DEFAULT_STYLES_PROVIDER_KEY = "default-styles";
688
+ var DEFAULT_STYLES_CSS_NAME_PREFIX = "e-default-";
689
+ var resolveCssName = (id) => `${DEFAULT_STYLES_CSS_NAME_PREFIX}${id}`;
690
+ var placeholderDefinition = (id) => ({
691
+ id,
692
+ label: id,
693
+ type: "class",
694
+ variants: []
695
+ });
696
+ var asClassDefinition = (style) => ({
697
+ ...style,
698
+ type: "class"
699
+ });
700
+ var defaultStylesStylesProvider = createStylesProvider({
701
+ key: DEFAULT_STYLES_PROVIDER_KEY,
702
+ priority: 15,
703
+ labels: {
704
+ singular: __4("tag", "elementor"),
705
+ plural: __4("tags", "elementor")
706
+ },
707
+ subscribe: (cb) => subscribeWithStates(cb),
708
+ actions: {
709
+ all: () => getAllowedDefaultStyleTags().map((tag) => {
710
+ const style = selectData(getState3())[tag];
711
+ return style ? asClassDefinition(style) : placeholderDefinition(tag);
712
+ }),
713
+ get: (id) => {
714
+ const style = selectData(getState3())[id];
715
+ return style ? asClassDefinition(style) : placeholderDefinition(id);
716
+ },
717
+ resolveCssName,
718
+ update: (payload) => {
719
+ dispatch4(
720
+ slice.actions.update({
721
+ style: payload
722
+ })
723
+ );
724
+ },
725
+ delete: (id) => {
726
+ dispatch4(slice.actions.deleteTag(id));
727
+ },
728
+ updateProps: (args) => {
729
+ dispatch4(
730
+ slice.actions.updateProps({
731
+ id: args.id,
732
+ meta: args.meta,
733
+ props: args.props,
734
+ mode: args.mode
735
+ })
736
+ );
737
+ },
738
+ updateCustomCss: (args) => {
739
+ dispatch4(
740
+ slice.actions.updateProps({
741
+ id: args.id,
742
+ meta: args.meta,
743
+ custom_css: args.custom_css,
744
+ props: {}
745
+ })
746
+ );
747
+ }
748
+ }
749
+ });
750
+ var subscribeWithStates = (cb) => {
751
+ let previousState = selectData(getState3());
752
+ return subscribeWithSelector(
753
+ (state) => selectData(state),
754
+ (currentState) => {
755
+ cb(previousState, currentState);
756
+ previousState = currentState;
757
+ }
758
+ );
759
+ };
760
+
761
+ // src/hooks/use-default-styles-action-props.ts
762
+ import { TextIcon } from "@elementor/icons";
763
+ import { __ as __5 } from "@wordpress/i18n";
764
+ function useDefaultStylesActionProps() {
765
+ return {
766
+ title: __5("Default Styles", "elementor"),
767
+ icon: TextIcon,
768
+ onClick: () => {
769
+ window.dispatchEvent(new CustomEvent(EVENT_REQUEST_OPEN_DEFAULT_STYLES));
770
+ }
771
+ };
772
+ }
773
+
774
+ // src/init.ts
775
+ function init() {
776
+ registerSlice(slice);
777
+ registerElementPanelDefaults("default-style", {
778
+ defaultTab: "style",
779
+ defaultSectionsExpanded: {
780
+ style: [...STYLE_SECTION_NAMES]
781
+ }
782
+ });
783
+ registerPanel(panel);
784
+ stylesRepository.register(defaultStylesStylesProvider);
785
+ toolsMenu.registerAction({
786
+ id: "default-styles-button",
787
+ priority: 4,
788
+ useProps: useDefaultStylesActionProps
789
+ });
790
+ injectIntoLogic({
791
+ id: "default-styles-populate-store",
792
+ component: PopulateStore
793
+ });
794
+ injectIntoLogic({
795
+ id: "default-styles-open-gate",
796
+ component: DefaultStylesOpenGate
797
+ });
798
+ }
799
+ export {
800
+ init
801
+ };
802
+ //# sourceMappingURL=index.mjs.map