@elementor/editor-variables 0.18.0 → 3.32.0-21

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.
Files changed (56) hide show
  1. package/CHANGELOG.md +0 -28
  2. package/dist/index.d.mts +19 -1
  3. package/dist/index.d.ts +19 -1
  4. package/dist/index.js +1282 -1026
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +1262 -990
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +16 -14
  9. package/src/api.ts +18 -2
  10. package/src/components/fields/color-field.tsx +3 -3
  11. package/src/components/fields/font-field.tsx +21 -10
  12. package/src/components/fields/label-field.tsx +31 -5
  13. package/src/components/ui/edit-confirmation-dialog.tsx +75 -0
  14. package/src/components/ui/missing-variable-alert.tsx +39 -0
  15. package/src/components/ui/no-variables.tsx +59 -26
  16. package/src/components/ui/tags/missing-tag.tsx +25 -0
  17. package/src/components/ui/variable/assigned-variable.tsx +11 -14
  18. package/src/components/ui/variable/deleted-variable.tsx +102 -50
  19. package/src/components/ui/variable/missing-variable.tsx +44 -0
  20. package/src/components/{color-variable-creation.tsx → variable-creation.tsx} +51 -22
  21. package/src/components/variable-edit.tsx +221 -0
  22. package/src/components/variable-restore.tsx +117 -0
  23. package/src/components/variable-selection-popover.tsx +91 -92
  24. package/src/components/variables-manager/variables-manager-panel.tsx +115 -0
  25. package/src/components/{font-variables-selection.tsx → variables-selection.tsx} +38 -17
  26. package/src/context/variable-selection-popover.context.tsx +19 -0
  27. package/src/context/variable-type-context.tsx +23 -0
  28. package/src/controls/variable-control.tsx +26 -0
  29. package/src/hooks/use-initial-value.ts +22 -0
  30. package/src/hooks/use-permissions.ts +15 -0
  31. package/src/hooks/use-prop-variable-action.tsx +53 -0
  32. package/src/hooks/use-prop-variables.ts +2 -2
  33. package/src/index.ts +1 -0
  34. package/src/init.ts +33 -4
  35. package/src/register-variable-types.tsx +29 -0
  36. package/src/repeater-injections.ts +5 -1
  37. package/src/service.ts +2 -19
  38. package/src/transformers/inheritance-transformer.tsx +30 -0
  39. package/src/transformers/utils/resolve-css-variable.ts +24 -0
  40. package/src/transformers/variable-transformer.ts +3 -16
  41. package/src/utils/tracking.ts +39 -0
  42. package/src/utils/validations.ts +40 -6
  43. package/src/variables-registry/create-variable-type-registry.ts +77 -0
  44. package/src/variables-registry/variable-type-registry.ts +3 -0
  45. package/src/components/color-variable-edit.tsx +0 -157
  46. package/src/components/color-variables-selection.tsx +0 -128
  47. package/src/components/font-variable-creation.tsx +0 -106
  48. package/src/components/font-variable-edit.tsx +0 -157
  49. package/src/components/variable-selection-popover.context.ts +0 -7
  50. package/src/controls/color-variable-control.tsx +0 -39
  51. package/src/controls/font-variable-control.tsx +0 -37
  52. package/src/hooks/use-prop-color-variable-action.tsx +0 -25
  53. package/src/hooks/use-prop-font-variable-action.tsx +0 -25
  54. package/src/init-color-variables.ts +0 -27
  55. package/src/init-font-variables.ts +0 -24
  56. package/src/utils.ts +0 -20
package/dist/index.js CHANGED
@@ -30,66 +30,123 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- init: () => init
33
+ init: () => init,
34
+ registerVariableType: () => registerVariableType
34
35
  });
35
36
  module.exports = __toCommonJS(index_exports);
36
37
 
37
38
  // src/init.ts
38
39
  var import_editor = require("@elementor/editor");
39
-
40
- // src/init-color-variables.ts
41
- var import_editor_canvas2 = require("@elementor/editor-canvas");
42
40
  var import_editor_editing_panel10 = require("@elementor/editor-editing-panel");
41
+ var import_editor_panels2 = require("@elementor/editor-panels");
43
42
 
44
- // src/controls/color-variable-control.tsx
45
- var React20 = __toESM(require("react"));
46
- var import_editor_controls10 = require("@elementor/editor-controls");
47
- var import_editor_props3 = require("@elementor/editor-props");
48
-
49
- // src/components/ui/color-indicator.tsx
43
+ // src/components/variables-manager/variables-manager-panel.tsx
44
+ var React = __toESM(require("react"));
45
+ var import_react = require("react");
46
+ var import_editor_panels = require("@elementor/editor-panels");
47
+ var import_editor_ui = require("@elementor/editor-ui");
48
+ var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
49
+ var import_icons = require("@elementor/icons");
50
50
  var import_ui = require("@elementor/ui");
51
- var ColorIndicator = (0, import_ui.styled)(import_ui.UnstableColorIndicator)(({ theme }) => ({
52
- borderRadius: `${theme.shape.borderRadius / 2}px`,
53
- marginRight: theme.spacing(0.25)
54
- }));
51
+ var import_i18n = require("@wordpress/i18n");
52
+ var id = "variables-manager";
53
+ var { panel, usePanelActions } = (0, import_editor_panels.__createPanel)({
54
+ id,
55
+ component: VariablesManagerPanel,
56
+ allowedEditModes: ["edit", id],
57
+ onOpen: () => {
58
+ (0, import_editor_v1_adapters.changeEditMode)(id);
59
+ },
60
+ onClose: () => {
61
+ (0, import_editor_v1_adapters.changeEditMode)("edit");
62
+ }
63
+ });
64
+ function VariablesManagerPanel() {
65
+ const { close: closePanel } = usePanelActions();
66
+ const isDirty = false;
67
+ usePreventUnload(isDirty);
68
+ return /* @__PURE__ */ React.createElement(import_editor_ui.ThemeProvider, null, /* @__PURE__ */ React.createElement(import_ui.ErrorBoundary, { fallback: /* @__PURE__ */ React.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React.createElement(import_editor_panels.Panel, null, /* @__PURE__ */ React.createElement(import_editor_panels.PanelHeader, null, /* @__PURE__ */ React.createElement(import_ui.Stack, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React.createElement(import_ui.Stack, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React.createElement(import_editor_panels.PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React.createElement(import_icons.FilterIcon, { fontSize: "inherit" }), (0, import_i18n.__)("Variables Manager", "elementor"))), /* @__PURE__ */ React.createElement(
69
+ CloseButton,
70
+ {
71
+ sx: { marginLeft: "auto" },
72
+ onClose: () => {
73
+ closePanel();
74
+ }
75
+ }
76
+ ))), /* @__PURE__ */ React.createElement(
77
+ import_editor_panels.PanelBody,
78
+ {
79
+ sx: {
80
+ display: "flex",
81
+ flexDirection: "column",
82
+ height: "100%"
83
+ }
84
+ },
85
+ /* @__PURE__ */ React.createElement(import_ui.Divider, null),
86
+ /* @__PURE__ */ React.createElement(
87
+ import_ui.Box,
88
+ {
89
+ px: 2,
90
+ sx: {
91
+ flexGrow: 1,
92
+ overflowY: "auto"
93
+ }
94
+ },
95
+ "List"
96
+ )
97
+ ), /* @__PURE__ */ React.createElement(import_editor_panels.PanelFooter, null, /* @__PURE__ */ React.createElement(import_ui.Button, { fullWidth: true, size: "small", color: "global", variant: "contained", disabled: !isDirty }, (0, import_i18n.__)("Save changes", "elementor"))))));
98
+ }
99
+ var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React.createElement(import_ui.IconButton, { size: "small", color: "secondary", onClick: onClose, "aria-label": "Close", ...props }, /* @__PURE__ */ React.createElement(import_icons.XIcon, { fontSize: "small" }));
100
+ var ErrorBoundaryFallback = () => /* @__PURE__ */ React.createElement(import_ui.Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React.createElement(import_ui.Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React.createElement("strong", null, (0, import_i18n.__)("Something went wrong", "elementor"))));
101
+ var usePreventUnload = (isDirty) => {
102
+ (0, import_react.useEffect)(() => {
103
+ const handleBeforeUnload = (event) => {
104
+ if (isDirty) {
105
+ event.preventDefault();
106
+ }
107
+ };
108
+ window.addEventListener("beforeunload", handleBeforeUnload);
109
+ return () => {
110
+ window.removeEventListener("beforeunload", handleBeforeUnload);
111
+ };
112
+ }, [isDirty]);
113
+ };
114
+
115
+ // src/controls/variable-control.tsx
116
+ var React24 = __toESM(require("react"));
117
+ var import_editor_controls9 = require("@elementor/editor-controls");
55
118
 
56
119
  // src/components/ui/variable/assigned-variable.tsx
57
- var import_react13 = require("react");
120
+ var import_react11 = require("react");
58
121
  var React16 = __toESM(require("react"));
59
- var import_editor_controls8 = require("@elementor/editor-controls");
60
- var import_icons11 = require("@elementor/icons");
61
- var import_ui18 = require("@elementor/ui");
62
-
63
- // src/components/variable-selection-popover.tsx
64
- var React14 = __toESM(require("react"));
65
- var import_react12 = require("react");
122
+ var import_editor_controls5 = require("@elementor/editor-controls");
123
+ var import_icons9 = require("@elementor/icons");
66
124
  var import_ui16 = require("@elementor/ui");
67
125
 
126
+ // src/variables-registry/create-variable-type-registry.ts
127
+ var import_editor_canvas3 = require("@elementor/editor-canvas");
128
+ var import_editor_editing_panel = require("@elementor/editor-editing-panel");
129
+
130
+ // src/transformers/inheritance-transformer.tsx
131
+ var React2 = __toESM(require("react"));
132
+ var import_editor_canvas = require("@elementor/editor-canvas");
133
+ var import_ui3 = require("@elementor/ui");
134
+ var import_i18n3 = require("@wordpress/i18n");
135
+
136
+ // src/components/ui/color-indicator.tsx
137
+ var import_ui2 = require("@elementor/ui");
138
+ var ColorIndicator = (0, import_ui2.styled)(import_ui2.UnstableColorIndicator)(({ theme }) => ({
139
+ borderRadius: `${theme.shape.borderRadius / 2}px`,
140
+ marginRight: theme.spacing(0.25)
141
+ }));
142
+
68
143
  // src/prop-types/color-variable-prop-type.ts
69
144
  var import_editor_props = require("@elementor/editor-props");
70
145
  var import_schema = require("@elementor/schema");
71
146
  var colorVariablePropTypeUtil = (0, import_editor_props.createPropUtils)("global-color-variable", import_schema.z.string());
72
147
 
73
- // src/prop-types/font-variable-prop-type.ts
74
- var import_editor_props2 = require("@elementor/editor-props");
75
- var import_schema2 = require("@elementor/schema");
76
- var fontVariablePropTypeUtil = (0, import_editor_props2.createPropUtils)("global-font-variable", import_schema2.z.string());
77
-
78
- // src/components/color-variable-creation.tsx
79
- var React3 = __toESM(require("react"));
80
- var import_react5 = require("react");
81
- var import_editor_controls = require("@elementor/editor-controls");
82
- var import_editor_editing_panel = require("@elementor/editor-editing-panel");
83
- var import_editor_ui = require("@elementor/editor-ui");
84
- var import_icons = require("@elementor/icons");
85
- var import_ui4 = require("@elementor/ui");
86
- var import_i18n5 = require("@wordpress/i18n");
87
-
88
- // src/hooks/use-prop-variables.ts
89
- var import_react = require("react");
90
-
91
148
  // src/service.ts
92
- var import_i18n = require("@wordpress/i18n");
149
+ var import_i18n2 = require("@wordpress/i18n");
93
150
 
94
151
  // src/api.ts
95
152
  var import_http_client = require("@elementor/http-client");
@@ -105,18 +162,25 @@ var apiClient = {
105
162
  value
106
163
  });
107
164
  },
108
- update: (id, label, value) => {
165
+ update: (id2, label, value) => {
109
166
  return (0, import_http_client.httpService)().put(BASE_PATH + "/update", {
110
- id,
167
+ id: id2,
111
168
  label,
112
169
  value
113
170
  });
114
171
  },
115
- delete: (id) => {
116
- return (0, import_http_client.httpService)().post(BASE_PATH + "/delete", { id });
172
+ delete: (id2) => {
173
+ return (0, import_http_client.httpService)().post(BASE_PATH + "/delete", { id: id2 });
117
174
  },
118
- restore: (id) => {
119
- return (0, import_http_client.httpService)().post(BASE_PATH + "/restore", { id });
175
+ restore: (id2, label, value) => {
176
+ const payload = { id: id2 };
177
+ if (label) {
178
+ payload.label = label;
179
+ }
180
+ if (value) {
181
+ payload.value = value;
182
+ }
183
+ return (0, import_http_client.httpService)().post(BASE_PATH + "/restore", payload);
120
184
  }
121
185
  };
122
186
 
@@ -147,14 +211,14 @@ var Storage = class {
147
211
  localStorage.setItem(STORAGE_WATERMARK_KEY, this.state.watermark.toString());
148
212
  localStorage.setItem(STORAGE_KEY, JSON.stringify(this.state.variables));
149
213
  }
150
- add(id, variable) {
214
+ add(id2, variable) {
151
215
  this.load();
152
- this.state.variables[id] = variable;
216
+ this.state.variables[id2] = variable;
153
217
  localStorage.setItem(STORAGE_KEY, JSON.stringify(this.state.variables));
154
218
  }
155
- update(id, variable) {
219
+ update(id2, variable) {
156
220
  this.load();
157
- this.state.variables[id] = variable;
221
+ this.state.variables[id2] = variable;
158
222
  localStorage.setItem(STORAGE_KEY, JSON.stringify(this.state.variables));
159
223
  }
160
224
  watermark(watermark) {
@@ -173,6 +237,11 @@ var Storage = class {
173
237
  }
174
238
  };
175
239
 
240
+ // src/prop-types/font-variable-prop-type.ts
241
+ var import_editor_props2 = require("@elementor/editor-props");
242
+ var import_schema2 = require("@elementor/schema");
243
+ var fontVariablePropTypeUtil = (0, import_editor_props2.createPropUtils)("global-font-variable", import_schema2.z.string());
244
+
176
245
  // src/sync/enqueue-font.ts
177
246
  var enqueueFont = (fontFamily, context = "preview") => {
178
247
  const extendedWindow = window;
@@ -276,7 +345,7 @@ var service = {
276
345
  return apiClient.create(type, label, value).then((response) => {
277
346
  const { success, data: payload } = response.data;
278
347
  if (!success) {
279
- const errorMessage = payload?.message || (0, import_i18n.__)("Unexpected response from server", "elementor");
348
+ const errorMessage = payload?.message || (0, import_i18n2.__)("Unexpected response from server", "elementor");
280
349
  throw new Error(errorMessage);
281
350
  }
282
351
  return payload;
@@ -292,16 +361,13 @@ var service = {
292
361
  id: variableId,
293
362
  variable: createdVariable
294
363
  };
295
- }).catch((error) => {
296
- const message = getErrorMessage(error.response);
297
- throw message ? new Error(message) : error;
298
364
  });
299
365
  },
300
- update: (id, { label, value }) => {
301
- return apiClient.update(id, label, value).then((response) => {
366
+ update: (id2, { label, value }) => {
367
+ return apiClient.update(id2, label, value).then((response) => {
302
368
  const { success, data: payload } = response.data;
303
369
  if (!success) {
304
- const errorMessage = payload?.message || (0, import_i18n.__)("Unexpected response from server", "elementor");
370
+ const errorMessage = payload?.message || (0, import_i18n2.__)("Unexpected response from server", "elementor");
305
371
  throw new Error(errorMessage);
306
372
  }
307
373
  return payload;
@@ -317,13 +383,10 @@ var service = {
317
383
  id: variableId,
318
384
  variable: updatedVariable
319
385
  };
320
- }).catch((error) => {
321
- const message = getErrorMessage(error.response);
322
- throw message ? new Error(message) : error;
323
386
  });
324
387
  },
325
- delete: (id) => {
326
- return apiClient.delete(id).then((response) => {
388
+ delete: (id2) => {
389
+ return apiClient.delete(id2).then((response) => {
327
390
  const { success, data: payload } = response.data;
328
391
  if (!success) {
329
392
  throw new Error("Unexpected response from server");
@@ -343,8 +406,8 @@ var service = {
343
406
  };
344
407
  });
345
408
  },
346
- restore: (id) => {
347
- return apiClient.restore(id).then((response) => {
409
+ restore: (id2, label, value) => {
410
+ return apiClient.restore(id2, label, value).then((response) => {
348
411
  const { success, data: payload } = response.data;
349
412
  if (!success) {
350
413
  throw new Error("Unexpected response from server");
@@ -371,14 +434,158 @@ var handleWatermark = (operation, newWatermark) => {
371
434
  }
372
435
  storage.watermark(newWatermark);
373
436
  };
374
- var getErrorMessage = (response) => {
375
- if (response?.data?.code === "duplicated_label") {
376
- return (0, import_i18n.__)("This variable name already exists. Please choose a unique name.", "elementor");
437
+
438
+ // src/transformers/utils/resolve-css-variable.ts
439
+ var resolveCssVariable = (id2, variable) => {
440
+ let name = id2;
441
+ let fallbackValue = "";
442
+ if (variable) {
443
+ fallbackValue = variable.value;
444
+ }
445
+ if (variable && !variable.deleted) {
446
+ name = variable.label;
447
+ }
448
+ if (!name.trim()) {
449
+ return null;
450
+ }
451
+ if (!fallbackValue.trim()) {
452
+ return `var(--${name})`;
453
+ }
454
+ return `var(--${name}, ${fallbackValue})`;
455
+ };
456
+
457
+ // src/transformers/inheritance-transformer.tsx
458
+ var inheritanceTransformer = (0, import_editor_canvas.createTransformer)((id2) => {
459
+ const variables = service.variables();
460
+ const variable = variables[id2];
461
+ if (!variable) {
462
+ return /* @__PURE__ */ React2.createElement("span", null, (0, import_i18n3.__)("Missing variable", "elementor"));
463
+ }
464
+ const showColorIndicator = variable.type === colorVariablePropTypeUtil.key;
465
+ const css = resolveCssVariable(id2, variable);
466
+ return /* @__PURE__ */ React2.createElement(import_ui3.Stack, { direction: "row", spacing: 0.5, sx: { paddingInline: "1px" }, alignItems: "center" }, showColorIndicator && /* @__PURE__ */ React2.createElement(ColorIndicator, { size: "inherit", value: variable.value }), /* @__PURE__ */ React2.createElement(import_ui3.Typography, { variant: "caption", overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis" }, css));
467
+ });
468
+
469
+ // src/transformers/variable-transformer.ts
470
+ var import_editor_canvas2 = require("@elementor/editor-canvas");
471
+ var variableTransformer = (0, import_editor_canvas2.createTransformer)((id2) => {
472
+ const variables = service.variables();
473
+ if (!variables[id2]) {
474
+ return null;
475
+ }
476
+ return resolveCssVariable(id2, variables[id2]);
477
+ });
478
+
479
+ // src/variables-registry/create-variable-type-registry.ts
480
+ function createVariableTypeRegistry() {
481
+ const variableTypes = {};
482
+ const registerVariableType2 = ({
483
+ icon,
484
+ startIcon,
485
+ valueField,
486
+ propTypeUtil,
487
+ variableType,
488
+ fallbackPropTypeUtil
489
+ }) => {
490
+ if (variableTypes[propTypeUtil.key]) {
491
+ throw new Error(`Variable with key "${propTypeUtil.key}" is already registered.`);
492
+ }
493
+ variableTypes[propTypeUtil.key] = {
494
+ icon,
495
+ startIcon,
496
+ valueField,
497
+ propTypeUtil,
498
+ variableType,
499
+ fallbackPropTypeUtil
500
+ };
501
+ registerTransformer(propTypeUtil.key);
502
+ registerInheritanceTransformer(propTypeUtil.key);
503
+ };
504
+ const registerTransformer = (key) => {
505
+ import_editor_canvas3.styleTransformersRegistry.register(key, variableTransformer);
506
+ };
507
+ const registerInheritanceTransformer = (key) => {
508
+ import_editor_editing_panel.stylesInheritanceTransformersRegistry.register(key, inheritanceTransformer);
509
+ };
510
+ const getVariableType2 = (key) => {
511
+ return variableTypes[key];
512
+ };
513
+ const hasVariableType2 = (key) => {
514
+ return key in variableTypes;
515
+ };
516
+ return {
517
+ registerVariableType: registerVariableType2,
518
+ getVariableType: getVariableType2,
519
+ hasVariableType: hasVariableType2
520
+ };
521
+ }
522
+
523
+ // src/variables-registry/variable-type-registry.ts
524
+ var { registerVariableType, getVariableType, hasVariableType } = createVariableTypeRegistry();
525
+
526
+ // src/components/variable-selection-popover.tsx
527
+ var React14 = __toESM(require("react"));
528
+ var import_react10 = require("react");
529
+ var import_editor_v1_adapters2 = require("@elementor/editor-v1-adapters");
530
+
531
+ // src/context/variable-selection-popover.context.tsx
532
+ var React3 = __toESM(require("react"));
533
+ var import_react2 = require("react");
534
+ var import_ui4 = require("@elementor/ui");
535
+ var PopoverContentRefContext = (0, import_react2.createContext)(null);
536
+ var PopoverContentRefContextProvider = ({ children }) => {
537
+ const [anchorRef, setAnchorRef] = (0, import_react2.useState)(null);
538
+ return /* @__PURE__ */ React3.createElement(PopoverContentRefContext.Provider, { value: anchorRef }, /* @__PURE__ */ React3.createElement(import_ui4.Box, { ref: setAnchorRef }, children));
539
+ };
540
+ var usePopoverContentRef = () => {
541
+ return (0, import_react2.useContext)(PopoverContentRefContext);
542
+ };
543
+
544
+ // src/context/variable-type-context.tsx
545
+ var React4 = __toESM(require("react"));
546
+ var import_react3 = require("react");
547
+ var VariableTypeContext = (0, import_react3.createContext)(null);
548
+ function VariableTypeProvider({ children, propTypeKey }) {
549
+ return /* @__PURE__ */ React4.createElement(VariableTypeContext.Provider, { value: propTypeKey }, children);
550
+ }
551
+ function useVariableType() {
552
+ const context = (0, import_react3.useContext)(VariableTypeContext);
553
+ if (context === null) {
554
+ throw new Error("useVariableType must be used within a VariableTypeProvider");
377
555
  }
378
- return (0, import_i18n.__)("There was a glitch. Try saving your variable again.", "elementor");
556
+ return getVariableType(context);
557
+ }
558
+
559
+ // src/hooks/use-permissions.ts
560
+ var import_editor_current_user = require("@elementor/editor-current-user");
561
+ var usePermissions = () => {
562
+ const { canUser } = (0, import_editor_current_user.useCurrentUserCapabilities)();
563
+ return {
564
+ canAssign: () => canUser("edit_posts"),
565
+ canUnlink: () => canUser("edit_posts"),
566
+ canAdd: () => canUser("manage_options"),
567
+ canDelete: () => canUser("manage_options"),
568
+ canEdit: () => canUser("manage_options"),
569
+ canRestore: () => canUser("manage_options"),
570
+ canManageSettings: () => canUser("manage_options")
571
+ };
379
572
  };
380
573
 
574
+ // src/components/variable-creation.tsx
575
+ var React6 = __toESM(require("react"));
576
+ var import_react6 = require("react");
577
+ var import_editor_controls2 = require("@elementor/editor-controls");
578
+ var import_editor_editing_panel2 = require("@elementor/editor-editing-panel");
579
+ var import_editor_ui2 = require("@elementor/editor-ui");
580
+ var import_icons2 = require("@elementor/icons");
581
+ var import_ui6 = require("@elementor/ui");
582
+ var import_i18n6 = require("@wordpress/i18n");
583
+
584
+ // src/hooks/use-initial-value.ts
585
+ var import_editor_controls = require("@elementor/editor-controls");
586
+
381
587
  // src/hooks/use-prop-variables.ts
588
+ var import_react4 = require("react");
382
589
  var useVariable = (key) => {
383
590
  const variables = service.variables();
384
591
  if (!variables?.[key]) {
@@ -401,7 +608,7 @@ var useFilteredVariables = (searchValue, propTypeKey) => {
401
608
  };
402
609
  };
403
610
  var usePropVariables = (propKey) => {
404
- return (0, import_react.useMemo)(() => normalizeVariables(propKey), [propKey]);
611
+ return (0, import_react4.useMemo)(() => normalizeVariables(propKey), [propKey]);
405
612
  };
406
613
  var isNotDeleted = ({ deleted }) => !deleted;
407
614
  var normalizeVariables = (propKey) => {
@@ -413,145 +620,166 @@ var normalizeVariables = (propKey) => {
413
620
  }));
414
621
  };
415
622
  var createVariable = (newVariable) => {
416
- return service.create(newVariable).then(({ id }) => {
417
- return id;
623
+ return service.create(newVariable).then(({ id: id2 }) => {
624
+ return id2;
418
625
  });
419
626
  };
420
627
  var updateVariable = (updateId, { value, label }) => {
421
- return service.update(updateId, { value, label }).then(({ id }) => {
422
- return id;
628
+ return service.update(updateId, { value, label }).then(({ id: id2 }) => {
629
+ return id2;
423
630
  });
424
631
  };
425
632
  var deleteVariable = (deleteId) => {
426
- return service.delete(deleteId).then(({ id }) => {
427
- return id;
633
+ return service.delete(deleteId).then(({ id: id2 }) => {
634
+ return id2;
428
635
  });
429
636
  };
430
- var restoreVariable = (restoreId) => {
431
- return service.restore(restoreId).then(({ id }) => {
432
- return id;
637
+ var restoreVariable = (restoreId, label, value) => {
638
+ return service.restore(restoreId, label, value).then(({ id: id2 }) => {
639
+ return id2;
433
640
  });
434
641
  };
435
642
 
436
- // src/components/fields/color-field.tsx
437
- var React = __toESM(require("react"));
438
- var import_react3 = require("react");
439
- var import_ui2 = require("@elementor/ui");
440
- var import_i18n3 = require("@wordpress/i18n");
643
+ // src/hooks/use-initial-value.ts
644
+ var useInitialValue = () => {
645
+ const { value: initial } = (0, import_editor_controls.useBoundProp)();
646
+ const hasAssignedVariable2 = hasVariableType(initial?.$$type) && Boolean(initial?.value);
647
+ const variable = useVariable(hasAssignedVariable2 ? initial.value : "");
648
+ if (hasAssignedVariable2) {
649
+ return variable ? variable.value : "";
650
+ }
651
+ return initial?.value ?? "";
652
+ };
653
+
654
+ // src/utils/tracking.ts
655
+ var trackVariableEvent = ({ varType, controlPath, action }) => {
656
+ const extendedWindow = window;
657
+ const config = extendedWindow?.elementorCommon?.eventsManager?.config;
658
+ if (!config?.names?.variables?.[action]) {
659
+ return;
660
+ }
661
+ const name = config.names.variables[action];
662
+ extendedWindow.elementorCommon?.eventsManager?.dispatchEvent(name, {
663
+ location: config.locations.variables,
664
+ secondaryLocation: config.secondaryLocations.variablesPopover,
665
+ trigger: config.triggers.click,
666
+ var_type: varType,
667
+ control_path: controlPath,
668
+ action_type: name
669
+ });
670
+ };
441
671
 
442
672
  // src/utils/validations.ts
443
- var import_i18n2 = require("@wordpress/i18n");
673
+ var import_i18n4 = require("@wordpress/i18n");
674
+ var ERROR_MESSAGES = {
675
+ MISSING_VARIABLE_NAME: (0, import_i18n4.__)("Give your variable a name.", "elementor"),
676
+ MISSING_VARIABLE_VALUE: (0, import_i18n4.__)("Add a value to complete your variable.", "elementor"),
677
+ INVALID_CHARACTERS: (0, import_i18n4.__)("Use letters, numbers, dashes (-), or underscores (_) for the name.", "elementor"),
678
+ NO_NON_SPECIAL_CHARACTER: (0, import_i18n4.__)("Names have to include at least one non-special character.", "elementor"),
679
+ VARIABLE_LABEL_MAX_LENGTH: (0, import_i18n4.__)("Keep names up to 50 characters.", "elementor"),
680
+ DUPLICATED_LABEL: (0, import_i18n4.__)("This variable name already exists. Please choose a unique name.", "elementor"),
681
+ UNEXPECTED_ERROR: (0, import_i18n4.__)("There was a glitch. Try saving your variable again.", "elementor")
682
+ };
444
683
  var VARIABLE_LABEL_MAX_LENGTH = 50;
684
+ var mapServerError = (error) => {
685
+ if (error?.response?.data?.code === "duplicated_label") {
686
+ return {
687
+ field: "label",
688
+ message: ERROR_MESSAGES.DUPLICATED_LABEL
689
+ };
690
+ }
691
+ return void 0;
692
+ };
445
693
  var validateLabel = (name) => {
446
694
  if (!name.trim()) {
447
- return (0, import_i18n2.__)("Give your variable a name.", "elementor");
695
+ return ERROR_MESSAGES.MISSING_VARIABLE_NAME;
448
696
  }
449
697
  const allowedChars = /^[a-zA-Z0-9_-]+$/;
450
698
  if (!allowedChars.test(name)) {
451
- return (0, import_i18n2.__)("Use letters, numbers, dashes (-), or underscores (_) for the name.", "elementor");
699
+ return ERROR_MESSAGES.INVALID_CHARACTERS;
452
700
  }
453
701
  const hasAlphanumeric = /[a-zA-Z0-9]/;
454
702
  if (!hasAlphanumeric.test(name)) {
455
- return (0, import_i18n2.__)("Names have to include at least one non-special character.", "elementor");
703
+ return ERROR_MESSAGES.NO_NON_SPECIAL_CHARACTER;
456
704
  }
457
705
  if (VARIABLE_LABEL_MAX_LENGTH < name.length) {
458
- return (0, import_i18n2.__)("Keep names up to 50 characters.", "elementor");
706
+ return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
459
707
  }
460
708
  return "";
461
709
  };
462
710
  var labelHint = (name) => {
463
711
  const hintThreshold = VARIABLE_LABEL_MAX_LENGTH * 0.8 - 1;
464
712
  if (hintThreshold < name.length) {
465
- return (0, import_i18n2.__)("Keep names up to 50 characters.", "elementor");
713
+ return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
466
714
  }
467
715
  return "";
468
716
  };
469
717
  var validateValue = (value) => {
470
718
  if (!value.trim()) {
471
- return (0, import_i18n2.__)("Add a value to complete your variable.", "elementor");
719
+ return ERROR_MESSAGES.MISSING_VARIABLE_VALUE;
472
720
  }
473
721
  return "";
474
722
  };
475
723
 
476
- // src/components/variable-selection-popover.context.ts
477
- var import_react2 = require("react");
478
- var PopoverContentRefContext = (0, import_react2.createContext)(null);
479
- var usePopoverContentRef = () => {
480
- return (0, import_react2.useContext)(PopoverContentRefContext);
481
- };
482
-
483
- // src/components/fields/color-field.tsx
484
- var ColorField = ({ value, onChange }) => {
485
- const [color, setColor] = (0, import_react3.useState)(value);
486
- const [errorMessage, setErrorMessage] = (0, import_react3.useState)("");
487
- const defaultRef = (0, import_react3.useRef)(null);
488
- const anchorRef = usePopoverContentRef() ?? defaultRef;
489
- const handleChange = (newValue) => {
490
- setColor(newValue);
491
- const errorMsg = validateValue(newValue);
492
- setErrorMessage(errorMsg);
493
- onChange(errorMsg ? "" : newValue);
724
+ // src/components/fields/label-field.tsx
725
+ var React5 = __toESM(require("react"));
726
+ var import_react5 = require("react");
727
+ var import_ui5 = require("@elementor/ui");
728
+ var import_i18n5 = require("@wordpress/i18n");
729
+ function isLabelEqual(a, b) {
730
+ return a.trim().toLowerCase() === b.trim().toLowerCase();
731
+ }
732
+ var useLabelError = (initialError) => {
733
+ const [error, setError] = (0, import_react5.useState)(initialError ?? { value: "", message: "" });
734
+ return {
735
+ labelFieldError: error,
736
+ setLabelFieldError: setError
494
737
  };
495
- return /* @__PURE__ */ React.createElement(import_ui2.Grid, { container: true, gap: 0.75, alignItems: "center" }, /* @__PURE__ */ React.createElement(import_ui2.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(import_ui2.FormLabel, { size: "tiny" }, (0, import_i18n3.__)("Value", "elementor"))), /* @__PURE__ */ React.createElement(import_ui2.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
496
- import_ui2.UnstableColorField,
497
- {
498
- size: "tiny",
499
- fullWidth: true,
500
- value: color,
501
- onChange: handleChange,
502
- error: errorMessage ?? void 0,
503
- slotProps: {
504
- colorPicker: {
505
- anchorEl: anchorRef.current,
506
- anchorOrigin: { vertical: "top", horizontal: "right" },
507
- transformOrigin: { vertical: "top", horizontal: -10 }
508
- }
509
- }
510
- }
511
- ), errorMessage && /* @__PURE__ */ React.createElement(import_ui2.FormHelperText, { error: true }, errorMessage)));
512
738
  };
513
-
514
- // src/components/fields/label-field.tsx
515
- var React2 = __toESM(require("react"));
516
- var import_react4 = require("react");
517
- var import_ui3 = require("@elementor/ui");
518
- var import_i18n4 = require("@wordpress/i18n");
519
- var LabelField = ({ value, onChange }) => {
520
- const [label, setLabel] = (0, import_react4.useState)(value);
521
- const [errorMessage, setErrorMessage] = (0, import_react4.useState)("");
522
- const [noticeMessage, setNoticeMessage] = (0, import_react4.useState)(() => labelHint(value));
739
+ var LabelField = ({ value, error, onChange }) => {
740
+ const [label, setLabel] = (0, import_react5.useState)(value);
741
+ const [errorMessage, setErrorMessage] = (0, import_react5.useState)("");
742
+ const [noticeMessage, setNoticeMessage] = (0, import_react5.useState)(() => labelHint(value));
523
743
  const handleChange = (newValue) => {
524
744
  setLabel(newValue);
525
- const errorMsg = validateLabel(newValue);
745
+ const errorMsg2 = validateLabel(newValue);
526
746
  const hintMsg = labelHint(newValue);
527
- setErrorMessage(errorMsg);
528
- setNoticeMessage(errorMsg ? "" : hintMsg);
529
- onChange(errorMsg ? "" : newValue);
747
+ setErrorMessage(errorMsg2);
748
+ setNoticeMessage(errorMsg2 ? "" : hintMsg);
749
+ onChange(isLabelEqual(newValue, error?.value ?? "") || errorMsg2 ? "" : newValue);
530
750
  };
531
- const id = (0, import_react4.useId)();
532
- return /* @__PURE__ */ React2.createElement(import_ui3.Grid, { container: true, gap: 0.75, alignItems: "center" }, /* @__PURE__ */ React2.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React2.createElement(import_ui3.FormLabel, { htmlFor: id, size: "tiny" }, (0, import_i18n4.__)("Name", "elementor"))), /* @__PURE__ */ React2.createElement(import_ui3.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React2.createElement(
533
- import_ui3.TextField,
751
+ const id2 = (0, import_react5.useId)();
752
+ let errorMsg = errorMessage;
753
+ if (isLabelEqual(label, error?.value ?? "") && error?.message) {
754
+ errorMsg = error.message;
755
+ }
756
+ const noticeMsg = errorMsg ? "" : noticeMessage;
757
+ return /* @__PURE__ */ React5.createElement(import_ui5.Grid, { container: true, gap: 0.75, alignItems: "center" }, /* @__PURE__ */ React5.createElement(import_ui5.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React5.createElement(import_ui5.FormLabel, { htmlFor: id2, size: "tiny" }, (0, import_i18n5.__)("Name", "elementor"))), /* @__PURE__ */ React5.createElement(import_ui5.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React5.createElement(
758
+ import_ui5.TextField,
534
759
  {
535
- id,
760
+ id: id2,
536
761
  size: "tiny",
537
762
  fullWidth: true,
538
763
  value: label,
539
- error: !!errorMessage,
764
+ error: !!errorMsg,
540
765
  onChange: (e) => handleChange(e.target.value),
541
766
  inputProps: { maxLength: VARIABLE_LABEL_MAX_LENGTH }
542
767
  }
543
- ), errorMessage && /* @__PURE__ */ React2.createElement(import_ui3.FormHelperText, { error: true }, errorMessage), noticeMessage && /* @__PURE__ */ React2.createElement(import_ui3.FormHelperText, null, noticeMessage)));
768
+ ), errorMsg && /* @__PURE__ */ React5.createElement(import_ui5.FormHelperText, { error: true }, errorMsg), noticeMsg && /* @__PURE__ */ React5.createElement(import_ui5.FormHelperText, null, noticeMsg)));
544
769
  };
545
770
 
546
- // src/components/color-variable-creation.tsx
771
+ // src/components/variable-creation.tsx
547
772
  var SIZE = "tiny";
548
- var ColorVariableCreation = ({ onGoBack, onClose }) => {
549
- const { setValue: setVariable } = (0, import_editor_controls.useBoundProp)(colorVariablePropTypeUtil);
550
- const [color, setColor] = (0, import_react5.useState)("");
551
- const [label, setLabel] = (0, import_react5.useState)("");
552
- const [errorMessage, setErrorMessage] = (0, import_react5.useState)("");
773
+ var VariableCreation = ({ onGoBack, onClose }) => {
774
+ const { icon: VariableIcon, valueField: ValueField, variableType, propTypeUtil } = useVariableType();
775
+ const { setValue: setVariable, path } = (0, import_editor_controls2.useBoundProp)(propTypeUtil);
776
+ const initialValue = useInitialValue();
777
+ const [value, setValue] = (0, import_react6.useState)(initialValue);
778
+ const [label, setLabel] = (0, import_react6.useState)("");
779
+ const [errorMessage, setErrorMessage] = (0, import_react6.useState)("");
780
+ const { labelFieldError, setLabelFieldError } = useLabelError();
553
781
  const resetFields = () => {
554
- setColor("");
782
+ setValue("");
555
783
  setLabel("");
556
784
  setErrorMessage("");
557
785
  };
@@ -559,96 +787,187 @@ var ColorVariableCreation = ({ onGoBack, onClose }) => {
559
787
  resetFields();
560
788
  onClose();
561
789
  };
562
- const handleCreate = () => {
790
+ const handleCreateAndTrack = () => {
563
791
  createVariable({
564
- value: color,
792
+ value,
565
793
  label,
566
- type: colorVariablePropTypeUtil.key
794
+ type: propTypeUtil.key
567
795
  }).then((key) => {
568
796
  setVariable(key);
569
797
  closePopover();
570
798
  }).catch((error) => {
571
- setErrorMessage(error.message);
799
+ const mappedError = mapServerError(error);
800
+ if (mappedError && "label" === mappedError.field) {
801
+ setLabel("");
802
+ setLabelFieldError({
803
+ value: label,
804
+ message: mappedError.message
805
+ });
806
+ return;
807
+ }
808
+ setErrorMessage(ERROR_MESSAGES.UNEXPECTED_ERROR);
809
+ });
810
+ trackVariableEvent({
811
+ varType: variableType,
812
+ controlPath: path.join("."),
813
+ action: "save"
572
814
  });
573
815
  };
574
816
  const hasEmptyValue = () => {
575
- return "" === color.trim() || "" === label.trim();
817
+ return "" === value.trim() || "" === label.trim();
818
+ };
819
+ const hasErrors = () => {
820
+ return !!errorMessage;
576
821
  };
577
- const isSubmitDisabled = hasEmptyValue();
578
- return /* @__PURE__ */ React3.createElement(import_editor_editing_panel.PopoverBody, { height: "auto" }, /* @__PURE__ */ React3.createElement(
579
- import_editor_ui.PopoverHeader,
822
+ const isSubmitDisabled = hasEmptyValue() || hasErrors();
823
+ return /* @__PURE__ */ React6.createElement(import_editor_editing_panel2.PopoverBody, { height: "auto" }, /* @__PURE__ */ React6.createElement(
824
+ import_editor_ui2.PopoverHeader,
580
825
  {
581
- icon: /* @__PURE__ */ React3.createElement(React3.Fragment, null, onGoBack && /* @__PURE__ */ React3.createElement(import_ui4.IconButton, { size: SIZE, "aria-label": (0, import_i18n5.__)("Go Back", "elementor"), onClick: onGoBack }, /* @__PURE__ */ React3.createElement(import_icons.ArrowLeftIcon, { fontSize: SIZE })), /* @__PURE__ */ React3.createElement(import_icons.BrushIcon, { fontSize: SIZE })),
582
- title: (0, import_i18n5.__)("Create variable", "elementor"),
826
+ icon: /* @__PURE__ */ React6.createElement(React6.Fragment, null, onGoBack && /* @__PURE__ */ React6.createElement(import_ui6.IconButton, { size: SIZE, "aria-label": (0, import_i18n6.__)("Go Back", "elementor"), onClick: onGoBack }, /* @__PURE__ */ React6.createElement(import_icons2.ArrowLeftIcon, { fontSize: SIZE })), /* @__PURE__ */ React6.createElement(VariableIcon, { fontSize: SIZE })),
827
+ title: (0, import_i18n6.__)("Create variable", "elementor"),
583
828
  onClose: closePopover
584
829
  }
585
- ), /* @__PURE__ */ React3.createElement(import_ui4.Divider, null), /* @__PURE__ */ React3.createElement(import_editor_controls.PopoverContent, { p: 2 }, /* @__PURE__ */ React3.createElement(
830
+ ), /* @__PURE__ */ React6.createElement(import_ui6.Divider, null), /* @__PURE__ */ React6.createElement(import_editor_controls2.PopoverContent, { p: 2 }, /* @__PURE__ */ React6.createElement(
586
831
  LabelField,
587
832
  {
588
833
  value: label,
589
- onChange: (value) => {
590
- setLabel(value);
834
+ error: labelFieldError,
835
+ onChange: (newValue) => {
836
+ setLabel(newValue);
591
837
  setErrorMessage("");
592
838
  }
593
839
  }
594
- ), /* @__PURE__ */ React3.createElement(
595
- ColorField,
840
+ ), /* @__PURE__ */ React6.createElement(
841
+ ValueField,
596
842
  {
597
- value: color,
598
- onChange: (value) => {
599
- setColor(value);
843
+ value,
844
+ onChange: (newValue) => {
845
+ setValue(newValue);
600
846
  setErrorMessage("");
601
847
  }
602
848
  }
603
- ), errorMessage && /* @__PURE__ */ React3.createElement(import_ui4.FormHelperText, { error: true }, errorMessage)), /* @__PURE__ */ React3.createElement(import_ui4.CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React3.createElement(import_ui4.Button, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleCreate }, (0, import_i18n5.__)("Create", "elementor"))));
849
+ ), errorMessage && /* @__PURE__ */ React6.createElement(import_ui6.FormHelperText, { error: true }, errorMessage)), /* @__PURE__ */ React6.createElement(import_ui6.CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React6.createElement(import_ui6.Button, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleCreateAndTrack }, (0, import_i18n6.__)("Create", "elementor"))));
604
850
  };
605
851
 
606
- // src/components/color-variable-edit.tsx
607
- var React5 = __toESM(require("react"));
608
- var import_react6 = require("react");
609
- var import_editor_controls2 = require("@elementor/editor-controls");
610
- var import_editor_editing_panel2 = require("@elementor/editor-editing-panel");
611
- var import_editor_ui2 = require("@elementor/editor-ui");
612
- var import_icons3 = require("@elementor/icons");
613
- var import_ui6 = require("@elementor/ui");
614
- var import_i18n7 = require("@wordpress/i18n");
852
+ // src/components/variable-edit.tsx
853
+ var React9 = __toESM(require("react"));
854
+ var import_react8 = require("react");
855
+ var import_editor_controls3 = require("@elementor/editor-controls");
856
+ var import_editor_current_user2 = require("@elementor/editor-current-user");
857
+ var import_editor_editing_panel3 = require("@elementor/editor-editing-panel");
858
+ var import_editor_ui3 = require("@elementor/editor-ui");
859
+ var import_icons5 = require("@elementor/icons");
860
+ var import_ui9 = require("@elementor/ui");
861
+ var import_i18n9 = require("@wordpress/i18n");
615
862
 
616
863
  // src/components/ui/delete-confirmation-dialog.tsx
617
- var React4 = __toESM(require("react"));
618
- var import_icons2 = require("@elementor/icons");
619
- var import_ui5 = require("@elementor/ui");
620
- var import_i18n6 = require("@wordpress/i18n");
621
- var TITLE_ID = "delete-variable-dialog";
622
- var DeleteConfirmationDialog = ({
864
+ var React7 = __toESM(require("react"));
865
+ var import_icons3 = require("@elementor/icons");
866
+ var import_ui7 = require("@elementor/ui");
867
+ var import_i18n7 = require("@wordpress/i18n");
868
+ var TITLE_ID = "delete-variable-dialog";
869
+ var DeleteConfirmationDialog = ({
623
870
  open,
624
871
  label,
625
872
  closeDialog,
626
873
  onConfirm
627
874
  }) => {
628
- return /* @__PURE__ */ React4.createElement(import_ui5.Dialog, { open, onClose: closeDialog, "aria-labelledby": TITLE_ID, maxWidth: "xs" }, /* @__PURE__ */ React4.createElement(import_ui5.DialogTitle, { id: TITLE_ID, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React4.createElement(import_icons2.AlertOctagonFilledIcon, { color: "error" }), (0, import_i18n6.__)("Delete this variable?", "elementor")), /* @__PURE__ */ React4.createElement(import_ui5.DialogContent, null, /* @__PURE__ */ React4.createElement(import_ui5.DialogContentText, { variant: "body2", color: "textPrimary" }, (0, import_i18n6.__)("All elements using", "elementor"), /* @__PURE__ */ React4.createElement(import_ui5.Typography, { variant: "subtitle2", component: "span" }, "\xA0", label, "\xA0"), (0, import_i18n6.__)("will keep their current values, but the variable itself will be removed.", "elementor"))), /* @__PURE__ */ React4.createElement(import_ui5.DialogActions, null, /* @__PURE__ */ React4.createElement(import_ui5.Button, { color: "secondary", onClick: closeDialog }, (0, import_i18n6.__)("Not now", "elementor")), /* @__PURE__ */ React4.createElement(import_ui5.Button, { variant: "contained", color: "error", onClick: onConfirm }, (0, import_i18n6.__)("Delete", "elementor"))));
875
+ return /* @__PURE__ */ React7.createElement(import_ui7.Dialog, { open, onClose: closeDialog, "aria-labelledby": TITLE_ID, maxWidth: "xs" }, /* @__PURE__ */ React7.createElement(import_ui7.DialogTitle, { id: TITLE_ID, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React7.createElement(import_icons3.AlertOctagonFilledIcon, { color: "error" }), (0, import_i18n7.__)("Delete this variable?", "elementor")), /* @__PURE__ */ React7.createElement(import_ui7.DialogContent, null, /* @__PURE__ */ React7.createElement(import_ui7.DialogContentText, { variant: "body2", color: "textPrimary" }, (0, import_i18n7.__)("All elements using", "elementor"), /* @__PURE__ */ React7.createElement(import_ui7.Typography, { variant: "subtitle2", component: "span" }, "\xA0", label, "\xA0"), (0, import_i18n7.__)("will keep their current values, but the variable itself will be removed.", "elementor"))), /* @__PURE__ */ React7.createElement(import_ui7.DialogActions, null, /* @__PURE__ */ React7.createElement(import_ui7.Button, { color: "secondary", onClick: closeDialog }, (0, import_i18n7.__)("Not now", "elementor")), /* @__PURE__ */ React7.createElement(import_ui7.Button, { variant: "contained", color: "error", onClick: onConfirm }, (0, import_i18n7.__)("Delete", "elementor"))));
876
+ };
877
+
878
+ // src/components/ui/edit-confirmation-dialog.tsx
879
+ var React8 = __toESM(require("react"));
880
+ var import_react7 = require("react");
881
+ var import_icons4 = require("@elementor/icons");
882
+ var import_ui8 = require("@elementor/ui");
883
+ var import_i18n8 = require("@wordpress/i18n");
884
+ var EDIT_CONFIRMATION_DIALOG_ID = "edit-confirmation-dialog";
885
+ var EditConfirmationDialog = ({
886
+ closeDialog,
887
+ onConfirm,
888
+ onSuppressMessage
889
+ }) => {
890
+ const [dontShowAgain, setDontShowAgain] = (0, import_react7.useState)(false);
891
+ const handleSave = () => {
892
+ if (dontShowAgain) {
893
+ onSuppressMessage?.();
894
+ }
895
+ onConfirm?.();
896
+ };
897
+ return /* @__PURE__ */ React8.createElement(import_ui8.Dialog, { open: true, onClose: closeDialog, maxWidth: "xs" }, /* @__PURE__ */ React8.createElement(import_ui8.DialogTitle, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ React8.createElement(import_icons4.AlertTriangleFilledIcon, { color: "secondary" }), (0, import_i18n8.__)("Changes to variables go live right away.", "elementor")), /* @__PURE__ */ React8.createElement(import_ui8.DialogContent, null, /* @__PURE__ */ React8.createElement(import_ui8.DialogContentText, { variant: "body2", color: "textPrimary" }, (0, import_i18n8.__)(
898
+ "Don't worry - all other changes you make will wait until you publish your site.",
899
+ "elementor"
900
+ ))), /* @__PURE__ */ React8.createElement(import_ui8.DialogActions, { sx: { justifyContent: "space-between", alignItems: "center" } }, /* @__PURE__ */ React8.createElement(
901
+ import_ui8.FormControlLabel,
902
+ {
903
+ control: /* @__PURE__ */ React8.createElement(
904
+ import_ui8.Checkbox,
905
+ {
906
+ checked: dontShowAgain,
907
+ onChange: (event) => setDontShowAgain(event.target.checked),
908
+ size: "small"
909
+ }
910
+ ),
911
+ label: /* @__PURE__ */ React8.createElement(import_ui8.Typography, { variant: "body2" }, (0, import_i18n8.__)("Don't show me again", "elementor"))
912
+ }
913
+ ), /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement(import_ui8.Button, { color: "secondary", onClick: closeDialog }, (0, import_i18n8.__)("Keep editing", "elementor")), /* @__PURE__ */ React8.createElement(import_ui8.Button, { variant: "contained", color: "secondary", onClick: handleSave, sx: { ml: 1 } }, (0, import_i18n8.__)("Save", "elementor")))));
629
914
  };
630
915
 
631
- // src/components/color-variable-edit.tsx
916
+ // src/components/variable-edit.tsx
632
917
  var SIZE2 = "tiny";
633
- var ColorVariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
634
- const { setValue: notifyBoundPropChange, value: assignedValue } = (0, import_editor_controls2.useBoundProp)(colorVariablePropTypeUtil);
635
- const [deleteConfirmation, setDeleteConfirmation] = (0, import_react6.useState)(false);
636
- const [errorMessage, setErrorMessage] = (0, import_react6.useState)("");
918
+ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
919
+ const { icon: VariableIcon, valueField: ValueField, variableType, propTypeUtil } = useVariableType();
920
+ const { setValue: notifyBoundPropChange, value: assignedValue } = (0, import_editor_controls3.useBoundProp)(propTypeUtil);
921
+ const [isMessageSuppressed, suppressMessage] = (0, import_editor_current_user2.useSuppressedMessage)(EDIT_CONFIRMATION_DIALOG_ID);
922
+ const [deleteConfirmation, setDeleteConfirmation] = (0, import_react8.useState)(false);
923
+ const [editConfirmation, setEditConfirmation] = (0, import_react8.useState)(false);
924
+ const [errorMessage, setErrorMessage] = (0, import_react8.useState)("");
925
+ const { labelFieldError, setLabelFieldError } = useLabelError();
637
926
  const variable = useVariable(editId);
638
927
  if (!variable) {
639
- throw new Error(`Global color variable not found`);
928
+ throw new Error(`Global ${variableType} variable not found`);
640
929
  }
641
- const [color, setColor] = (0, import_react6.useState)(variable.value);
642
- const [label, setLabel] = (0, import_react6.useState)(variable.label);
930
+ const userPermissions = usePermissions();
931
+ const [value, setValue] = (0, import_react8.useState)(variable.value);
932
+ const [label, setLabel] = (0, import_react8.useState)(variable.label);
933
+ (0, import_react8.useEffect)(() => {
934
+ styleVariablesRepository.update({
935
+ [editId]: {
936
+ ...variable,
937
+ value
938
+ }
939
+ });
940
+ return () => {
941
+ styleVariablesRepository.update({
942
+ [editId]: { ...variable }
943
+ });
944
+ };
945
+ }, [editId, value, variable]);
643
946
  const handleUpdate = () => {
947
+ if (isMessageSuppressed) {
948
+ handleSaveVariable();
949
+ } else {
950
+ setEditConfirmation(true);
951
+ }
952
+ };
953
+ const handleSaveVariable = () => {
644
954
  updateVariable(editId, {
645
- value: color,
955
+ value,
646
956
  label
647
957
  }).then(() => {
648
958
  maybeTriggerBoundPropChange();
649
959
  onSubmit?.();
650
960
  }).catch((error) => {
651
- setErrorMessage(error.message);
961
+ const mappedError = mapServerError(error);
962
+ if (mappedError && "label" === mappedError.field) {
963
+ setLabel("");
964
+ setLabelFieldError({
965
+ value: label,
966
+ message: mappedError.message
967
+ });
968
+ return;
969
+ }
970
+ setErrorMessage(ERROR_MESSAGES.UNEXPECTED_ERROR);
652
971
  });
653
972
  };
654
973
  const handleDelete = () => {
@@ -668,61 +987,70 @@ var ColorVariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
668
987
  const closeDeleteDialog = () => () => {
669
988
  setDeleteConfirmation(false);
670
989
  };
990
+ const closeEditDialog = () => () => {
991
+ setEditConfirmation(false);
992
+ };
671
993
  const actions = [];
672
- actions.push(
673
- /* @__PURE__ */ React5.createElement(
674
- import_ui6.IconButton,
675
- {
676
- key: "delete",
677
- size: SIZE2,
678
- "aria-label": (0, import_i18n7.__)("Delete", "elementor"),
679
- onClick: handleDeleteConfirmation
680
- },
681
- /* @__PURE__ */ React5.createElement(import_icons3.TrashIcon, { fontSize: SIZE2 })
682
- )
683
- );
994
+ if (userPermissions.canDelete()) {
995
+ actions.push(
996
+ /* @__PURE__ */ React9.createElement(
997
+ import_ui9.IconButton,
998
+ {
999
+ key: "delete",
1000
+ size: SIZE2,
1001
+ "aria-label": (0, import_i18n9.__)("Delete", "elementor"),
1002
+ onClick: handleDeleteConfirmation
1003
+ },
1004
+ /* @__PURE__ */ React9.createElement(import_icons5.TrashIcon, { fontSize: SIZE2 })
1005
+ )
1006
+ );
1007
+ }
684
1008
  const hasEmptyValues = () => {
685
- return !color.trim() || !label.trim();
1009
+ return !value.trim() || !label.trim();
686
1010
  };
687
1011
  const noValueChanged = () => {
688
- return color === variable.value && label === variable.label;
1012
+ return value === variable.value && label === variable.label;
689
1013
  };
690
- const isSubmitDisabled = noValueChanged() || hasEmptyValues();
691
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(import_editor_editing_panel2.PopoverBody, { height: "auto" }, /* @__PURE__ */ React5.createElement(
692
- import_editor_ui2.PopoverHeader,
1014
+ const hasErrors = () => {
1015
+ return !!errorMessage;
1016
+ };
1017
+ const isSubmitDisabled = noValueChanged() || hasEmptyValues() || hasErrors();
1018
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(import_editor_editing_panel3.PopoverBody, { height: "auto" }, /* @__PURE__ */ React9.createElement(
1019
+ import_editor_ui3.PopoverHeader,
693
1020
  {
694
- title: (0, import_i18n7.__)("Edit variable", "elementor"),
1021
+ title: (0, import_i18n9.__)("Edit variable", "elementor"),
695
1022
  onClose,
696
- icon: /* @__PURE__ */ React5.createElement(React5.Fragment, null, onGoBack && /* @__PURE__ */ React5.createElement(
697
- import_ui6.IconButton,
1023
+ icon: /* @__PURE__ */ React9.createElement(React9.Fragment, null, onGoBack && /* @__PURE__ */ React9.createElement(
1024
+ import_ui9.IconButton,
698
1025
  {
699
1026
  size: SIZE2,
700
- "aria-label": (0, import_i18n7.__)("Go Back", "elementor"),
1027
+ "aria-label": (0, import_i18n9.__)("Go Back", "elementor"),
701
1028
  onClick: onGoBack
702
1029
  },
703
- /* @__PURE__ */ React5.createElement(import_icons3.ArrowLeftIcon, { fontSize: SIZE2 })
704
- ), /* @__PURE__ */ React5.createElement(import_icons3.BrushIcon, { fontSize: SIZE2 })),
1030
+ /* @__PURE__ */ React9.createElement(import_icons5.ArrowLeftIcon, { fontSize: SIZE2 })
1031
+ ), /* @__PURE__ */ React9.createElement(VariableIcon, { fontSize: SIZE2 })),
705
1032
  actions
706
1033
  }
707
- ), /* @__PURE__ */ React5.createElement(import_ui6.Divider, null), /* @__PURE__ */ React5.createElement(import_editor_controls2.PopoverContent, { p: 2 }, /* @__PURE__ */ React5.createElement(
1034
+ ), /* @__PURE__ */ React9.createElement(import_ui9.Divider, null), /* @__PURE__ */ React9.createElement(import_editor_controls3.PopoverContent, { p: 2 }, /* @__PURE__ */ React9.createElement(
708
1035
  LabelField,
709
1036
  {
710
1037
  value: label,
711
- onChange: (value) => {
712
- setLabel(value);
1038
+ error: labelFieldError,
1039
+ onChange: (newValue) => {
1040
+ setLabel(newValue);
713
1041
  setErrorMessage("");
714
1042
  }
715
1043
  }
716
- ), /* @__PURE__ */ React5.createElement(
717
- ColorField,
1044
+ ), /* @__PURE__ */ React9.createElement(
1045
+ ValueField,
718
1046
  {
719
- value: color,
720
- onChange: (value) => {
721
- setColor(value);
1047
+ value,
1048
+ onChange: (newValue) => {
1049
+ setValue(newValue);
722
1050
  setErrorMessage("");
723
1051
  }
724
1052
  }
725
- ), errorMessage && /* @__PURE__ */ React5.createElement(import_ui6.FormHelperText, { error: true }, errorMessage)), /* @__PURE__ */ React5.createElement(import_ui6.CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React5.createElement(import_ui6.Button, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleUpdate }, (0, import_i18n7.__)("Save", "elementor")))), deleteConfirmation && /* @__PURE__ */ React5.createElement(
1053
+ ), errorMessage && /* @__PURE__ */ React9.createElement(import_ui9.FormHelperText, { error: true }, errorMessage)), /* @__PURE__ */ React9.createElement(import_ui9.CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React9.createElement(import_ui9.Button, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleUpdate }, (0, import_i18n9.__)("Save", "elementor")))), deleteConfirmation && /* @__PURE__ */ React9.createElement(
726
1054
  DeleteConfirmationDialog,
727
1055
  {
728
1056
  open: true,
@@ -730,30 +1058,37 @@ var ColorVariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
730
1058
  onConfirm: handleDelete,
731
1059
  closeDialog: closeDeleteDialog()
732
1060
  }
1061
+ ), editConfirmation && !isMessageSuppressed && /* @__PURE__ */ React9.createElement(
1062
+ EditConfirmationDialog,
1063
+ {
1064
+ closeDialog: closeEditDialog(),
1065
+ onConfirm: handleSaveVariable,
1066
+ onSuppressMessage: suppressMessage
1067
+ }
733
1068
  ));
734
1069
  };
735
1070
 
736
- // src/components/color-variables-selection.tsx
737
- var React9 = __toESM(require("react"));
738
- var import_react7 = require("react");
739
- var import_editor_controls3 = require("@elementor/editor-controls");
740
- var import_editor_editing_panel3 = require("@elementor/editor-editing-panel");
741
- var import_editor_ui4 = require("@elementor/editor-ui");
742
- var import_icons5 = require("@elementor/icons");
743
- var import_ui11 = require("@elementor/ui");
744
- var import_i18n11 = require("@wordpress/i18n");
1071
+ // src/components/variables-selection.tsx
1072
+ var React13 = __toESM(require("react"));
1073
+ var import_react9 = require("react");
1074
+ var import_editor_controls4 = require("@elementor/editor-controls");
1075
+ var import_editor_editing_panel4 = require("@elementor/editor-editing-panel");
1076
+ var import_editor_ui5 = require("@elementor/editor-ui");
1077
+ var import_icons7 = require("@elementor/icons");
1078
+ var import_ui14 = require("@elementor/ui");
1079
+ var import_i18n13 = require("@wordpress/i18n");
745
1080
 
746
1081
  // src/components/ui/menu-item-content.tsx
747
- var React6 = __toESM(require("react"));
748
- var import_editor_ui3 = require("@elementor/editor-ui");
749
- var import_icons4 = require("@elementor/icons");
750
- var import_ui7 = require("@elementor/ui");
751
- var import_i18n8 = require("@wordpress/i18n");
1082
+ var React10 = __toESM(require("react"));
1083
+ var import_editor_ui4 = require("@elementor/editor-ui");
1084
+ var import_icons6 = require("@elementor/icons");
1085
+ var import_ui10 = require("@elementor/ui");
1086
+ var import_i18n10 = require("@wordpress/i18n");
752
1087
  var SIZE3 = "tiny";
753
1088
  var MenuItemContent = ({ item }) => {
754
1089
  const onEdit = item.onEdit;
755
- return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(import_ui7.ListItemIcon, null, item.icon), /* @__PURE__ */ React6.createElement(
756
- import_ui7.Box,
1090
+ return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(import_ui10.ListItemIcon, null, item.icon), /* @__PURE__ */ React10.createElement(
1091
+ import_ui10.Box,
757
1092
  {
758
1093
  sx: {
759
1094
  flex: 1,
@@ -763,49 +1098,49 @@ var MenuItemContent = ({ item }) => {
763
1098
  gap: 1
764
1099
  }
765
1100
  },
766
- /* @__PURE__ */ React6.createElement(
767
- import_editor_ui3.EllipsisWithTooltip,
1101
+ /* @__PURE__ */ React10.createElement(
1102
+ import_editor_ui4.EllipsisWithTooltip,
768
1103
  {
769
1104
  title: item.label || item.value,
770
- as: import_ui7.Typography,
1105
+ as: import_ui10.Typography,
771
1106
  variant: "caption",
772
1107
  color: "text.primary",
773
1108
  sx: { marginTop: "1px", lineHeight: "2" },
774
1109
  maxWidth: "50%"
775
1110
  }
776
1111
  ),
777
- item.secondaryText && /* @__PURE__ */ React6.createElement(
778
- import_editor_ui3.EllipsisWithTooltip,
1112
+ item.secondaryText && /* @__PURE__ */ React10.createElement(
1113
+ import_editor_ui4.EllipsisWithTooltip,
779
1114
  {
780
1115
  title: item.secondaryText,
781
- as: import_ui7.Typography,
1116
+ as: import_ui10.Typography,
782
1117
  variant: "caption",
783
1118
  color: "text.tertiary",
784
1119
  sx: { marginTop: "1px", lineHeight: "1" },
785
1120
  maxWidth: "50%"
786
1121
  }
787
1122
  )
788
- ), !!onEdit && /* @__PURE__ */ React6.createElement(
789
- import_ui7.IconButton,
1123
+ ), !!onEdit && /* @__PURE__ */ React10.createElement(
1124
+ import_ui10.IconButton,
790
1125
  {
791
1126
  sx: { mx: 1, opacity: "0" },
792
1127
  onClick: (e) => {
793
1128
  e.stopPropagation();
794
1129
  onEdit(item.value);
795
1130
  },
796
- "aria-label": (0, import_i18n8.__)("Edit", "elementor")
1131
+ "aria-label": (0, import_i18n10.__)("Edit", "elementor")
797
1132
  },
798
- /* @__PURE__ */ React6.createElement(import_icons4.EditIcon, { color: "action", fontSize: SIZE3 })
1133
+ /* @__PURE__ */ React10.createElement(import_icons6.EditIcon, { color: "action", fontSize: SIZE3 })
799
1134
  ));
800
1135
  };
801
1136
 
802
1137
  // src/components/ui/no-search-results.tsx
803
- var React7 = __toESM(require("react"));
804
- var import_ui8 = require("@elementor/ui");
805
- var import_i18n9 = require("@wordpress/i18n");
1138
+ var React11 = __toESM(require("react"));
1139
+ var import_ui11 = require("@elementor/ui");
1140
+ var import_i18n11 = require("@wordpress/i18n");
806
1141
  var NoSearchResults = ({ searchValue, onClear, icon }) => {
807
- return /* @__PURE__ */ React7.createElement(
808
- import_ui8.Stack,
1142
+ return /* @__PURE__ */ React11.createElement(
1143
+ import_ui11.Stack,
809
1144
  {
810
1145
  gap: 1,
811
1146
  alignItems: "center",
@@ -816,34 +1151,53 @@ var NoSearchResults = ({ searchValue, onClear, icon }) => {
816
1151
  sx: { pb: 3.5 }
817
1152
  },
818
1153
  icon,
819
- /* @__PURE__ */ React7.createElement(import_ui8.Typography, { align: "center", variant: "subtitle2" }, (0, import_i18n9.__)("Sorry, nothing matched", "elementor"), /* @__PURE__ */ React7.createElement("br", null), "\u201C", searchValue, "\u201D."),
820
- /* @__PURE__ */ React7.createElement(import_ui8.Typography, { align: "center", variant: "caption", sx: { display: "flex", flexDirection: "column" } }, (0, import_i18n9.__)("Try something else.", "elementor"), /* @__PURE__ */ React7.createElement(import_ui8.Link, { color: "text.secondary", variant: "caption", component: "button", onClick: onClear }, (0, import_i18n9.__)("Clear & try again", "elementor")))
1154
+ /* @__PURE__ */ React11.createElement(import_ui11.Typography, { align: "center", variant: "subtitle2" }, (0, import_i18n11.__)("Sorry, nothing matched", "elementor"), /* @__PURE__ */ React11.createElement("br", null), "\u201C", searchValue, "\u201D."),
1155
+ /* @__PURE__ */ React11.createElement(import_ui11.Typography, { align: "center", variant: "caption", sx: { display: "flex", flexDirection: "column" } }, (0, import_i18n11.__)("Try something else.", "elementor"), /* @__PURE__ */ React11.createElement(import_ui11.Link, { color: "text.secondary", variant: "caption", component: "button", onClick: onClear }, (0, import_i18n11.__)("Clear & try again", "elementor")))
821
1156
  );
822
1157
  };
823
1158
 
824
1159
  // src/components/ui/no-variables.tsx
825
- var React8 = __toESM(require("react"));
826
- var import_ui9 = require("@elementor/ui");
827
- var import_i18n10 = require("@wordpress/i18n");
828
- var NoVariables = ({ icon, title, onAdd }) => /* @__PURE__ */ React8.createElement(
829
- import_ui9.Stack,
830
- {
831
- gap: 1,
832
- alignItems: "center",
833
- justifyContent: "center",
834
- height: "100%",
835
- color: "text.secondary",
836
- sx: { p: 2.5, pb: 5.5 }
837
- },
838
- icon,
839
- /* @__PURE__ */ React8.createElement(import_ui9.Typography, { align: "center", variant: "subtitle2" }, title),
840
- /* @__PURE__ */ React8.createElement(import_ui9.Typography, { align: "center", variant: "caption", maxWidth: "180px" }, (0, import_i18n10.__)("Variables are saved attributes that you can apply anywhere on your site.", "elementor")),
841
- onAdd && /* @__PURE__ */ React8.createElement(import_ui9.Button, { variant: "outlined", color: "secondary", size: "small", onClick: onAdd }, (0, import_i18n10.__)("Create a variable", "elementor"))
842
- );
1160
+ var React12 = __toESM(require("react"));
1161
+ var import_ui12 = require("@elementor/ui");
1162
+ var import_i18n12 = require("@wordpress/i18n");
1163
+ var NoVariables = ({ icon, title, onAdd }) => {
1164
+ const canAdd = usePermissions().canAdd();
1165
+ return /* @__PURE__ */ React12.createElement(
1166
+ import_ui12.Stack,
1167
+ {
1168
+ gap: 1,
1169
+ alignItems: "center",
1170
+ justifyContent: "center",
1171
+ height: "100%",
1172
+ color: "text.secondary",
1173
+ sx: { p: 2.5, pb: 5.5 }
1174
+ },
1175
+ icon,
1176
+ canAdd ? /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(
1177
+ NoVariablesContent,
1178
+ {
1179
+ title: title || (0, import_i18n12.__)("Create your first variable", "elementor"),
1180
+ message: (0, import_i18n12.__)(
1181
+ "Variables are saved attributes that you can apply anywhere on your site.",
1182
+ "elementor"
1183
+ )
1184
+ }
1185
+ ), onAdd && /* @__PURE__ */ React12.createElement(import_ui12.Button, { variant: "outlined", color: "secondary", size: "small", onClick: onAdd }, (0, import_i18n12.__)("Create a variable", "elementor"))) : /* @__PURE__ */ React12.createElement(
1186
+ NoVariablesContent,
1187
+ {
1188
+ title: (0, import_i18n12.__)("There are no variables", "elementor"),
1189
+ message: (0, import_i18n12.__)("With your current role, you can only connect and detach variables.", "elementor")
1190
+ }
1191
+ )
1192
+ );
1193
+ };
1194
+ function NoVariablesContent({ title, message }) {
1195
+ return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(import_ui12.Typography, { align: "center", variant: "subtitle2" }, title), /* @__PURE__ */ React12.createElement(import_ui12.Typography, { align: "center", variant: "caption", maxWidth: "180px" }, message));
1196
+ }
843
1197
 
844
1198
  // src/components/ui/styled-menu-list.tsx
845
- var import_ui10 = require("@elementor/ui");
846
- var VariablesStyledMenuList = (0, import_ui10.styled)(import_ui10.MenuList)(({ theme }) => ({
1199
+ var import_ui13 = require("@elementor/ui");
1200
+ var VariablesStyledMenuList = (0, import_ui13.styled)(import_ui13.MenuList)(({ theme }) => ({
847
1201
  "& > li": {
848
1202
  height: 32,
849
1203
  width: "100%",
@@ -873,38 +1227,53 @@ var VariablesStyledMenuList = (0, import_ui10.styled)(import_ui10.MenuList)(({ t
873
1227
  position: "relative"
874
1228
  }));
875
1229
 
876
- // src/components/color-variables-selection.tsx
1230
+ // src/components/variables-selection.tsx
877
1231
  var SIZE4 = "tiny";
878
- var ColorVariablesSelection = ({ closePopover, onAdd, onEdit, onSettings }) => {
879
- const { value: variable, setValue: setVariable } = (0, import_editor_controls3.useBoundProp)(colorVariablePropTypeUtil);
880
- const [searchValue, setSearchValue] = (0, import_react7.useState)("");
1232
+ var VariablesSelection = ({ closePopover, onAdd, onEdit, onSettings }) => {
1233
+ const { icon: VariableIcon, startIcon, variableType, propTypeUtil } = useVariableType();
1234
+ const { value: variable, setValue: setVariable, path } = (0, import_editor_controls4.useBoundProp)(propTypeUtil);
1235
+ const [searchValue, setSearchValue] = (0, import_react9.useState)("");
881
1236
  const {
882
1237
  list: variables,
883
1238
  hasMatches: hasSearchResults,
884
1239
  isSourceNotEmpty: hasVariables
885
- } = useFilteredVariables(searchValue, colorVariablePropTypeUtil.key);
886
- const handleSetColorVariable = (key) => {
1240
+ } = useFilteredVariables(searchValue, propTypeUtil.key);
1241
+ const handleSetVariable = (key) => {
887
1242
  setVariable(key);
1243
+ trackVariableEvent({
1244
+ varType: variableType,
1245
+ controlPath: path.join("."),
1246
+ action: "connect"
1247
+ });
888
1248
  closePopover();
889
1249
  };
1250
+ const onAddAndTrack = () => {
1251
+ onAdd?.();
1252
+ trackVariableEvent({
1253
+ varType: variableType,
1254
+ controlPath: path.join("."),
1255
+ action: "add"
1256
+ });
1257
+ };
890
1258
  const actions = [];
891
1259
  if (onAdd) {
892
1260
  actions.push(
893
- /* @__PURE__ */ React9.createElement(import_ui11.IconButton, { key: "add", size: SIZE4, onClick: onAdd }, /* @__PURE__ */ React9.createElement(import_icons5.PlusIcon, { fontSize: SIZE4 }))
1261
+ /* @__PURE__ */ React13.createElement(import_ui14.IconButton, { key: "add", size: SIZE4, onClick: onAddAndTrack }, /* @__PURE__ */ React13.createElement(import_icons7.PlusIcon, { fontSize: SIZE4 }))
894
1262
  );
895
1263
  }
896
1264
  if (onSettings) {
897
1265
  actions.push(
898
- /* @__PURE__ */ React9.createElement(import_ui11.IconButton, { key: "settings", size: SIZE4, onClick: onSettings }, /* @__PURE__ */ React9.createElement(import_icons5.SettingsIcon, { fontSize: SIZE4 }))
1266
+ /* @__PURE__ */ React13.createElement(import_ui14.IconButton, { key: "settings", size: SIZE4, onClick: onSettings }, /* @__PURE__ */ React13.createElement(import_icons7.SettingsIcon, { fontSize: SIZE4 }))
899
1267
  );
900
1268
  }
1269
+ const StartIcon = startIcon || (() => /* @__PURE__ */ React13.createElement(VariableIcon, { fontSize: SIZE4 }));
901
1270
  const items = variables.map(({ value, label, key }) => ({
902
1271
  type: "item",
903
1272
  value: key,
904
1273
  label,
905
- icon: /* @__PURE__ */ React9.createElement(ColorIndicator, { size: "inherit", component: "span", value }),
1274
+ icon: /* @__PURE__ */ React13.createElement(StartIcon, { value }),
906
1275
  secondaryText: value,
907
- onEdit: () => onEdit?.(key)
1276
+ onEdit: onEdit ? () => onEdit?.(key) : void 0
908
1277
  }));
909
1278
  const handleSearch = (search) => {
910
1279
  setSearchValue(search);
@@ -912,602 +1281,473 @@ var ColorVariablesSelection = ({ closePopover, onAdd, onEdit, onSettings }) => {
912
1281
  const handleClearSearch = () => {
913
1282
  setSearchValue("");
914
1283
  };
915
- return /* @__PURE__ */ React9.createElement(import_editor_editing_panel3.PopoverBody, null, /* @__PURE__ */ React9.createElement(
916
- import_editor_ui4.PopoverHeader,
1284
+ const noVariableTitle = (0, import_i18n13.sprintf)(
1285
+ /* translators: %s: Variable Type. */
1286
+ (0, import_i18n13.__)("Create your first %s variable", "elementor"),
1287
+ variableType
1288
+ );
1289
+ return /* @__PURE__ */ React13.createElement(import_editor_editing_panel4.PopoverBody, null, /* @__PURE__ */ React13.createElement(
1290
+ import_editor_ui5.PopoverHeader,
917
1291
  {
918
- title: (0, import_i18n11.__)("Variables", "elementor"),
919
- icon: /* @__PURE__ */ React9.createElement(import_icons5.ColorFilterIcon, { fontSize: SIZE4 }),
1292
+ title: (0, import_i18n13.__)("Variables", "elementor"),
1293
+ icon: /* @__PURE__ */ React13.createElement(import_icons7.ColorFilterIcon, { fontSize: SIZE4 }),
920
1294
  onClose: closePopover,
921
1295
  actions
922
1296
  }
923
- ), hasVariables && /* @__PURE__ */ React9.createElement(
924
- import_editor_ui4.PopoverSearch,
1297
+ ), hasVariables && /* @__PURE__ */ React13.createElement(
1298
+ import_editor_ui5.PopoverSearch,
925
1299
  {
926
1300
  value: searchValue,
927
1301
  onSearch: handleSearch,
928
- placeholder: (0, import_i18n11.__)("Search", "elementor")
1302
+ placeholder: (0, import_i18n13.__)("Search", "elementor")
929
1303
  }
930
- ), /* @__PURE__ */ React9.createElement(import_ui11.Divider, null), hasVariables && hasSearchResults && /* @__PURE__ */ React9.createElement(
931
- import_editor_ui4.PopoverMenuList,
1304
+ ), /* @__PURE__ */ React13.createElement(import_ui14.Divider, null), hasVariables && hasSearchResults && /* @__PURE__ */ React13.createElement(
1305
+ import_editor_ui5.PopoverMenuList,
932
1306
  {
933
1307
  items,
934
- onSelect: handleSetColorVariable,
1308
+ onSelect: handleSetVariable,
935
1309
  onClose: () => {
936
1310
  },
937
1311
  selectedValue: variable,
938
- "data-testid": "color-variables-list",
1312
+ "data-testid": `${variableType}-variables-list`,
939
1313
  menuListTemplate: VariablesStyledMenuList,
940
- menuItemContentTemplate: (item) => /* @__PURE__ */ React9.createElement(MenuItemContent, { item })
1314
+ menuItemContentTemplate: (item) => /* @__PURE__ */ React13.createElement(MenuItemContent, { item })
941
1315
  }
942
- ), !hasSearchResults && hasVariables && /* @__PURE__ */ React9.createElement(
1316
+ ), !hasSearchResults && hasVariables && /* @__PURE__ */ React13.createElement(
943
1317
  NoSearchResults,
944
1318
  {
945
1319
  searchValue,
946
1320
  onClear: handleClearSearch,
947
- icon: /* @__PURE__ */ React9.createElement(import_icons5.BrushIcon, { fontSize: "large" })
1321
+ icon: /* @__PURE__ */ React13.createElement(VariableIcon, { fontSize: "large" })
1322
+ }
1323
+ ), !hasVariables && /* @__PURE__ */ React13.createElement(NoVariables, { title: noVariableTitle, icon: /* @__PURE__ */ React13.createElement(VariableIcon, { fontSize: "large" }), onAdd }));
1324
+ };
1325
+
1326
+ // src/components/variable-selection-popover.tsx
1327
+ var VIEW_LIST = "list";
1328
+ var VIEW_ADD = "add";
1329
+ var VIEW_EDIT = "edit";
1330
+ var VariableSelectionPopover = ({ closePopover, propTypeKey, selectedVariable }) => {
1331
+ const [currentView, setCurrentView] = (0, import_react10.useState)(VIEW_LIST);
1332
+ const [editId, setEditId] = (0, import_react10.useState)("");
1333
+ const { open } = usePanelActions();
1334
+ const onSettingsAvailable = (0, import_editor_v1_adapters2.isExperimentActive)("e_variables_settings") ? () => {
1335
+ open();
1336
+ } : void 0;
1337
+ return /* @__PURE__ */ React14.createElement(VariableTypeProvider, { propTypeKey }, /* @__PURE__ */ React14.createElement(PopoverContentRefContextProvider, null, RenderView({
1338
+ propTypeKey,
1339
+ currentView,
1340
+ selectedVariable,
1341
+ editId,
1342
+ setEditId,
1343
+ setCurrentView,
1344
+ closePopover,
1345
+ onSettings: onSettingsAvailable
1346
+ })));
1347
+ };
1348
+ function RenderView(props) {
1349
+ const userPermissions = usePermissions();
1350
+ const handlers = {
1351
+ onClose: () => {
1352
+ props.closePopover();
1353
+ },
1354
+ onGoBack: () => {
1355
+ props.setCurrentView(VIEW_LIST);
1356
+ }
1357
+ };
1358
+ if (userPermissions.canAdd()) {
1359
+ handlers.onAdd = () => {
1360
+ props.setCurrentView(VIEW_ADD);
1361
+ };
1362
+ }
1363
+ if (userPermissions.canEdit()) {
1364
+ handlers.onEdit = (key) => {
1365
+ props.setEditId(key);
1366
+ props.setCurrentView(VIEW_EDIT);
1367
+ };
1368
+ }
1369
+ if (userPermissions.canManageSettings() && props.onSettings) {
1370
+ handlers.onSettings = () => {
1371
+ props.onSettings?.();
1372
+ props.closePopover();
1373
+ };
1374
+ }
1375
+ const handleSubmitOnEdit = () => {
1376
+ if (props?.selectedVariable?.key === props.editId) {
1377
+ handlers.onClose();
1378
+ } else {
1379
+ handlers.onGoBack?.();
948
1380
  }
949
- ), !hasVariables && /* @__PURE__ */ React9.createElement(
950
- NoVariables,
1381
+ };
1382
+ if (VIEW_LIST === props.currentView) {
1383
+ return /* @__PURE__ */ React14.createElement(
1384
+ VariablesSelection,
1385
+ {
1386
+ closePopover: handlers.onClose,
1387
+ onAdd: handlers.onAdd,
1388
+ onEdit: handlers.onEdit,
1389
+ onSettings: handlers.onSettings
1390
+ }
1391
+ );
1392
+ }
1393
+ if (VIEW_ADD === props.currentView) {
1394
+ return /* @__PURE__ */ React14.createElement(VariableCreation, { onGoBack: handlers.onGoBack, onClose: handlers.onClose });
1395
+ }
1396
+ if (VIEW_EDIT === props.currentView) {
1397
+ return /* @__PURE__ */ React14.createElement(
1398
+ VariableEdit,
1399
+ {
1400
+ editId: props.editId,
1401
+ onGoBack: handlers.onGoBack,
1402
+ onClose: handlers.onClose,
1403
+ onSubmit: handleSubmitOnEdit
1404
+ }
1405
+ );
1406
+ }
1407
+ return null;
1408
+ }
1409
+
1410
+ // src/components/ui/tags/assigned-tag.tsx
1411
+ var React15 = __toESM(require("react"));
1412
+ var import_icons8 = require("@elementor/icons");
1413
+ var import_ui15 = require("@elementor/ui");
1414
+ var import_i18n14 = require("@wordpress/i18n");
1415
+ var SIZE5 = "tiny";
1416
+ var AssignedTag = ({ startIcon, label, onUnlink, ...props }) => {
1417
+ const actions = [];
1418
+ if (onUnlink) {
1419
+ actions.push(
1420
+ /* @__PURE__ */ React15.createElement(import_ui15.IconButton, { key: "unlink", size: SIZE5, onClick: onUnlink, "aria-label": (0, import_i18n14.__)("Unlink", "elementor") }, /* @__PURE__ */ React15.createElement(import_icons8.DetachIcon, { fontSize: SIZE5 }))
1421
+ );
1422
+ }
1423
+ return /* @__PURE__ */ React15.createElement(import_ui15.Tooltip, { title: label, placement: "top" }, /* @__PURE__ */ React15.createElement(
1424
+ import_ui15.UnstableTag,
951
1425
  {
952
- title: (0, import_i18n11.__)("Create your first color variable", "elementor"),
953
- icon: /* @__PURE__ */ React9.createElement(import_icons5.BrushIcon, { fontSize: "large" }),
954
- onAdd
1426
+ fullWidth: true,
1427
+ showActionsOnHover: true,
1428
+ startIcon: /* @__PURE__ */ React15.createElement(import_ui15.Stack, { gap: 0.5, direction: "row", alignItems: "center" }, startIcon),
1429
+ label: /* @__PURE__ */ React15.createElement(import_ui15.Box, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React15.createElement(import_ui15.Typography, { sx: { lineHeight: 1.34 }, variant: "caption", noWrap: true }, label)),
1430
+ actions,
1431
+ ...props
955
1432
  }
956
1433
  ));
957
1434
  };
958
1435
 
959
- // src/components/font-variable-creation.tsx
960
- var React11 = __toESM(require("react"));
961
- var import_react9 = require("react");
962
- var import_editor_controls5 = require("@elementor/editor-controls");
963
- var import_editor_editing_panel5 = require("@elementor/editor-editing-panel");
964
- var import_editor_ui5 = require("@elementor/editor-ui");
965
- var import_icons7 = require("@elementor/icons");
966
- var import_ui13 = require("@elementor/ui");
967
- var import_i18n13 = require("@wordpress/i18n");
968
-
969
- // src/components/fields/font-field.tsx
970
- var React10 = __toESM(require("react"));
971
- var import_react8 = require("react");
972
- var import_editor_controls4 = require("@elementor/editor-controls");
973
- var import_editor_editing_panel4 = require("@elementor/editor-editing-panel");
974
- var import_icons6 = require("@elementor/icons");
975
- var import_ui12 = require("@elementor/ui");
976
- var import_i18n12 = require("@wordpress/i18n");
977
- var FontField = ({ value, onChange }) => {
978
- const [fontFamily, setFontFamily] = (0, import_react8.useState)(value);
979
- const [errorMessage, setErrorMessage] = (0, import_react8.useState)("");
980
- const defaultRef = (0, import_react8.useRef)(null);
981
- const anchorRef = usePopoverContentRef() ?? defaultRef;
982
- const fontPopoverState = (0, import_ui12.usePopupState)({ variant: "popover" });
983
- const fontFamilies = (0, import_editor_editing_panel4.useFontFamilies)();
984
- const sectionWidth = (0, import_editor_editing_panel4.useSectionWidth)();
985
- const handleChange = (newValue) => {
986
- setFontFamily(newValue);
987
- const errorMsg = validateValue(newValue);
988
- setErrorMessage(errorMsg);
989
- onChange(errorMsg ? "" : newValue);
990
- };
991
- const handleFontFamilyChange = (newFontFamily) => {
992
- handleChange(newFontFamily);
993
- fontPopoverState.close();
1436
+ // src/components/ui/variable/assigned-variable.tsx
1437
+ var AssignedVariable = ({ variable, propTypeKey }) => {
1438
+ const { fallbackPropTypeUtil, startIcon, propTypeUtil } = getVariableType(propTypeKey);
1439
+ const { setValue } = (0, import_editor_controls5.useBoundProp)();
1440
+ const anchorRef = (0, import_react11.useRef)(null);
1441
+ const popupId = (0, import_react11.useId)();
1442
+ const popupState = (0, import_ui16.usePopupState)({
1443
+ variant: "popover",
1444
+ popupId: `elementor-variables-list-${popupId}`
1445
+ });
1446
+ const unlinkVariable = () => {
1447
+ const fallbackValue = fallbackPropTypeUtil.create(variable.value);
1448
+ setValue(fallbackValue);
994
1449
  };
995
- return /* @__PURE__ */ React10.createElement(import_ui12.Grid, { container: true, gap: 0.75, alignItems: "center" }, /* @__PURE__ */ React10.createElement(import_ui12.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React10.createElement(import_ui12.FormLabel, { size: "tiny" }, (0, import_i18n12.__)("Value", "elementor"))), /* @__PURE__ */ React10.createElement(import_ui12.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React10.createElement(
996
- import_ui12.UnstableTag,
1450
+ const StartIcon = startIcon || (() => null);
1451
+ return /* @__PURE__ */ React16.createElement(import_ui16.Box, { ref: anchorRef }, /* @__PURE__ */ React16.createElement(
1452
+ AssignedTag,
997
1453
  {
998
- variant: "outlined",
999
- label: fontFamily,
1000
- endIcon: /* @__PURE__ */ React10.createElement(import_icons6.ChevronDownIcon, { fontSize: "tiny" }),
1001
- ...(0, import_ui12.bindTrigger)(fontPopoverState),
1002
- fullWidth: true
1454
+ label: variable.label,
1455
+ startIcon: /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(import_icons9.ColorFilterIcon, { fontSize: SIZE5 }), /* @__PURE__ */ React16.createElement(StartIcon, { value: variable.value })),
1456
+ onUnlink: unlinkVariable,
1457
+ ...(0, import_ui16.bindTrigger)(popupState)
1003
1458
  }
1004
- ), /* @__PURE__ */ React10.createElement(
1005
- import_ui12.Popover,
1459
+ ), /* @__PURE__ */ React16.createElement(
1460
+ import_ui16.Popover,
1006
1461
  {
1007
- disablePortal: true,
1008
1462
  disableScrollLock: true,
1009
1463
  anchorEl: anchorRef.current,
1010
- anchorOrigin: { vertical: "top", horizontal: "right" },
1011
- transformOrigin: { vertical: "top", horizontal: -20 },
1012
- ...(0, import_ui12.bindPopover)(fontPopoverState)
1464
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
1465
+ transformOrigin: { vertical: "top", horizontal: "right" },
1466
+ PaperProps: {
1467
+ sx: { my: 1 }
1468
+ },
1469
+ ...(0, import_ui16.bindPopover)(popupState)
1013
1470
  },
1014
- /* @__PURE__ */ React10.createElement(
1015
- import_editor_controls4.FontFamilySelector,
1471
+ /* @__PURE__ */ React16.createElement(
1472
+ VariableSelectionPopover,
1016
1473
  {
1017
- fontFamilies,
1018
- fontFamily,
1019
- onFontFamilyChange: handleFontFamilyChange,
1020
- onClose: fontPopoverState.close,
1021
- sectionWidth
1474
+ selectedVariable: variable,
1475
+ closePopover: popupState.close,
1476
+ propTypeKey: propTypeUtil.key
1022
1477
  }
1023
1478
  )
1024
- ), errorMessage && /* @__PURE__ */ React10.createElement(import_ui12.FormHelperText, { error: true }, errorMessage)));
1479
+ ));
1025
1480
  };
1026
1481
 
1027
- // src/components/font-variable-creation.tsx
1028
- var SIZE5 = "tiny";
1029
- var FontVariableCreation = ({ onClose, onGoBack }) => {
1030
- const { setValue: setVariable } = (0, import_editor_controls5.useBoundProp)(fontVariablePropTypeUtil);
1031
- const [fontFamily, setFontFamily] = (0, import_react9.useState)("");
1032
- const [label, setLabel] = (0, import_react9.useState)("");
1033
- const [errorMessage, setErrorMessage] = (0, import_react9.useState)("");
1034
- const resetFields = () => {
1035
- setFontFamily("");
1036
- setLabel("");
1037
- setErrorMessage("");
1482
+ // src/components/ui/variable/deleted-variable.tsx
1483
+ var React20 = __toESM(require("react"));
1484
+ var import_react13 = require("react");
1485
+ var import_editor_controls7 = require("@elementor/editor-controls");
1486
+ var import_ui20 = require("@elementor/ui");
1487
+
1488
+ // src/components/variable-restore.tsx
1489
+ var React17 = __toESM(require("react"));
1490
+ var import_react12 = require("react");
1491
+ var import_editor_controls6 = require("@elementor/editor-controls");
1492
+ var import_editor_editing_panel5 = require("@elementor/editor-editing-panel");
1493
+ var import_editor_ui6 = require("@elementor/editor-ui");
1494
+ var import_ui17 = require("@elementor/ui");
1495
+ var import_i18n15 = require("@wordpress/i18n");
1496
+ var SIZE6 = "tiny";
1497
+ var VariableRestore = ({ variableId, onClose, onSubmit }) => {
1498
+ const { icon: VariableIcon, valueField: ValueField, variableType, propTypeUtil } = useVariableType();
1499
+ const { setValue: notifyBoundPropChange } = (0, import_editor_controls6.useBoundProp)(propTypeUtil);
1500
+ const variable = useVariable(variableId);
1501
+ if (!variable) {
1502
+ throw new Error(`Global ${variableType} variable not found`);
1503
+ }
1504
+ const [errorMessage, setErrorMessage] = (0, import_react12.useState)("");
1505
+ const [label, setLabel] = (0, import_react12.useState)(variable.label);
1506
+ const [value, setValue] = (0, import_react12.useState)(variable.value);
1507
+ const { labelFieldError, setLabelFieldError } = useLabelError({
1508
+ value: variable.label,
1509
+ message: ERROR_MESSAGES.DUPLICATED_LABEL
1510
+ });
1511
+ const handleRestore = () => {
1512
+ restoreVariable(variableId, label, value).then(() => {
1513
+ notifyBoundPropChange(variableId);
1514
+ onSubmit?.();
1515
+ }).catch((error) => {
1516
+ const mappedError = mapServerError(error);
1517
+ if (mappedError && "label" === mappedError.field) {
1518
+ setLabel("");
1519
+ setLabelFieldError({
1520
+ value: label,
1521
+ message: mappedError.message
1522
+ });
1523
+ return;
1524
+ }
1525
+ setErrorMessage(ERROR_MESSAGES.UNEXPECTED_ERROR);
1526
+ });
1038
1527
  };
1039
- const closePopover = () => {
1040
- resetFields();
1041
- onClose();
1528
+ const hasEmptyValues = () => {
1529
+ return !value.trim() || !label.trim();
1042
1530
  };
1043
- const handleCreate = () => {
1044
- createVariable({
1045
- value: fontFamily,
1046
- label,
1047
- type: fontVariablePropTypeUtil.key
1048
- }).then((key) => {
1049
- setVariable(key);
1050
- closePopover();
1051
- }).catch((error) => {
1052
- setErrorMessage(error.message);
1053
- });
1531
+ const noValueChanged = () => {
1532
+ return value === variable.value && label === variable.label;
1054
1533
  };
1055
- const hasEmptyValue = () => {
1056
- return "" === fontFamily.trim() || "" === label.trim();
1534
+ const hasErrors = () => {
1535
+ return !!errorMessage;
1057
1536
  };
1058
- const isSubmitDisabled = hasEmptyValue();
1059
- return /* @__PURE__ */ React11.createElement(import_editor_editing_panel5.PopoverBody, { height: "auto" }, /* @__PURE__ */ React11.createElement(
1060
- import_editor_ui5.PopoverHeader,
1537
+ const isSubmitDisabled = noValueChanged() || hasEmptyValues() || hasErrors();
1538
+ return /* @__PURE__ */ React17.createElement(PopoverContentRefContextProvider, null, /* @__PURE__ */ React17.createElement(import_editor_editing_panel5.PopoverBody, { height: "auto" }, /* @__PURE__ */ React17.createElement(
1539
+ import_editor_ui6.PopoverHeader,
1061
1540
  {
1062
- icon: /* @__PURE__ */ React11.createElement(React11.Fragment, null, onGoBack && /* @__PURE__ */ React11.createElement(import_ui13.IconButton, { size: SIZE5, "aria-label": (0, import_i18n13.__)("Go Back", "elementor"), onClick: onGoBack }, /* @__PURE__ */ React11.createElement(import_icons7.ArrowLeftIcon, { fontSize: SIZE5 })), /* @__PURE__ */ React11.createElement(import_icons7.TextIcon, { fontSize: SIZE5 })),
1063
- title: (0, import_i18n13.__)("Create variable", "elementor"),
1064
- onClose: closePopover
1541
+ icon: /* @__PURE__ */ React17.createElement(VariableIcon, { fontSize: SIZE6 }),
1542
+ title: (0, import_i18n15.__)("Restore variable", "elementor"),
1543
+ onClose
1065
1544
  }
1066
- ), /* @__PURE__ */ React11.createElement(import_ui13.Divider, null), /* @__PURE__ */ React11.createElement(import_editor_controls5.PopoverContent, { p: 2 }, /* @__PURE__ */ React11.createElement(
1545
+ ), /* @__PURE__ */ React17.createElement(import_ui17.Divider, null), /* @__PURE__ */ React17.createElement(import_editor_controls6.PopoverContent, { p: 2 }, /* @__PURE__ */ React17.createElement(
1067
1546
  LabelField,
1068
1547
  {
1069
1548
  value: label,
1070
- onChange: (value) => {
1071
- setLabel(value);
1549
+ error: labelFieldError,
1550
+ onChange: (newValue) => {
1551
+ setLabel(newValue);
1072
1552
  setErrorMessage("");
1073
1553
  }
1074
1554
  }
1075
- ), /* @__PURE__ */ React11.createElement(
1076
- FontField,
1555
+ ), /* @__PURE__ */ React17.createElement(
1556
+ ValueField,
1077
1557
  {
1078
- value: fontFamily,
1079
- onChange: (value) => {
1080
- setFontFamily(value);
1558
+ value,
1559
+ onChange: (newValue) => {
1560
+ setValue(newValue);
1081
1561
  setErrorMessage("");
1082
1562
  }
1083
1563
  }
1084
- ), errorMessage && /* @__PURE__ */ React11.createElement(import_ui13.FormHelperText, { error: true }, errorMessage)), /* @__PURE__ */ React11.createElement(import_ui13.CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React11.createElement(import_ui13.Button, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleCreate }, (0, import_i18n13.__)("Create", "elementor"))));
1564
+ ), errorMessage && /* @__PURE__ */ React17.createElement(import_ui17.FormHelperText, { error: true }, errorMessage)), /* @__PURE__ */ React17.createElement(import_ui17.CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React17.createElement(import_ui17.Button, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleRestore }, (0, import_i18n15.__)("Restore", "elementor")))));
1085
1565
  };
1086
1566
 
1087
- // src/components/font-variable-edit.tsx
1088
- var React12 = __toESM(require("react"));
1089
- var import_react10 = require("react");
1090
- var import_editor_controls6 = require("@elementor/editor-controls");
1567
+ // src/components/ui/deleted-variable-alert.tsx
1568
+ var React18 = __toESM(require("react"));
1091
1569
  var import_editor_editing_panel6 = require("@elementor/editor-editing-panel");
1092
- var import_editor_ui6 = require("@elementor/editor-ui");
1093
- var import_icons8 = require("@elementor/icons");
1094
- var import_ui14 = require("@elementor/ui");
1095
- var import_i18n14 = require("@wordpress/i18n");
1096
- var SIZE6 = "tiny";
1097
- var FontVariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1098
- const { setValue: notifyBoundPropChange, value: assignedValue } = (0, import_editor_controls6.useBoundProp)(fontVariablePropTypeUtil);
1099
- const [deleteConfirmation, setDeleteConfirmation] = (0, import_react10.useState)(false);
1100
- const [errorMessage, setErrorMessage] = (0, import_react10.useState)("");
1101
- const variable = useVariable(editId);
1102
- if (!variable) {
1103
- throw new Error(`Global font variable "${editId}" not found`);
1104
- }
1105
- const [fontFamily, setFontFamily] = (0, import_react10.useState)(variable.value);
1106
- const [label, setLabel] = (0, import_react10.useState)(variable.label);
1107
- const handleUpdate = () => {
1108
- updateVariable(editId, {
1109
- value: fontFamily,
1110
- label
1111
- }).then(() => {
1112
- maybeTriggerBoundPropChange();
1113
- onSubmit?.();
1114
- }).catch((error) => {
1115
- setErrorMessage(error.message);
1116
- });
1117
- };
1118
- const handleDelete = () => {
1119
- deleteVariable(editId).then(() => {
1120
- maybeTriggerBoundPropChange();
1121
- onSubmit?.();
1122
- });
1123
- };
1124
- const maybeTriggerBoundPropChange = () => {
1125
- if (editId === assignedValue) {
1126
- notifyBoundPropChange(editId);
1127
- }
1128
- };
1129
- const handleDeleteConfirmation = () => {
1130
- setDeleteConfirmation(true);
1131
- };
1132
- const closeDeleteDialog = () => () => {
1133
- setDeleteConfirmation(false);
1134
- };
1135
- const hasEmptyValue = () => {
1136
- return !fontFamily.trim() || !label.trim();
1137
- };
1138
- const noValueChanged = () => {
1139
- return fontFamily === variable.value && label === variable.label;
1140
- };
1141
- const isSubmitDisabled = noValueChanged() || hasEmptyValue();
1142
- const actions = [];
1143
- actions.push(
1144
- /* @__PURE__ */ React12.createElement(
1145
- import_ui14.IconButton,
1146
- {
1147
- key: "delete",
1148
- size: SIZE6,
1149
- "aria-label": (0, import_i18n14.__)("Delete", "elementor"),
1150
- onClick: handleDeleteConfirmation
1151
- },
1152
- /* @__PURE__ */ React12.createElement(import_icons8.TrashIcon, { fontSize: SIZE6 })
1153
- )
1154
- );
1155
- return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(import_editor_editing_panel6.PopoverBody, { height: "auto" }, /* @__PURE__ */ React12.createElement(
1156
- import_editor_ui6.PopoverHeader,
1570
+ var import_ui18 = require("@elementor/ui");
1571
+ var import_i18n16 = require("@wordpress/i18n");
1572
+ var DeletedVariableAlert = ({ onClose, onUnlink, onRestore, label }) => {
1573
+ const sectionWidth = (0, import_editor_editing_panel6.useSectionWidth)();
1574
+ return /* @__PURE__ */ React18.createElement(import_ui18.ClickAwayListener, { onClickAway: onClose }, /* @__PURE__ */ React18.createElement(
1575
+ import_ui18.Alert,
1157
1576
  {
1158
- icon: /* @__PURE__ */ React12.createElement(React12.Fragment, null, onGoBack && /* @__PURE__ */ React12.createElement(
1159
- import_ui14.IconButton,
1160
- {
1161
- size: SIZE6,
1162
- "aria-label": (0, import_i18n14.__)("Go Back", "elementor"),
1163
- onClick: onGoBack
1164
- },
1165
- /* @__PURE__ */ React12.createElement(import_icons8.ArrowLeftIcon, { fontSize: SIZE6 })
1166
- ), /* @__PURE__ */ React12.createElement(import_icons8.TextIcon, { fontSize: SIZE6 })),
1167
- title: (0, import_i18n14.__)("Edit variable", "elementor"),
1577
+ variant: "standard",
1578
+ severity: "warning",
1168
1579
  onClose,
1169
- actions
1170
- }
1171
- ), /* @__PURE__ */ React12.createElement(import_ui14.Divider, null), /* @__PURE__ */ React12.createElement(import_editor_controls6.PopoverContent, { p: 2 }, /* @__PURE__ */ React12.createElement(
1172
- LabelField,
1173
- {
1174
- value: label,
1175
- onChange: (value) => {
1176
- setLabel(value);
1177
- setErrorMessage("");
1178
- }
1179
- }
1180
- ), /* @__PURE__ */ React12.createElement(
1181
- FontField,
1182
- {
1183
- value: fontFamily,
1184
- onChange: (value) => {
1185
- setFontFamily(value);
1186
- setErrorMessage("");
1187
- }
1188
- }
1189
- ), errorMessage && /* @__PURE__ */ React12.createElement(import_ui14.FormHelperText, { error: true }, errorMessage)), /* @__PURE__ */ React12.createElement(import_ui14.CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React12.createElement(import_ui14.Button, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleUpdate }, (0, import_i18n14.__)("Save", "elementor")))), deleteConfirmation && /* @__PURE__ */ React12.createElement(
1190
- DeleteConfirmationDialog,
1191
- {
1192
- open: true,
1193
- label,
1194
- onConfirm: handleDelete,
1195
- closeDialog: closeDeleteDialog()
1196
- }
1197
- ));
1198
- };
1199
-
1200
- // src/components/font-variables-selection.tsx
1201
- var React13 = __toESM(require("react"));
1202
- var import_react11 = require("react");
1203
- var import_editor_controls7 = require("@elementor/editor-controls");
1204
- var import_editor_editing_panel7 = require("@elementor/editor-editing-panel");
1205
- var import_editor_ui7 = require("@elementor/editor-ui");
1206
- var import_icons9 = require("@elementor/icons");
1207
- var import_ui15 = require("@elementor/ui");
1208
- var import_i18n15 = require("@wordpress/i18n");
1209
- var SIZE7 = "tiny";
1210
- var FontVariablesSelection = ({ closePopover, onAdd, onEdit, onSettings }) => {
1211
- const { value: variable, setValue: setVariable } = (0, import_editor_controls7.useBoundProp)(fontVariablePropTypeUtil);
1212
- const [searchValue, setSearchValue] = (0, import_react11.useState)("");
1213
- const {
1214
- list: variables,
1215
- hasMatches: hasSearchResults,
1216
- isSourceNotEmpty: hasVariables
1217
- } = useFilteredVariables(searchValue, fontVariablePropTypeUtil.key);
1218
- const handleSetVariable = (key) => {
1219
- setVariable(key);
1220
- closePopover();
1221
- };
1222
- const actions = [];
1223
- if (onAdd) {
1224
- actions.push(
1225
- /* @__PURE__ */ React13.createElement(import_ui15.IconButton, { key: "add", size: SIZE7, onClick: onAdd }, /* @__PURE__ */ React13.createElement(import_icons9.PlusIcon, { fontSize: SIZE7 }))
1226
- );
1227
- }
1228
- if (onSettings) {
1229
- actions.push(
1230
- /* @__PURE__ */ React13.createElement(import_ui15.IconButton, { key: "settings", size: SIZE7, onClick: onSettings }, /* @__PURE__ */ React13.createElement(import_icons9.SettingsIcon, { fontSize: SIZE7 }))
1231
- );
1232
- }
1233
- const items = variables.map(({ value, label, key }) => ({
1234
- type: "item",
1235
- value: key,
1580
+ action: /* @__PURE__ */ React18.createElement(React18.Fragment, null, onUnlink && /* @__PURE__ */ React18.createElement(import_ui18.AlertAction, { variant: "contained", onClick: onUnlink }, (0, import_i18n16.__)("Unlink", "elementor")), onRestore && /* @__PURE__ */ React18.createElement(import_ui18.AlertAction, { variant: "outlined", onClick: onRestore }, (0, import_i18n16.__)("Restore", "elementor"))),
1581
+ sx: { width: sectionWidth }
1582
+ },
1583
+ /* @__PURE__ */ React18.createElement(import_ui18.AlertTitle, null, (0, import_i18n16.__)("Deleted variable", "elementor")),
1584
+ (0, import_i18n16.__)("The variable", "elementor"),
1585
+ " '",
1236
1586
  label,
1237
- icon: /* @__PURE__ */ React13.createElement(import_icons9.TextIcon, { fontSize: SIZE7 }),
1238
- secondaryText: value,
1239
- onEdit: () => onEdit?.(key)
1240
- }));
1241
- const handleSearch = (search) => {
1242
- setSearchValue(search);
1243
- };
1244
- const handleClearSearch = () => {
1245
- setSearchValue("");
1246
- };
1247
- return /* @__PURE__ */ React13.createElement(import_editor_editing_panel7.PopoverBody, null, /* @__PURE__ */ React13.createElement(
1248
- import_editor_ui7.PopoverHeader,
1249
- {
1250
- title: (0, import_i18n15.__)("Variables", "elementor"),
1251
- onClose: closePopover,
1252
- icon: /* @__PURE__ */ React13.createElement(import_icons9.ColorFilterIcon, { fontSize: SIZE7 }),
1253
- actions
1254
- }
1255
- ), hasVariables && /* @__PURE__ */ React13.createElement(
1256
- import_editor_ui7.PopoverSearch,
1257
- {
1258
- value: searchValue,
1259
- onSearch: handleSearch,
1260
- placeholder: (0, import_i18n15.__)("Search", "elementor")
1261
- }
1262
- ), /* @__PURE__ */ React13.createElement(import_ui15.Divider, null), hasVariables && hasSearchResults && /* @__PURE__ */ React13.createElement(
1263
- import_editor_ui7.PopoverMenuList,
1264
- {
1265
- items,
1266
- onSelect: handleSetVariable,
1267
- onClose: () => {
1268
- },
1269
- selectedValue: variable,
1270
- "data-testid": "font-variables-list",
1271
- menuListTemplate: VariablesStyledMenuList,
1272
- menuItemContentTemplate: (item) => /* @__PURE__ */ React13.createElement(MenuItemContent, { item })
1273
- }
1274
- ), !hasSearchResults && hasVariables && /* @__PURE__ */ React13.createElement(
1275
- NoSearchResults,
1276
- {
1277
- searchValue,
1278
- onClear: handleClearSearch,
1279
- icon: /* @__PURE__ */ React13.createElement(import_icons9.TextIcon, { fontSize: "large" })
1280
- }
1281
- ), !hasVariables && /* @__PURE__ */ React13.createElement(
1282
- NoVariables,
1283
- {
1284
- title: (0, import_i18n15.__)("Create your first font variable", "elementor"),
1285
- icon: /* @__PURE__ */ React13.createElement(import_icons9.TextIcon, { fontSize: "large" }),
1286
- onAdd
1287
- }
1587
+ "'",
1588
+ " ",
1589
+ (0, import_i18n16.__)(
1590
+ "has been deleted, but it is still referenced in this location. You may restore the variable or unlink it to assign a different value.",
1591
+ "elementor"
1592
+ )
1288
1593
  ));
1289
1594
  };
1290
1595
 
1291
- // src/components/variable-selection-popover.tsx
1292
- var VIEW_LIST = "list";
1293
- var VIEW_ADD = "add";
1294
- var VIEW_EDIT = "edit";
1295
- var VariableSelectionPopover = ({ closePopover, propTypeKey, selectedVariable }) => {
1296
- const [currentView, setCurrentView] = (0, import_react12.useState)(VIEW_LIST);
1297
- const editIdRef = (0, import_react12.useRef)("");
1298
- const anchorRef = (0, import_react12.useRef)(null);
1299
- return /* @__PURE__ */ React14.createElement(PopoverContentRefContext.Provider, { value: anchorRef }, /* @__PURE__ */ React14.createElement(import_ui16.Box, { ref: anchorRef }, renderStage({
1300
- propTypeKey,
1301
- currentView,
1302
- selectedVariable,
1303
- editIdRef,
1304
- setCurrentView,
1305
- closePopover
1306
- })));
1307
- };
1308
- function renderStage(props) {
1309
- const handleSubmitOnEdit = () => {
1310
- if (props?.selectedVariable?.key === props.editIdRef.current) {
1311
- props.closePopover();
1312
- } else {
1313
- props.setCurrentView(VIEW_LIST);
1314
- }
1315
- };
1316
- if (fontVariablePropTypeUtil.key === props.propTypeKey) {
1317
- if (VIEW_LIST === props.currentView) {
1318
- return /* @__PURE__ */ React14.createElement(
1319
- FontVariablesSelection,
1320
- {
1321
- closePopover: props.closePopover,
1322
- onAdd: () => {
1323
- props.setCurrentView(VIEW_ADD);
1324
- },
1325
- onEdit: (key) => {
1326
- props.editIdRef.current = key;
1327
- props.setCurrentView(VIEW_EDIT);
1328
- }
1329
- }
1330
- );
1331
- }
1332
- if (VIEW_ADD === props.currentView) {
1333
- return /* @__PURE__ */ React14.createElement(
1334
- FontVariableCreation,
1335
- {
1336
- onGoBack: () => props.setCurrentView(VIEW_LIST),
1337
- onClose: props.closePopover
1338
- }
1339
- );
1340
- }
1341
- if (VIEW_EDIT === props.currentView) {
1342
- return /* @__PURE__ */ React14.createElement(
1343
- FontVariableEdit,
1344
- {
1345
- editId: props.editIdRef.current ?? "",
1346
- onGoBack: () => props.setCurrentView(VIEW_LIST),
1347
- onClose: props.closePopover,
1348
- onSubmit: handleSubmitOnEdit
1349
- }
1350
- );
1351
- }
1352
- }
1353
- if (colorVariablePropTypeUtil.key === props.propTypeKey) {
1354
- if (VIEW_LIST === props.currentView) {
1355
- return /* @__PURE__ */ React14.createElement(
1356
- ColorVariablesSelection,
1357
- {
1358
- closePopover: props.closePopover,
1359
- onAdd: () => {
1360
- props.setCurrentView(VIEW_ADD);
1361
- },
1362
- onEdit: (key) => {
1363
- props.editIdRef.current = key;
1364
- props.setCurrentView(VIEW_EDIT);
1365
- }
1366
- }
1367
- );
1368
- }
1369
- if (VIEW_ADD === props.currentView) {
1370
- return /* @__PURE__ */ React14.createElement(
1371
- ColorVariableCreation,
1372
- {
1373
- onGoBack: () => props.setCurrentView(VIEW_LIST),
1374
- onClose: props.closePopover
1375
- }
1376
- );
1377
- }
1378
- if (VIEW_EDIT === props.currentView) {
1379
- return /* @__PURE__ */ React14.createElement(
1380
- ColorVariableEdit,
1381
- {
1382
- editId: props.editIdRef.current ?? "",
1383
- onGoBack: () => props.setCurrentView(VIEW_LIST),
1384
- onClose: props.closePopover,
1385
- onSubmit: handleSubmitOnEdit
1386
- }
1387
- );
1388
- }
1389
- }
1390
- return null;
1391
- }
1392
-
1393
- // src/components/ui/tags/assigned-tag.tsx
1394
- var React15 = __toESM(require("react"));
1596
+ // src/components/ui/tags/deleted-tag.tsx
1597
+ var React19 = __toESM(require("react"));
1395
1598
  var import_icons10 = require("@elementor/icons");
1396
- var import_ui17 = require("@elementor/ui");
1397
- var import_i18n16 = require("@wordpress/i18n");
1398
- var SIZE8 = "tiny";
1399
- var AssignedTag = ({ startIcon, label, onUnlink, ...props }) => {
1400
- const actions = [];
1401
- if (onUnlink) {
1402
- actions.push(
1403
- /* @__PURE__ */ React15.createElement(import_ui17.IconButton, { key: "unlink", size: SIZE8, onClick: onUnlink, "aria-label": (0, import_i18n16.__)("Unlink", "elementor") }, /* @__PURE__ */ React15.createElement(import_icons10.DetachIcon, { fontSize: SIZE8 }))
1404
- );
1405
- }
1406
- return /* @__PURE__ */ React15.createElement(import_ui17.Tooltip, { title: label, placement: "top" }, /* @__PURE__ */ React15.createElement(
1407
- import_ui17.UnstableTag,
1599
+ var import_ui19 = require("@elementor/ui");
1600
+ var import_i18n17 = require("@wordpress/i18n");
1601
+ var DeletedTag = React19.forwardRef(({ label, onClick, ...props }, ref) => {
1602
+ return /* @__PURE__ */ React19.createElement(
1603
+ import_ui19.Chip,
1408
1604
  {
1409
- fullWidth: true,
1410
- showActionsOnHover: true,
1411
- startIcon: /* @__PURE__ */ React15.createElement(import_ui17.Stack, { gap: 0.5, direction: "row", alignItems: "center" }, startIcon),
1412
- label: /* @__PURE__ */ React15.createElement(import_ui17.Box, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React15.createElement(import_ui17.Typography, { sx: { lineHeight: 1.34 }, variant: "caption", noWrap: true }, label)),
1413
- actions,
1605
+ ref,
1606
+ size: "tiny",
1607
+ color: "warning",
1608
+ shape: "rounded",
1609
+ variant: "standard",
1610
+ onClick,
1611
+ icon: /* @__PURE__ */ React19.createElement(import_icons10.AlertTriangleFilledIcon, null),
1612
+ label: /* @__PURE__ */ React19.createElement(import_ui19.Tooltip, { title: label, placement: "top" }, /* @__PURE__ */ React19.createElement(import_ui19.Box, { sx: { display: "flex", gap: 0.5, alignItems: "center" } }, /* @__PURE__ */ React19.createElement(import_ui19.Typography, { variant: "caption", noWrap: true }, label), /* @__PURE__ */ React19.createElement(import_ui19.Typography, { variant: "caption", noWrap: true, sx: { textOverflow: "initial", overflow: "visible" } }, "(", (0, import_i18n17.__)("deleted", "elementor"), ")"))),
1613
+ sx: {
1614
+ height: (theme) => theme.spacing(3.5),
1615
+ borderRadius: (theme) => theme.spacing(1),
1616
+ justifyContent: "flex-start",
1617
+ width: "100%"
1618
+ },
1414
1619
  ...props
1415
1620
  }
1416
- ));
1417
- };
1621
+ );
1622
+ });
1418
1623
 
1419
- // src/components/ui/variable/assigned-variable.tsx
1420
- var AssignedVariable = ({
1421
- variable,
1422
- variablePropTypeUtil,
1423
- fallbackPropTypeUtil,
1424
- additionalStartIcon
1425
- }) => {
1426
- const { setValue } = (0, import_editor_controls8.useBoundProp)();
1427
- const anchorRef = (0, import_react13.useRef)(null);
1624
+ // src/components/ui/variable/deleted-variable.tsx
1625
+ var DeletedVariable = ({ variable, propTypeKey }) => {
1626
+ const { fallbackPropTypeUtil, propTypeUtil } = getVariableType(propTypeKey);
1627
+ const { setValue } = (0, import_editor_controls7.useBoundProp)();
1628
+ const userPermissions = usePermissions();
1629
+ const [showInfotip, setShowInfotip] = (0, import_react13.useState)(false);
1630
+ const toggleInfotip = () => setShowInfotip((prev) => !prev);
1631
+ const closeInfotip = () => setShowInfotip(false);
1632
+ const deletedChipAnchorRef = (0, import_react13.useRef)(null);
1428
1633
  const popupId = (0, import_react13.useId)();
1429
- const popupState = (0, import_ui18.usePopupState)({
1634
+ const popupState = (0, import_ui20.usePopupState)({
1430
1635
  variant: "popover",
1431
- popupId: `elementor-variables-list-${popupId}`
1636
+ popupId: `elementor-variables-restore-${popupId}`
1432
1637
  });
1433
- const unlinkVariable = () => {
1434
- setValue(fallbackPropTypeUtil.create(variable.value));
1638
+ const handlers = {};
1639
+ if (userPermissions.canUnlink()) {
1640
+ handlers.onUnlink = () => {
1641
+ setValue(fallbackPropTypeUtil.create(variable.value));
1642
+ };
1643
+ }
1644
+ if (userPermissions.canRestore()) {
1645
+ handlers.onRestore = () => {
1646
+ if (!variable.key) {
1647
+ return;
1648
+ }
1649
+ restoreVariable(variable.key).then((key) => {
1650
+ setValue(propTypeUtil.create(key));
1651
+ closeInfotip();
1652
+ }).catch(() => {
1653
+ closeInfotip();
1654
+ popupState.setAnchorEl(deletedChipAnchorRef.current);
1655
+ popupState.open();
1656
+ });
1657
+ };
1658
+ }
1659
+ const handleRestoreWithOverrides = () => {
1660
+ popupState.close();
1435
1661
  };
1436
- return /* @__PURE__ */ React16.createElement(import_ui18.Box, { ref: anchorRef }, /* @__PURE__ */ React16.createElement(
1437
- AssignedTag,
1662
+ return /* @__PURE__ */ React20.createElement(React20.Fragment, null, /* @__PURE__ */ React20.createElement(import_ui20.Box, { ref: deletedChipAnchorRef }, showInfotip && /* @__PURE__ */ React20.createElement(import_ui20.Backdrop, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React20.createElement(
1663
+ import_ui20.Infotip,
1438
1664
  {
1439
- label: variable.label,
1440
- startIcon: /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(import_icons11.ColorFilterIcon, { fontSize: SIZE8 }), additionalStartIcon),
1441
- onUnlink: unlinkVariable,
1442
- ...(0, import_ui18.bindTrigger)(popupState)
1443
- }
1444
- ), /* @__PURE__ */ React16.createElement(
1445
- import_ui18.Popover,
1665
+ color: "warning",
1666
+ placement: "right-start",
1667
+ open: showInfotip,
1668
+ disableHoverListener: true,
1669
+ onClose: closeInfotip,
1670
+ content: /* @__PURE__ */ React20.createElement(
1671
+ DeletedVariableAlert,
1672
+ {
1673
+ onClose: closeInfotip,
1674
+ onUnlink: handlers.onUnlink,
1675
+ onRestore: handlers.onRestore,
1676
+ label: variable.label
1677
+ }
1678
+ ),
1679
+ slotProps: {
1680
+ popper: {
1681
+ modifiers: [
1682
+ {
1683
+ name: "offset",
1684
+ options: { offset: [0, 24] }
1685
+ }
1686
+ ]
1687
+ }
1688
+ }
1689
+ },
1690
+ /* @__PURE__ */ React20.createElement(DeletedTag, { label: variable.label, onClick: toggleInfotip })
1691
+ ), /* @__PURE__ */ React20.createElement(
1692
+ import_ui20.Popover,
1446
1693
  {
1447
1694
  disableScrollLock: true,
1448
- anchorEl: anchorRef.current,
1449
1695
  anchorOrigin: { vertical: "bottom", horizontal: "right" },
1450
1696
  transformOrigin: { vertical: "top", horizontal: "right" },
1451
1697
  PaperProps: {
1452
1698
  sx: { my: 1 }
1453
1699
  },
1454
- ...(0, import_ui18.bindPopover)(popupState)
1700
+ ...(0, import_ui20.bindPopover)(popupState)
1455
1701
  },
1456
- /* @__PURE__ */ React16.createElement(
1457
- VariableSelectionPopover,
1702
+ /* @__PURE__ */ React20.createElement(VariableTypeProvider, { propTypeKey }, /* @__PURE__ */ React20.createElement(
1703
+ VariableRestore,
1458
1704
  {
1459
- selectedVariable: variable,
1460
- closePopover: popupState.close,
1461
- propTypeKey: variablePropTypeUtil.key
1705
+ variableId: variable.key ?? "",
1706
+ onClose: popupState.close,
1707
+ onSubmit: handleRestoreWithOverrides
1462
1708
  }
1463
- )
1464
- ));
1709
+ ))
1710
+ )));
1465
1711
  };
1466
1712
 
1467
- // src/components/ui/variable/deleted-variable.tsx
1468
- var React19 = __toESM(require("react"));
1713
+ // src/components/ui/variable/missing-variable.tsx
1714
+ var React23 = __toESM(require("react"));
1469
1715
  var import_react14 = require("react");
1470
- var import_editor_controls9 = require("@elementor/editor-controls");
1471
- var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
1472
- var import_ui21 = require("@elementor/ui");
1473
-
1474
- // src/components/ui/deleted-variable-alert.tsx
1475
- var React17 = __toESM(require("react"));
1476
- var import_editor_editing_panel8 = require("@elementor/editor-editing-panel");
1477
- var import_ui19 = require("@elementor/ui");
1478
- var import_i18n17 = require("@wordpress/i18n");
1479
- var DeletedVariableAlert = ({ onClose, onUnlink, onRestore, label }) => {
1480
- const sectionWidth = (0, import_editor_editing_panel8.useSectionWidth)();
1481
- return /* @__PURE__ */ React17.createElement(import_ui19.ClickAwayListener, { onClickAway: onClose }, /* @__PURE__ */ React17.createElement(
1482
- import_ui19.Alert,
1716
+ var import_editor_controls8 = require("@elementor/editor-controls");
1717
+ var import_ui23 = require("@elementor/ui");
1718
+ var import_i18n19 = require("@wordpress/i18n");
1719
+
1720
+ // src/components/ui/missing-variable-alert.tsx
1721
+ var React21 = __toESM(require("react"));
1722
+ var import_editor_editing_panel7 = require("@elementor/editor-editing-panel");
1723
+ var import_ui21 = require("@elementor/ui");
1724
+ var import_i18n18 = require("@wordpress/i18n");
1725
+ var MissingVariableAlert = ({ onClose, onClear }) => {
1726
+ const sectionWidth = (0, import_editor_editing_panel7.useSectionWidth)();
1727
+ return /* @__PURE__ */ React21.createElement(import_ui21.ClickAwayListener, { onClickAway: onClose }, /* @__PURE__ */ React21.createElement(
1728
+ import_ui21.Alert,
1483
1729
  {
1484
1730
  variant: "standard",
1485
1731
  severity: "warning",
1486
1732
  onClose,
1487
- action: /* @__PURE__ */ React17.createElement(React17.Fragment, null, onUnlink && /* @__PURE__ */ React17.createElement(import_ui19.AlertAction, { variant: "contained", onClick: onUnlink }, (0, import_i18n17.__)("Unlink", "elementor")), onRestore && /* @__PURE__ */ React17.createElement(import_ui19.AlertAction, { variant: "outlined", onClick: onRestore }, (0, import_i18n17.__)("Restore", "elementor"))),
1733
+ action: /* @__PURE__ */ React21.createElement(React21.Fragment, null, onClear && /* @__PURE__ */ React21.createElement(import_ui21.AlertAction, { variant: "contained", onClick: onClear }, (0, import_i18n18.__)("Clear", "elementor"))),
1488
1734
  sx: { width: sectionWidth }
1489
1735
  },
1490
- /* @__PURE__ */ React17.createElement(import_ui19.AlertTitle, null, (0, import_i18n17.__)("Deleted variable", "elementor")),
1491
- (0, import_i18n17.__)("The variable", "elementor"),
1492
- " '",
1493
- label,
1494
- "'",
1495
- " ",
1496
- (0, import_i18n17.__)(
1497
- "has been deleted, but it is still referenced in this location. You may restore the variable or unlink it to assign a different value.",
1736
+ /* @__PURE__ */ React21.createElement(import_ui21.AlertTitle, null, (0, import_i18n18.__)("This variable is missing", "elementor")),
1737
+ (0, import_i18n18.__)(
1738
+ "It may have been deleted. Try clearing this field and select a different value or variable.",
1498
1739
  "elementor"
1499
1740
  )
1500
1741
  ));
1501
1742
  };
1502
1743
 
1503
- // src/components/ui/tags/deleted-tag.tsx
1504
- var React18 = __toESM(require("react"));
1505
- var import_icons12 = require("@elementor/icons");
1506
- var import_ui20 = require("@elementor/ui");
1507
- var import_i18n18 = require("@wordpress/i18n");
1508
- var DeletedTag = React18.forwardRef(({ label, onClick, ...props }, ref) => {
1509
- return /* @__PURE__ */ React18.createElement(
1510
- import_ui20.Chip,
1744
+ // src/components/ui/tags/missing-tag.tsx
1745
+ var React22 = __toESM(require("react"));
1746
+ var import_icons11 = require("@elementor/icons");
1747
+ var import_ui22 = require("@elementor/ui");
1748
+ var MissingTag = React22.forwardRef(({ label, onClick, ...props }, ref) => {
1749
+ return /* @__PURE__ */ React22.createElement(
1750
+ import_ui22.Chip,
1511
1751
  {
1512
1752
  ref,
1513
1753
  size: "tiny",
@@ -1515,8 +1755,8 @@ var DeletedTag = React18.forwardRef(({ label, onClick, ...props }, ref) => {
1515
1755
  shape: "rounded",
1516
1756
  variant: "standard",
1517
1757
  onClick,
1518
- icon: /* @__PURE__ */ React18.createElement(import_icons12.AlertTriangleFilledIcon, null),
1519
- label: /* @__PURE__ */ React18.createElement(import_ui20.Tooltip, { title: label, placement: "top" }, /* @__PURE__ */ React18.createElement(import_ui20.Box, { sx: { display: "flex", gap: 0.5, alignItems: "center" } }, /* @__PURE__ */ React18.createElement(import_ui20.Typography, { variant: "caption", noWrap: true }, label), /* @__PURE__ */ React18.createElement(import_ui20.Typography, { variant: "caption", noWrap: true, sx: { textOverflow: "initial", overflow: "visible" } }, "(", (0, import_i18n18.__)("deleted", "elementor"), ")"))),
1758
+ icon: /* @__PURE__ */ React22.createElement(import_icons11.AlertTriangleFilledIcon, null),
1759
+ label,
1520
1760
  sx: {
1521
1761
  height: (theme) => theme.spacing(3.5),
1522
1762
  borderRadius: (theme) => theme.spacing(1),
@@ -1528,42 +1768,22 @@ var DeletedTag = React18.forwardRef(({ label, onClick, ...props }, ref) => {
1528
1768
  );
1529
1769
  });
1530
1770
 
1531
- // src/components/ui/variable/deleted-variable.tsx
1532
- var isV331Active = (0, import_editor_v1_adapters.isExperimentActive)("e_v_3_31");
1533
- var DeletedVariable = ({ variable, variablePropTypeUtil, fallbackPropTypeUtil }) => {
1534
- const { setValue } = (0, import_editor_controls9.useBoundProp)();
1535
- const [showInfotip, setShowInfotip] = (0, import_react14.useState)(false);
1536
- const toggleInfotip = () => setShowInfotip((prev) => !prev);
1537
- const closeInfotip = () => setShowInfotip(false);
1538
- const unlinkVariable = () => {
1539
- setValue(fallbackPropTypeUtil.create(variable.value));
1540
- };
1541
- const handleRestore = () => {
1542
- if (!variable.key) {
1543
- return;
1544
- }
1545
- restoreVariable(variable.key).then((key) => {
1546
- setValue(variablePropTypeUtil.create(key));
1547
- closeInfotip();
1548
- });
1549
- };
1550
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, showInfotip && /* @__PURE__ */ React19.createElement(import_ui21.Backdrop, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React19.createElement(
1551
- import_ui21.Infotip,
1771
+ // src/components/ui/variable/missing-variable.tsx
1772
+ var MissingVariable = () => {
1773
+ const { setValue } = (0, import_editor_controls8.useBoundProp)();
1774
+ const [infotipVisible, setInfotipVisible] = (0, import_react14.useState)(false);
1775
+ const toggleInfotip = () => setInfotipVisible((prev) => !prev);
1776
+ const closeInfotip = () => setInfotipVisible(false);
1777
+ const clearValue = () => setValue(null);
1778
+ return /* @__PURE__ */ React23.createElement(React23.Fragment, null, infotipVisible && /* @__PURE__ */ React23.createElement(import_ui23.Backdrop, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React23.createElement(
1779
+ import_ui23.Infotip,
1552
1780
  {
1553
1781
  color: "warning",
1554
1782
  placement: "right-start",
1555
- open: showInfotip,
1783
+ open: infotipVisible,
1556
1784
  disableHoverListener: true,
1557
1785
  onClose: closeInfotip,
1558
- content: /* @__PURE__ */ React19.createElement(
1559
- DeletedVariableAlert,
1560
- {
1561
- onClose: closeInfotip,
1562
- onUnlink: unlinkVariable,
1563
- onRestore: isV331Active ? handleRestore : void 0,
1564
- label: variable.label
1565
- }
1566
- ),
1786
+ content: /* @__PURE__ */ React23.createElement(MissingVariableAlert, { onClose: closeInfotip, onClear: clearValue }),
1567
1787
  slotProps: {
1568
1788
  popper: {
1569
1789
  modifiers: [
@@ -1575,229 +1795,197 @@ var DeletedVariable = ({ variable, variablePropTypeUtil, fallbackPropTypeUtil })
1575
1795
  }
1576
1796
  }
1577
1797
  },
1578
- /* @__PURE__ */ React19.createElement(DeletedTag, { label: variable.label, onClick: toggleInfotip })
1798
+ /* @__PURE__ */ React23.createElement(MissingTag, { label: (0, import_i18n19.__)("Missing variable", "elementor"), onClick: toggleInfotip })
1579
1799
  ));
1580
1800
  };
1581
1801
 
1582
- // src/controls/color-variable-control.tsx
1583
- var ColorVariableControl = () => {
1584
- const { value: variableValue } = (0, import_editor_controls10.useBoundProp)(colorVariablePropTypeUtil);
1585
- const assignedVariable = useVariable(variableValue);
1802
+ // src/controls/variable-control.tsx
1803
+ var VariableControl = () => {
1804
+ const boundProp = (0, import_editor_controls9.useBoundProp)().value;
1805
+ const assignedVariable = useVariable(boundProp?.value);
1586
1806
  if (!assignedVariable) {
1587
- throw new Error(`Global color variable ${variableValue} not found`);
1807
+ return /* @__PURE__ */ React24.createElement(MissingVariable, null);
1588
1808
  }
1589
- const isVariableDeleted = assignedVariable?.deleted;
1590
- if (isVariableDeleted) {
1591
- return /* @__PURE__ */ React20.createElement(
1592
- DeletedVariable,
1593
- {
1594
- variable: assignedVariable,
1595
- variablePropTypeUtil: colorVariablePropTypeUtil,
1596
- fallbackPropTypeUtil: import_editor_props3.colorPropTypeUtil
1597
- }
1598
- );
1809
+ const { $$type: propTypeKey } = boundProp;
1810
+ if (assignedVariable?.deleted) {
1811
+ return /* @__PURE__ */ React24.createElement(DeletedVariable, { variable: assignedVariable, propTypeKey });
1599
1812
  }
1600
- return /* @__PURE__ */ React20.createElement(
1601
- AssignedVariable,
1602
- {
1603
- variable: assignedVariable,
1604
- variablePropTypeUtil: colorVariablePropTypeUtil,
1605
- fallbackPropTypeUtil: import_editor_props3.colorPropTypeUtil,
1606
- additionalStartIcon: /* @__PURE__ */ React20.createElement(ColorIndicator, { size: "inherit", value: assignedVariable.value, component: "span" })
1607
- }
1608
- );
1609
- };
1610
-
1611
- // src/hooks/use-prop-color-variable-action.tsx
1612
- var React21 = __toESM(require("react"));
1613
- var import_editor_editing_panel9 = require("@elementor/editor-editing-panel");
1614
- var import_icons13 = require("@elementor/icons");
1615
- var import_i18n19 = require("@wordpress/i18n");
1616
-
1617
- // src/utils.ts
1618
- var hasAssignedColorVariable = (propValue) => {
1619
- return !!colorVariablePropTypeUtil.isValid(propValue);
1620
- };
1621
- var supportsColorVariables = (propType) => {
1622
- return propType.kind === "union" && colorVariablePropTypeUtil.key in propType.prop_types;
1623
- };
1624
- var hasAssignedFontVariable = (propValue) => {
1625
- return !!fontVariablePropTypeUtil.isValid(propValue);
1626
- };
1627
- var supportsFontVariables = (propType) => {
1628
- return propType.kind === "union" && fontVariablePropTypeUtil.key in propType.prop_types;
1813
+ return /* @__PURE__ */ React24.createElement(AssignedVariable, { variable: assignedVariable, propTypeKey });
1629
1814
  };
1630
1815
 
1631
- // src/hooks/use-prop-color-variable-action.tsx
1632
- var usePropColorVariableAction = () => {
1633
- const { propType } = (0, import_editor_editing_panel9.useBoundProp)();
1634
- const visible = !!propType && supportsColorVariables(propType);
1816
+ // src/hooks/use-prop-variable-action.tsx
1817
+ var React25 = __toESM(require("react"));
1818
+ var import_editor_editing_panel8 = require("@elementor/editor-editing-panel");
1819
+ var import_icons12 = require("@elementor/icons");
1820
+ var import_i18n20 = require("@wordpress/i18n");
1821
+ var usePropVariableAction = () => {
1822
+ const { propType, path } = (0, import_editor_editing_panel8.useBoundProp)();
1823
+ const variable = resolveVariableFromPropType(propType);
1635
1824
  return {
1636
- visible,
1637
- icon: import_icons13.ColorFilterIcon,
1638
- title: (0, import_i18n19.__)("Variables", "elementor"),
1825
+ visible: Boolean(variable),
1826
+ icon: import_icons12.ColorFilterIcon,
1827
+ title: (0, import_i18n20.__)("Variables", "elementor"),
1639
1828
  content: ({ close: closePopover }) => {
1640
- return /* @__PURE__ */ React21.createElement(VariableSelectionPopover, { closePopover, propTypeKey: colorVariablePropTypeUtil.key });
1829
+ if (!variable) {
1830
+ return null;
1831
+ }
1832
+ trackOpenVariablePopover(path, variable.variableType);
1833
+ return /* @__PURE__ */ React25.createElement(VariableSelectionPopover, { closePopover, propTypeKey: variable.propTypeUtil.key });
1641
1834
  }
1642
1835
  };
1643
1836
  };
1644
-
1645
- // src/repeater-injections.ts
1646
- var import_editor_controls11 = require("@elementor/editor-controls");
1647
- var import_editor_props4 = require("@elementor/editor-props");
1648
-
1649
- // src/components/variables-repeater-item-slot.tsx
1650
- var React22 = __toESM(require("react"));
1651
- var useColorVariable = (value) => {
1652
- const variableId = value?.value?.color?.value;
1653
- return useVariable(variableId || "");
1654
- };
1655
- var BackgroundRepeaterColorIndicator = ({ value }) => {
1656
- const colorVariable = useColorVariable(value);
1657
- return /* @__PURE__ */ React22.createElement(ColorIndicator, { component: "span", size: "inherit", value: colorVariable?.value });
1658
- };
1659
- var BackgroundRepeaterLabel = ({ value }) => {
1660
- const colorVariable = useColorVariable(value);
1661
- return /* @__PURE__ */ React22.createElement("span", null, colorVariable?.label);
1662
- };
1663
- var BoxShadowRepeaterColorIndicator = ({ value }) => {
1664
- const colorVariable = useColorVariable(value);
1665
- return /* @__PURE__ */ React22.createElement(ColorIndicator, { component: "span", size: "inherit", value: colorVariable?.value });
1666
- };
1667
-
1668
- // src/repeater-injections.ts
1669
- function registerRepeaterInjections() {
1670
- (0, import_editor_controls11.injectIntoRepeaterItemIcon)({
1671
- id: "color-variables-background-icon",
1672
- component: BackgroundRepeaterColorIndicator,
1673
- condition: ({ value: prop }) => {
1674
- return hasAssignedColorVariable(import_editor_props4.backgroundColorOverlayPropTypeUtil.extract(prop)?.color);
1675
- }
1676
- });
1677
- (0, import_editor_controls11.injectIntoRepeaterItemIcon)({
1678
- id: "color-variables-icon",
1679
- component: BoxShadowRepeaterColorIndicator,
1680
- condition: ({ value: prop }) => {
1681
- return hasAssignedColorVariable(import_editor_props4.shadowPropTypeUtil.extract(prop)?.color);
1682
- }
1683
- });
1684
- (0, import_editor_controls11.injectIntoRepeaterItemLabel)({
1685
- id: "color-variables-label",
1686
- component: BackgroundRepeaterLabel,
1687
- condition: ({ value: prop }) => {
1688
- return hasAssignedColorVariable(import_editor_props4.backgroundColorOverlayPropTypeUtil.extract(prop)?.color);
1689
- }
1690
- });
1691
- }
1692
-
1693
- // src/transformers/variable-transformer.ts
1694
- var import_editor_canvas = require("@elementor/editor-canvas");
1695
- var variableTransformer = (0, import_editor_canvas.createTransformer)((id) => {
1696
- const variables = service.variables();
1697
- let name = id;
1698
- let fallbackValue = "";
1699
- if (variables[id]) {
1700
- fallbackValue = variables[id].value;
1701
- if (!variables[id]?.deleted) {
1702
- name = variables[id].label;
1703
- }
1704
- }
1705
- if (!name.trim()) {
1706
- return null;
1837
+ var resolveVariableFromPropType = (propType) => {
1838
+ if (propType.kind !== "union") {
1839
+ return void 0;
1707
1840
  }
1708
- if (!fallbackValue.trim()) {
1709
- return `var(--${name})`;
1841
+ for (const key of Object.keys(propType.prop_types)) {
1842
+ const variable = getVariableType(key);
1843
+ if (variable) {
1844
+ return variable;
1845
+ }
1710
1846
  }
1711
- return `var(--${name}, ${fallbackValue})`;
1712
- });
1713
-
1714
- // src/init-color-variables.ts
1715
- var { registerPopoverAction } = import_editor_editing_panel10.controlActionsMenu;
1716
- function initColorVariables() {
1717
- (0, import_editor_editing_panel10.registerControlReplacement)({
1718
- component: ColorVariableControl,
1719
- condition: ({ value }) => hasAssignedColorVariable(value)
1720
- });
1721
- registerPopoverAction({
1722
- id: "color-variables",
1723
- useProps: usePropColorVariableAction
1847
+ return void 0;
1848
+ };
1849
+ var trackOpenVariablePopover = (path, variableType) => {
1850
+ trackVariableEvent({
1851
+ varType: variableType,
1852
+ controlPath: path.join("."),
1853
+ action: "open"
1724
1854
  });
1725
- import_editor_canvas2.styleTransformersRegistry.register(colorVariablePropTypeUtil.key, variableTransformer);
1726
- registerRepeaterInjections();
1727
- }
1855
+ };
1728
1856
 
1729
- // src/init-font-variables.ts
1730
- var import_editor_canvas3 = require("@elementor/editor-canvas");
1731
- var import_editor_editing_panel12 = require("@elementor/editor-editing-panel");
1857
+ // src/register-variable-types.tsx
1858
+ var React28 = __toESM(require("react"));
1859
+ var import_editor_props3 = require("@elementor/editor-props");
1860
+ var import_icons14 = require("@elementor/icons");
1732
1861
 
1733
- // src/controls/font-variable-control.tsx
1734
- var React23 = __toESM(require("react"));
1735
- var import_editor_controls12 = require("@elementor/editor-controls");
1736
- var import_editor_props5 = require("@elementor/editor-props");
1737
- var FontVariableControl = () => {
1738
- const { value: variableValue } = (0, import_editor_controls12.useBoundProp)(fontVariablePropTypeUtil);
1739
- const assignedVariable = useVariable(variableValue);
1740
- if (!assignedVariable) {
1741
- throw new Error(`Global font variable ${variableValue} not found`);
1742
- }
1743
- const isVariableDeleted = assignedVariable?.deleted;
1744
- if (isVariableDeleted) {
1745
- return /* @__PURE__ */ React23.createElement(
1746
- DeletedVariable,
1747
- {
1748
- variable: assignedVariable,
1749
- variablePropTypeUtil: fontVariablePropTypeUtil,
1750
- fallbackPropTypeUtil: import_editor_props5.stringPropTypeUtil
1751
- }
1752
- );
1753
- }
1754
- return /* @__PURE__ */ React23.createElement(
1755
- AssignedVariable,
1862
+ // src/components/fields/color-field.tsx
1863
+ var React26 = __toESM(require("react"));
1864
+ var import_react15 = require("react");
1865
+ var import_ui24 = require("@elementor/ui");
1866
+ var import_i18n21 = require("@wordpress/i18n");
1867
+ var ColorField = ({ value, onChange }) => {
1868
+ const [color, setColor] = (0, import_react15.useState)(value);
1869
+ const [errorMessage, setErrorMessage] = (0, import_react15.useState)("");
1870
+ const defaultRef = (0, import_react15.useRef)(null);
1871
+ const anchorRef = usePopoverContentRef() ?? defaultRef.current;
1872
+ const handleChange = (newValue) => {
1873
+ setColor(newValue);
1874
+ const errorMsg = validateValue(newValue);
1875
+ setErrorMessage(errorMsg);
1876
+ onChange(errorMsg ? "" : newValue);
1877
+ };
1878
+ return /* @__PURE__ */ React26.createElement(import_ui24.Grid, { container: true, gap: 0.75, alignItems: "center" }, /* @__PURE__ */ React26.createElement(import_ui24.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React26.createElement(import_ui24.FormLabel, { size: "tiny" }, (0, import_i18n21.__)("Value", "elementor"))), /* @__PURE__ */ React26.createElement(import_ui24.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React26.createElement(
1879
+ import_ui24.UnstableColorField,
1756
1880
  {
1757
- variable: assignedVariable,
1758
- variablePropTypeUtil: fontVariablePropTypeUtil,
1759
- fallbackPropTypeUtil: import_editor_props5.stringPropTypeUtil
1881
+ size: "tiny",
1882
+ fullWidth: true,
1883
+ value: color,
1884
+ onChange: handleChange,
1885
+ error: errorMessage ?? void 0,
1886
+ slotProps: {
1887
+ colorPicker: {
1888
+ anchorEl: anchorRef,
1889
+ anchorOrigin: { vertical: "top", horizontal: "right" },
1890
+ transformOrigin: { vertical: "top", horizontal: -10 }
1891
+ }
1892
+ }
1760
1893
  }
1761
- );
1894
+ ), errorMessage && /* @__PURE__ */ React26.createElement(import_ui24.FormHelperText, { error: true }, errorMessage)));
1762
1895
  };
1763
1896
 
1764
- // src/hooks/use-prop-font-variable-action.tsx
1765
- var React24 = __toESM(require("react"));
1766
- var import_editor_editing_panel11 = require("@elementor/editor-editing-panel");
1767
- var import_icons14 = require("@elementor/icons");
1768
- var import_i18n20 = require("@wordpress/i18n");
1769
- var usePropFontVariableAction = () => {
1770
- const { propType } = (0, import_editor_editing_panel11.useBoundProp)();
1771
- const visible = !!propType && supportsFontVariables(propType);
1772
- return {
1773
- visible,
1774
- icon: import_icons14.ColorFilterIcon,
1775
- title: (0, import_i18n20.__)("Variables", "elementor"),
1776
- content: ({ close: closePopover }) => {
1777
- return /* @__PURE__ */ React24.createElement(VariableSelectionPopover, { closePopover, propTypeKey: fontVariablePropTypeUtil.key });
1778
- }
1897
+ // src/components/fields/font-field.tsx
1898
+ var React27 = __toESM(require("react"));
1899
+ var import_react16 = require("react");
1900
+ var import_editor_controls10 = require("@elementor/editor-controls");
1901
+ var import_editor_editing_panel9 = require("@elementor/editor-editing-panel");
1902
+ var import_icons13 = require("@elementor/icons");
1903
+ var import_ui25 = require("@elementor/ui");
1904
+ var import_i18n22 = require("@wordpress/i18n");
1905
+ var FontField = ({ value, onChange }) => {
1906
+ const [fontFamily, setFontFamily] = (0, import_react16.useState)(value);
1907
+ const [errorMessage, setErrorMessage] = (0, import_react16.useState)("");
1908
+ const defaultRef = (0, import_react16.useRef)(null);
1909
+ const anchorRef = usePopoverContentRef() ?? defaultRef.current;
1910
+ const fontPopoverState = (0, import_ui25.usePopupState)({ variant: "popover" });
1911
+ const fontFamilies = (0, import_editor_editing_panel9.useFontFamilies)();
1912
+ const sectionWidth = (0, import_editor_editing_panel9.useSectionWidth)();
1913
+ const mapFontSubs = React27.useMemo(() => {
1914
+ return fontFamilies.map(({ label, fonts }) => ({
1915
+ label,
1916
+ items: fonts
1917
+ }));
1918
+ }, [fontFamilies]);
1919
+ const handleChange = (newValue) => {
1920
+ setFontFamily(newValue);
1921
+ const errorMsg = validateValue(newValue);
1922
+ setErrorMessage(errorMsg);
1923
+ onChange(errorMsg ? "" : newValue);
1924
+ };
1925
+ const handleFontFamilyChange = (newFontFamily) => {
1926
+ handleChange(newFontFamily);
1927
+ fontPopoverState.close();
1779
1928
  };
1929
+ return /* @__PURE__ */ React27.createElement(import_ui25.Grid, { container: true, gap: 0.75, alignItems: "center" }, /* @__PURE__ */ React27.createElement(import_ui25.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React27.createElement(import_ui25.FormLabel, { size: "tiny" }, (0, import_i18n22.__)("Value", "elementor"))), /* @__PURE__ */ React27.createElement(import_ui25.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React27.createElement(
1930
+ import_ui25.UnstableTag,
1931
+ {
1932
+ variant: "outlined",
1933
+ label: fontFamily,
1934
+ endIcon: /* @__PURE__ */ React27.createElement(import_icons13.ChevronDownIcon, { fontSize: "tiny" }),
1935
+ ...(0, import_ui25.bindTrigger)(fontPopoverState),
1936
+ fullWidth: true
1937
+ }
1938
+ ), /* @__PURE__ */ React27.createElement(
1939
+ import_ui25.Popover,
1940
+ {
1941
+ disablePortal: true,
1942
+ disableScrollLock: true,
1943
+ anchorEl: anchorRef,
1944
+ anchorOrigin: { vertical: "top", horizontal: "right" },
1945
+ transformOrigin: { vertical: "top", horizontal: -28 },
1946
+ ...(0, import_ui25.bindPopover)(fontPopoverState)
1947
+ },
1948
+ /* @__PURE__ */ React27.createElement(
1949
+ import_editor_controls10.ItemSelector,
1950
+ {
1951
+ itemsList: mapFontSubs,
1952
+ selectedItem: fontFamily,
1953
+ onItemChange: handleFontFamilyChange,
1954
+ onClose: fontPopoverState.close,
1955
+ sectionWidth,
1956
+ title: (0, import_i18n22.__)("Font Family", "elementor"),
1957
+ itemStyle: (item) => ({ fontFamily: item.value }),
1958
+ onDebounce: import_editor_controls10.enqueueFont,
1959
+ icon: import_icons13.TextIcon
1960
+ }
1961
+ )
1962
+ ), errorMessage && /* @__PURE__ */ React27.createElement(import_ui25.FormHelperText, { error: true }, errorMessage)));
1780
1963
  };
1781
1964
 
1782
- // src/init-font-variables.ts
1783
- var { registerPopoverAction: registerPopoverAction2 } = import_editor_editing_panel12.controlActionsMenu;
1784
- function initFontVariables() {
1785
- (0, import_editor_editing_panel12.registerControlReplacement)({
1786
- component: FontVariableControl,
1787
- condition: ({ value }) => hasAssignedFontVariable(value)
1965
+ // src/register-variable-types.tsx
1966
+ function registerVariableTypes() {
1967
+ registerVariableType({
1968
+ valueField: ColorField,
1969
+ icon: import_icons14.BrushIcon,
1970
+ propTypeUtil: colorVariablePropTypeUtil,
1971
+ fallbackPropTypeUtil: import_editor_props3.colorPropTypeUtil,
1972
+ variableType: "color",
1973
+ startIcon: ({ value }) => /* @__PURE__ */ React28.createElement(ColorIndicator, { size: "inherit", component: "span", value })
1788
1974
  });
1789
- registerPopoverAction2({
1790
- id: "font-variables",
1791
- useProps: usePropFontVariableAction
1975
+ registerVariableType({
1976
+ valueField: FontField,
1977
+ icon: import_icons14.TextIcon,
1978
+ propTypeUtil: fontVariablePropTypeUtil,
1979
+ fallbackPropTypeUtil: import_editor_props3.stringPropTypeUtil,
1980
+ variableType: "font"
1792
1981
  });
1793
- import_editor_canvas3.styleTransformersRegistry.register(fontVariablePropTypeUtil.key, variableTransformer);
1794
1982
  }
1795
1983
 
1796
1984
  // src/renderers/style-variables-renderer.tsx
1797
- var React25 = __toESM(require("react"));
1798
- var import_react15 = require("react");
1799
- var import_editor_v1_adapters2 = require("@elementor/editor-v1-adapters");
1800
- var import_ui22 = require("@elementor/ui");
1985
+ var React29 = __toESM(require("react"));
1986
+ var import_react17 = require("react");
1987
+ var import_editor_v1_adapters3 = require("@elementor/editor-v1-adapters");
1988
+ var import_ui26 = require("@elementor/ui");
1801
1989
 
1802
1990
  // src/sync/get-canvas-iframe-document.ts
1803
1991
  function getCanvasIframeDocument() {
@@ -1816,14 +2004,14 @@ function StyleVariablesRenderer() {
1816
2004
  }
1817
2005
  const cssVariables = convertToCssVariables(styleVariables);
1818
2006
  const wrappedCss = `${VARIABLES_WRAPPER}{${cssVariables}}`;
1819
- return /* @__PURE__ */ React25.createElement(import_ui22.Portal, { container }, /* @__PURE__ */ React25.createElement("style", { "data-e-style-id": "e-variables", key: wrappedCss }, wrappedCss));
2007
+ return /* @__PURE__ */ React29.createElement(import_ui26.Portal, { container }, /* @__PURE__ */ React29.createElement("style", { "data-e-style-id": "e-variables", key: wrappedCss }, wrappedCss));
1820
2008
  }
1821
2009
  function usePortalContainer() {
1822
- return (0, import_editor_v1_adapters2.__privateUseListenTo)((0, import_editor_v1_adapters2.commandEndEvent)("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
2010
+ return (0, import_editor_v1_adapters3.__privateUseListenTo)((0, import_editor_v1_adapters3.commandEndEvent)("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
1823
2011
  }
1824
2012
  function useStyleVariables() {
1825
- const [variables, setVariables] = (0, import_react15.useState)({});
1826
- (0, import_react15.useEffect)(() => {
2013
+ const [variables, setVariables] = (0, import_react17.useState)({});
2014
+ (0, import_react17.useEffect)(() => {
1827
2015
  const unsubscribe = styleVariablesRepository.subscribe(setVariables);
1828
2016
  return () => {
1829
2017
  unsubscribe();
@@ -1841,18 +2029,86 @@ function convertToCssVariables(variables) {
1841
2029
  return listOfVariables.map(([key, variable]) => cssVariableDeclaration(key, variable)).join("");
1842
2030
  }
1843
2031
 
2032
+ // src/repeater-injections.ts
2033
+ var import_editor_controls11 = require("@elementor/editor-controls");
2034
+ var import_editor_props4 = require("@elementor/editor-props");
2035
+
2036
+ // src/components/variables-repeater-item-slot.tsx
2037
+ var React30 = __toESM(require("react"));
2038
+ var useColorVariable = (value) => {
2039
+ const variableId = value?.value?.color?.value;
2040
+ return useVariable(variableId || "");
2041
+ };
2042
+ var BackgroundRepeaterColorIndicator = ({ value }) => {
2043
+ const colorVariable = useColorVariable(value);
2044
+ return /* @__PURE__ */ React30.createElement(ColorIndicator, { component: "span", size: "inherit", value: colorVariable?.value });
2045
+ };
2046
+ var BackgroundRepeaterLabel = ({ value }) => {
2047
+ const colorVariable = useColorVariable(value);
2048
+ return /* @__PURE__ */ React30.createElement("span", null, colorVariable?.label);
2049
+ };
2050
+ var BoxShadowRepeaterColorIndicator = ({ value }) => {
2051
+ const colorVariable = useColorVariable(value);
2052
+ return /* @__PURE__ */ React30.createElement(ColorIndicator, { component: "span", size: "inherit", value: colorVariable?.value });
2053
+ };
2054
+
2055
+ // src/repeater-injections.ts
2056
+ function registerRepeaterInjections() {
2057
+ (0, import_editor_controls11.injectIntoRepeaterItemIcon)({
2058
+ id: "color-variables-background-icon",
2059
+ component: BackgroundRepeaterColorIndicator,
2060
+ condition: ({ value: prop }) => {
2061
+ return hasAssignedColorVariable(import_editor_props4.backgroundColorOverlayPropTypeUtil.extract(prop)?.color);
2062
+ }
2063
+ });
2064
+ (0, import_editor_controls11.injectIntoRepeaterItemIcon)({
2065
+ id: "color-variables-icon",
2066
+ component: BoxShadowRepeaterColorIndicator,
2067
+ condition: ({ value: prop }) => {
2068
+ return hasAssignedColorVariable(import_editor_props4.shadowPropTypeUtil.extract(prop)?.color);
2069
+ }
2070
+ });
2071
+ (0, import_editor_controls11.injectIntoRepeaterItemLabel)({
2072
+ id: "color-variables-label",
2073
+ component: BackgroundRepeaterLabel,
2074
+ condition: ({ value: prop }) => {
2075
+ return hasAssignedColorVariable(import_editor_props4.backgroundColorOverlayPropTypeUtil.extract(prop)?.color);
2076
+ }
2077
+ });
2078
+ }
2079
+ var hasAssignedColorVariable = (propValue) => {
2080
+ return !!colorVariablePropTypeUtil.isValid(propValue);
2081
+ };
2082
+
1844
2083
  // src/init.ts
2084
+ var { registerPopoverAction } = import_editor_editing_panel10.controlActionsMenu;
1845
2085
  function init() {
1846
- initColorVariables();
1847
- initFontVariables();
2086
+ registerVariableTypes();
2087
+ registerRepeaterInjections();
2088
+ (0, import_editor_editing_panel10.registerControlReplacement)({
2089
+ component: VariableControl,
2090
+ condition: ({ value }) => hasAssignedVariable(value)
2091
+ });
2092
+ registerPopoverAction({
2093
+ id: "variables",
2094
+ useProps: usePropVariableAction
2095
+ });
1848
2096
  service.init();
1849
2097
  (0, import_editor.injectIntoTop)({
1850
2098
  id: "canvas-style-variables-render",
1851
2099
  component: StyleVariablesRenderer
1852
2100
  });
2101
+ (0, import_editor_panels2.__registerPanel)(panel);
2102
+ }
2103
+ function hasAssignedVariable(propValue) {
2104
+ if (propValue && typeof propValue === "object" && "$$type" in propValue) {
2105
+ return hasVariableType(propValue.$$type);
2106
+ }
2107
+ return false;
1853
2108
  }
1854
2109
  // Annotate the CommonJS export names for ESM import in node:
1855
2110
  0 && (module.exports = {
1856
- init
2111
+ init,
2112
+ registerVariableType
1857
2113
  });
1858
2114
  //# sourceMappingURL=index.js.map