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