@elementor/editor-variables 3.33.0-98 → 3.35.0-324

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 (60) hide show
  1. package/dist/index.d.mts +17 -4
  2. package/dist/index.d.ts +17 -4
  3. package/dist/index.js +1903 -809
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1850 -747
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +16 -14
  8. package/src/api.ts +24 -0
  9. package/src/batch-operations.ts +86 -0
  10. package/src/components/fields/color-field.tsx +1 -0
  11. package/src/components/fields/font-field.tsx +2 -1
  12. package/src/components/fields/label-field.tsx +42 -6
  13. package/src/components/ui/deleted-variable-alert.tsx +14 -10
  14. package/src/components/ui/{no-variables.tsx → empty-state.tsx} +8 -13
  15. package/src/components/ui/menu-item-content.tsx +14 -11
  16. package/src/components/ui/mismatch-variable-alert.tsx +5 -9
  17. package/src/components/ui/missing-variable-alert.tsx +8 -9
  18. package/src/components/ui/no-search-results.tsx +1 -2
  19. package/src/components/ui/tags/assigned-tag.tsx +6 -3
  20. package/src/components/ui/tags/warning-variable-tag.tsx +44 -0
  21. package/src/components/ui/variable/deleted-variable.tsx +13 -6
  22. package/src/components/ui/variable/mismatch-variable.tsx +11 -4
  23. package/src/components/ui/variable/missing-variable.tsx +2 -2
  24. package/src/components/variable-creation.tsx +13 -4
  25. package/src/components/variable-edit.tsx +12 -12
  26. package/src/components/variable-restore.tsx +3 -2
  27. package/src/components/variables-manager/hooks/use-auto-edit.ts +21 -0
  28. package/src/components/variables-manager/hooks/use-error-navigation.ts +49 -0
  29. package/src/components/variables-manager/hooks/use-variables-manager-state.ts +89 -0
  30. package/src/components/variables-manager/variable-editable-cell.tsx +131 -67
  31. package/src/components/variables-manager/variables-manager-create-menu.tsx +118 -0
  32. package/src/components/variables-manager/variables-manager-panel.tsx +290 -59
  33. package/src/components/variables-manager/variables-manager-table.tsx +124 -14
  34. package/src/components/variables-selection.tsx +61 -15
  35. package/src/controls/variable-control.tsx +1 -1
  36. package/src/hooks/use-prop-variables.ts +28 -9
  37. package/src/hooks/use-variable-bound-prop.ts +42 -0
  38. package/src/index.ts +1 -0
  39. package/src/init.ts +9 -6
  40. package/src/mcp/create-variable-tool.ts +70 -0
  41. package/src/mcp/delete-variable-tool.ts +50 -0
  42. package/src/mcp/index.ts +17 -0
  43. package/src/mcp/list-variables-tool.ts +58 -0
  44. package/src/mcp/update-variable-tool.ts +81 -0
  45. package/src/mcp/variables-resource.ts +28 -0
  46. package/src/register-variable-types.tsx +4 -0
  47. package/src/service.ts +60 -1
  48. package/src/storage.ts +8 -0
  49. package/src/types.ts +1 -0
  50. package/src/utils/filter-by-search.ts +5 -0
  51. package/src/utils/tracking.ts +37 -22
  52. package/src/utils/unlink-variable.ts +1 -1
  53. package/src/utils/validations.ts +72 -3
  54. package/src/variables-registry/create-variable-type-registry.ts +20 -8
  55. package/src/variables-registry/variable-type-registry.ts +2 -1
  56. package/src/components/ui/tags/deleted-tag.tsx +0 -37
  57. package/src/components/ui/tags/mismatch-tag.tsx +0 -37
  58. package/src/components/ui/tags/missing-tag.tsx +0 -25
  59. /package/src/components/variables-manager/{variable-edit-menu.tsx → ui/variable-edit-menu.tsx} +0 -0
  60. /package/src/components/variables-manager/{variable-table-cell.tsx → ui/variable-table-cell.tsx} +0 -0
package/dist/index.mjs CHANGED
@@ -2,10 +2,11 @@
2
2
  import { injectIntoTop } from "@elementor/editor";
3
3
  import { controlActionsMenu, registerControlReplacement } from "@elementor/editor-editing-panel";
4
4
  import { __registerPanel as registerPanel } from "@elementor/editor-panels";
5
+ import { isTransformable as isTransformable2 } from "@elementor/editor-props";
5
6
 
6
7
  // src/components/variables-manager/variables-manager-panel.tsx
7
- import * as React8 from "react";
8
- import { useEffect, useState as useState4 } from "react";
8
+ import * as React12 from "react";
9
+ import { useCallback as useCallback5, useEffect as useEffect3, useState as useState5 } from "react";
9
10
  import {
10
11
  __createPanel as createPanel,
11
12
  Panel,
@@ -14,19 +15,154 @@ import {
14
15
  PanelHeader,
15
16
  PanelHeaderTitle
16
17
  } from "@elementor/editor-panels";
17
- import { ThemeProvider } from "@elementor/editor-ui";
18
+ import { SaveChangesDialog, SearchField, ThemeProvider, useDialog } from "@elementor/editor-ui";
18
19
  import { changeEditMode } from "@elementor/editor-v1-adapters";
19
- import { ColorFilterIcon, TrashIcon, XIcon } from "@elementor/icons";
20
- import { Alert, Box, Button, Divider, ErrorBoundary, IconButton as IconButton3, Stack as Stack4 } from "@elementor/ui";
21
- import { __ as __5 } from "@wordpress/i18n";
20
+ import { AlertTriangleFilledIcon as AlertTriangleFilledIcon2, ColorFilterIcon, TrashIcon } from "@elementor/icons";
21
+ import {
22
+ Alert,
23
+ AlertAction,
24
+ AlertTitle,
25
+ Button as Button3,
26
+ CloseButton,
27
+ Divider,
28
+ Infotip,
29
+ Stack as Stack6,
30
+ usePopupState as usePopupState2
31
+ } from "@elementor/ui";
32
+ import { __ as __9 } from "@wordpress/i18n";
22
33
 
23
- // src/hooks/use-prop-variables.ts
24
- import { useMemo } from "react";
25
- import { useBoundProp } from "@elementor/editor-controls";
34
+ // src/utils/tracking.ts
35
+ import { getMixpanel } from "@elementor/mixpanel";
36
+ var trackVariableEvent = ({ varType, controlPath, action }) => {
37
+ const { dispatchEvent, config } = getMixpanel();
38
+ if (!config?.names?.variables?.[action]) {
39
+ return;
40
+ }
41
+ const name = config.names.variables[action];
42
+ dispatchEvent?.(name, {
43
+ location: config?.locations?.variables || "",
44
+ secondaryLocation: config?.secondaryLocations?.variablesPopover || "",
45
+ trigger: config?.triggers?.click || "",
46
+ var_type: varType,
47
+ control_path: controlPath,
48
+ action_type: name
49
+ });
50
+ };
51
+ var trackVariablesManagerEvent = ({ action, varType, controlPath }) => {
52
+ const { dispatchEvent, config } = getMixpanel();
53
+ if (!config?.names?.variables?.[action]) {
54
+ return;
55
+ }
56
+ const name = config.names.variables[action];
57
+ const eventData = {
58
+ location: config?.locations?.variablesManager || "",
59
+ trigger: config?.triggers?.click || "",
60
+ action_type: name
61
+ };
62
+ if (varType) {
63
+ eventData.var_type = varType;
64
+ }
65
+ if (controlPath) {
66
+ eventData.style_control_path = controlPath;
67
+ }
68
+ dispatchEvent?.(name, eventData);
69
+ };
26
70
 
27
- // src/context/variable-type-context.tsx
28
- import * as React2 from "react";
29
- import { createContext, useContext } from "react";
71
+ // src/utils/validations.ts
72
+ import { AlertTriangleFilledIcon, InfoCircleFilledIcon } from "@elementor/icons";
73
+ import { __, sprintf } from "@wordpress/i18n";
74
+ var ERROR_MESSAGES = {
75
+ MISSING_VARIABLE_NAME: __("Give your variable a name.", "elementor"),
76
+ MISSING_VARIABLE_VALUE: __("Add a value to complete your variable.", "elementor"),
77
+ INVALID_CHARACTERS: __("Use letters, numbers, dashes (-), or underscores (_) for the name.", "elementor"),
78
+ NO_NON_SPECIAL_CHARACTER: __("Names have to include at least one non-special character.", "elementor"),
79
+ VARIABLE_LABEL_MAX_LENGTH: __("Keep names up to 50 characters.", "elementor"),
80
+ DUPLICATED_LABEL: __("This variable name already exists. Please choose a unique name.", "elementor"),
81
+ UNEXPECTED_ERROR: __("There was a glitch. Try saving your variable again.", "elementor"),
82
+ BATCH: {
83
+ DUPLICATED_LABELS: (count, name) => (
84
+ // eslint-disable-next-line @wordpress/i18n-translator-comments
85
+ sprintf(__("We found %1$d duplicated %2$s.", "elementor"), count, name)
86
+ ),
87
+ UNEXPECTED_ERROR: __("There was a glitch.", "elementor"),
88
+ DUPLICATED_LABEL_ACTION: __("Take me there", "elementor"),
89
+ DUPLICATED_LABEL_ACTION_MESSAGE: __("Please rename the variables.", "elementor"),
90
+ UNEXPECTED_ERROR_ACTION_MESSAGE: __("Try saving your variables again.", "elementor")
91
+ }
92
+ };
93
+ var VARIABLE_LABEL_MAX_LENGTH = 50;
94
+ var mapServerError = (error) => {
95
+ if (error?.response?.data?.code === "duplicated_label") {
96
+ return {
97
+ field: "label",
98
+ message: ERROR_MESSAGES.DUPLICATED_LABEL
99
+ };
100
+ }
101
+ if (error?.response?.data?.code === "batch_duplicated_label") {
102
+ const errorData = error?.response?.data?.data ?? {};
103
+ const count = Object.keys(errorData).length;
104
+ const name = count === 1 ? "name" : "names";
105
+ const duplicatedIds = Object.keys(errorData);
106
+ return {
107
+ field: "label",
108
+ message: ERROR_MESSAGES.BATCH.DUPLICATED_LABELS(count, name),
109
+ severity: "error",
110
+ IconComponent: AlertTriangleFilledIcon,
111
+ action: {
112
+ label: ERROR_MESSAGES.BATCH.DUPLICATED_LABEL_ACTION,
113
+ message: ERROR_MESSAGES.BATCH.DUPLICATED_LABEL_ACTION_MESSAGE,
114
+ data: {
115
+ duplicatedIds
116
+ }
117
+ }
118
+ };
119
+ }
120
+ if (error?.response?.data?.code === "batch_operation_failed") {
121
+ return {
122
+ field: "label",
123
+ message: ERROR_MESSAGES.BATCH.UNEXPECTED_ERROR,
124
+ severity: "secondary",
125
+ IconComponent: InfoCircleFilledIcon,
126
+ action: {
127
+ message: ERROR_MESSAGES.BATCH.UNEXPECTED_ERROR_ACTION_MESSAGE
128
+ }
129
+ };
130
+ }
131
+ return void 0;
132
+ };
133
+ var validateLabel = (name, variables) => {
134
+ if (!name.trim()) {
135
+ return ERROR_MESSAGES.MISSING_VARIABLE_NAME;
136
+ }
137
+ const allowedChars = /^[a-zA-Z0-9_-]+$/;
138
+ if (!allowedChars.test(name)) {
139
+ return ERROR_MESSAGES.INVALID_CHARACTERS;
140
+ }
141
+ const hasAlphanumeric = /[a-zA-Z0-9]/;
142
+ if (!hasAlphanumeric.test(name)) {
143
+ return ERROR_MESSAGES.NO_NON_SPECIAL_CHARACTER;
144
+ }
145
+ if (VARIABLE_LABEL_MAX_LENGTH < name.length) {
146
+ return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
147
+ }
148
+ if (Object.values(variables ?? {}).some((variable) => variable.label === name)) {
149
+ return ERROR_MESSAGES.DUPLICATED_LABEL;
150
+ }
151
+ return "";
152
+ };
153
+ var labelHint = (name) => {
154
+ const hintThreshold = VARIABLE_LABEL_MAX_LENGTH * 0.8 - 1;
155
+ if (hintThreshold < name.length) {
156
+ return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
157
+ }
158
+ return "";
159
+ };
160
+ var validateValue = (value) => {
161
+ if (!value.trim()) {
162
+ return ERROR_MESSAGES.MISSING_VARIABLE_VALUE;
163
+ }
164
+ return "";
165
+ };
30
166
 
31
167
  // src/variables-registry/create-variable-type-registry.ts
32
168
  import { styleTransformersRegistry } from "@elementor/editor-canvas";
@@ -36,7 +172,7 @@ import { stylesInheritanceTransformersRegistry } from "@elementor/editor-editing
36
172
  import * as React from "react";
37
173
  import { createTransformer } from "@elementor/editor-canvas";
38
174
  import { Stack, Typography } from "@elementor/ui";
39
- import { __ as __2 } from "@wordpress/i18n";
175
+ import { __ as __3 } from "@wordpress/i18n";
40
176
 
41
177
  // src/components/ui/color-indicator.tsx
42
178
  import { styled, UnstableColorIndicator } from "@elementor/ui";
@@ -51,7 +187,7 @@ import { z } from "@elementor/schema";
51
187
  var colorVariablePropTypeUtil = createPropUtils("global-color-variable", z.string());
52
188
 
53
189
  // src/service.ts
54
- import { __ } from "@wordpress/i18n";
190
+ import { __ as __2 } from "@wordpress/i18n";
55
191
 
56
192
  // src/api.ts
57
193
  import { httpService } from "@elementor/http-client";
@@ -86,9 +222,72 @@ var apiClient = {
86
222
  payload.value = value;
87
223
  }
88
224
  return httpService().post(BASE_PATH + "/restore", payload);
225
+ },
226
+ batch: (payload) => {
227
+ return httpService().post(BASE_PATH + "/batch", payload);
89
228
  }
90
229
  };
91
230
 
231
+ // src/batch-operations.ts
232
+ var generateTempId = () => {
233
+ const timestamp = Date.now().toString(36);
234
+ const random = Math.random().toString(36).substring(2, 8);
235
+ return `tmp-${timestamp}-${random}`;
236
+ };
237
+ var isTempId = (id2) => {
238
+ return id2.startsWith("tmp-");
239
+ };
240
+ var buildOperationsArray = (originalVariables, currentVariables) => {
241
+ const operations = [];
242
+ Object.entries(currentVariables).forEach(([id2, variable]) => {
243
+ if (isTempId(id2)) {
244
+ operations.push({
245
+ type: "create",
246
+ variable: {
247
+ ...variable,
248
+ id: id2
249
+ }
250
+ });
251
+ } else if (originalVariables[id2]) {
252
+ const original = originalVariables[id2];
253
+ if (original.deleted && !variable.deleted) {
254
+ operations.push({
255
+ type: "restore",
256
+ id: id2,
257
+ ...original.label !== variable.label && { label: variable.label },
258
+ ...original.value !== variable.value && { value: variable.value }
259
+ });
260
+ } else if (!variable.deleted && (original.label !== variable.label || original.value !== variable.value || original.order !== variable.order)) {
261
+ operations.push({
262
+ type: "update",
263
+ id: id2,
264
+ variable: {
265
+ ...original.label !== variable.label && { label: variable.label },
266
+ ...original.value !== variable.value && { value: variable.value },
267
+ ...original.order !== variable.order && { order: variable.order }
268
+ }
269
+ });
270
+ }
271
+ }
272
+ });
273
+ Object.entries(originalVariables).forEach(([id2, variable]) => {
274
+ if (isTempId(id2) || variable.deleted) {
275
+ return;
276
+ }
277
+ const currentVariable = currentVariables[id2];
278
+ if (!currentVariable || currentVariable.deleted) {
279
+ operations.push({
280
+ type: "delete",
281
+ id: id2
282
+ });
283
+ }
284
+ });
285
+ return operations.filter((op) => {
286
+ const id2 = op.id || op.variable?.id;
287
+ return id2 && !(isTempId(id2) && currentVariables[id2]?.deleted);
288
+ });
289
+ };
290
+
92
291
  // src/storage.ts
93
292
  var STORAGE_KEY = "elementor-global-variables";
94
293
  var STORAGE_WATERMARK_KEY = "elementor-global-variables-watermark";
@@ -96,6 +295,9 @@ var OP_RW = "RW";
96
295
  var OP_RO = "RO";
97
296
  var Storage = class {
98
297
  state;
298
+ notifyChange() {
299
+ window.dispatchEvent(new Event("variables:updated"));
300
+ }
99
301
  constructor() {
100
302
  this.state = {
101
303
  watermark: -1,
@@ -115,16 +317,19 @@ var Storage = class {
115
317
  this.state.watermark = watermark;
116
318
  localStorage.setItem(STORAGE_WATERMARK_KEY, this.state.watermark.toString());
117
319
  localStorage.setItem(STORAGE_KEY, JSON.stringify(this.state.variables));
320
+ this.notifyChange();
118
321
  }
119
322
  add(id2, variable) {
120
323
  this.load();
121
324
  this.state.variables[id2] = variable;
122
325
  localStorage.setItem(STORAGE_KEY, JSON.stringify(this.state.variables));
326
+ this.notifyChange();
123
327
  }
124
328
  update(id2, variable) {
125
329
  this.load();
126
330
  this.state.variables[id2] = variable;
127
331
  localStorage.setItem(STORAGE_KEY, JSON.stringify(this.state.variables));
332
+ this.notifyChange();
128
333
  }
129
334
  watermark(watermark) {
130
335
  this.state.watermark = watermark;
@@ -229,8 +434,11 @@ var service = {
229
434
  variables: () => {
230
435
  return storage.load();
231
436
  },
437
+ getWatermark: () => {
438
+ return storage.state.watermark;
439
+ },
232
440
  init: () => {
233
- service.load();
441
+ return service.load();
234
442
  },
235
443
  load: () => {
236
444
  return apiClient.list().then((response) => {
@@ -250,7 +458,7 @@ var service = {
250
458
  return apiClient.create(type, label, value).then((response) => {
251
459
  const { success, data: payload } = response.data;
252
460
  if (!success) {
253
- const errorMessage = payload?.message || __("Unexpected response from server", "elementor");
461
+ const errorMessage = payload?.message || __2("Unexpected response from server", "elementor");
254
462
  throw new Error(errorMessage);
255
463
  }
256
464
  return payload;
@@ -272,7 +480,7 @@ var service = {
272
480
  return apiClient.update(id2, label, value).then((response) => {
273
481
  const { success, data: payload } = response.data;
274
482
  if (!success) {
275
- const errorMessage = payload?.message || __("Unexpected response from server", "elementor");
483
+ const errorMessage = payload?.message || __2("Unexpected response from server", "elementor");
276
484
  throw new Error(errorMessage);
277
485
  }
278
486
  return payload;
@@ -331,6 +539,47 @@ var service = {
331
539
  variable: restoredVariable
332
540
  };
333
541
  });
542
+ },
543
+ batchSave: (originalVariables, currentVariables) => {
544
+ const operations = buildOperationsArray(originalVariables, currentVariables);
545
+ const batchPayload = { operations, watermark: storage.state.watermark };
546
+ if (operations.length === 0) {
547
+ return Promise.resolve({
548
+ success: true,
549
+ watermark: storage.state.watermark,
550
+ operations: 0
551
+ });
552
+ }
553
+ return apiClient.batch(batchPayload).then((response) => {
554
+ const { success, data: payload } = response.data;
555
+ if (!success) {
556
+ throw new Error("Unexpected response from server");
557
+ }
558
+ return payload;
559
+ }).then((data) => {
560
+ const { results, watermark } = data;
561
+ handleWatermark(OP_RW, watermark);
562
+ if (results) {
563
+ results.forEach((result) => {
564
+ if (result.variable) {
565
+ const { id: variableId, ...variableData } = result.variable;
566
+ if (result.type === "create") {
567
+ storage.add(variableId, variableData);
568
+ } else {
569
+ storage.update(variableId, variableData);
570
+ }
571
+ styleVariablesRepository.update({
572
+ [variableId]: variableData
573
+ });
574
+ }
575
+ });
576
+ }
577
+ return {
578
+ success: true,
579
+ watermark,
580
+ operations: operations.length
581
+ };
582
+ });
334
583
  }
335
584
  };
336
585
  var handleWatermark = (operation, newWatermark) => {
@@ -364,7 +613,7 @@ var inheritanceTransformer = createTransformer((id2) => {
364
613
  const variables = service.variables();
365
614
  const variable = variables[id2];
366
615
  if (!variable) {
367
- return /* @__PURE__ */ React.createElement("span", null, __2("Missing variable", "elementor"));
616
+ return /* @__PURE__ */ React.createElement("span", null, __3("Missing variable", "elementor"));
368
617
  }
369
618
  const showColorIndicator = variable.type === colorVariablePropTypeUtil.key;
370
619
  const css = resolveCssVariable(id2, variable);
@@ -385,19 +634,19 @@ var variableTransformer = createTransformer2((id2) => {
385
634
  function createVariableTypeRegistry() {
386
635
  const variableTypes = {};
387
636
  const registerVariableType2 = ({
637
+ key,
388
638
  icon,
389
639
  startIcon,
390
640
  valueField,
391
641
  propTypeUtil,
392
642
  variableType,
643
+ defaultValue,
393
644
  selectionFilter,
394
645
  valueTransformer,
395
646
  fallbackPropTypeUtil,
396
647
  isCompatible
397
648
  }) => {
398
- if (variableTypes[propTypeUtil.key]) {
399
- throw new Error(`Variable with key "${propTypeUtil.key}" is already registered.`);
400
- }
649
+ const variableTypeKey = key ?? propTypeUtil.key;
401
650
  if (!isCompatible) {
402
651
  isCompatible = (propType, variable) => {
403
652
  if ("union" === propType.kind) {
@@ -408,12 +657,13 @@ function createVariableTypeRegistry() {
408
657
  return false;
409
658
  };
410
659
  }
411
- variableTypes[propTypeUtil.key] = {
660
+ variableTypes[variableTypeKey] = {
412
661
  icon,
413
662
  startIcon,
414
663
  valueField,
415
664
  propTypeUtil,
416
665
  variableType,
666
+ defaultValue,
417
667
  selectionFilter,
418
668
  valueTransformer,
419
669
  fallbackPropTypeUtil,
@@ -431,23 +681,181 @@ function createVariableTypeRegistry() {
431
681
  const getVariableType2 = (key) => {
432
682
  return variableTypes[key];
433
683
  };
684
+ const getVariableTypes2 = () => {
685
+ return variableTypes;
686
+ };
434
687
  const hasVariableType2 = (key) => {
435
688
  return key in variableTypes;
436
689
  };
437
690
  return {
438
691
  registerVariableType: registerVariableType2,
439
692
  getVariableType: getVariableType2,
693
+ getVariableTypes: getVariableTypes2,
440
694
  hasVariableType: hasVariableType2
441
695
  };
442
696
  }
443
697
 
444
698
  // src/variables-registry/variable-type-registry.ts
445
- var { registerVariableType, getVariableType, hasVariableType } = createVariableTypeRegistry();
699
+ var { registerVariableType, getVariableType, getVariableTypes, hasVariableType } = createVariableTypeRegistry();
700
+
701
+ // src/components/ui/delete-confirmation-dialog.tsx
702
+ import * as React2 from "react";
703
+ import { AlertOctagonFilledIcon } from "@elementor/icons";
704
+ import {
705
+ Button,
706
+ Dialog,
707
+ DialogActions,
708
+ DialogContent,
709
+ DialogContentText,
710
+ DialogTitle,
711
+ Typography as Typography2
712
+ } from "@elementor/ui";
713
+ import { __ as __4 } from "@wordpress/i18n";
714
+ var TITLE_ID = "delete-variable-dialog";
715
+ var DeleteConfirmationDialog = ({
716
+ open,
717
+ label,
718
+ closeDialog,
719
+ onConfirm
720
+ }) => {
721
+ return /* @__PURE__ */ React2.createElement(Dialog, { open, onClose: closeDialog, "aria-labelledby": TITLE_ID, maxWidth: "xs" }, /* @__PURE__ */ React2.createElement(DialogTitle, { id: TITLE_ID, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React2.createElement(AlertOctagonFilledIcon, { color: "error" }), __4("Delete this variable?", "elementor")), /* @__PURE__ */ React2.createElement(DialogContent, null, /* @__PURE__ */ React2.createElement(DialogContentText, { variant: "body2", color: "textPrimary" }, __4("All elements using", "elementor"), "\xA0", /* @__PURE__ */ React2.createElement(Typography2, { variant: "subtitle2", component: "span", sx: { lineBreak: "anywhere" } }, label), "\xA0", __4("will keep their current values, but the variable itself will be removed.", "elementor"))), /* @__PURE__ */ React2.createElement(DialogActions, null, /* @__PURE__ */ React2.createElement(Button, { color: "secondary", onClick: closeDialog }, __4("Not now", "elementor")), /* @__PURE__ */ React2.createElement(Button, { variant: "contained", color: "error", onClick: onConfirm }, __4("Delete", "elementor"))));
722
+ };
723
+
724
+ // src/components/ui/empty-state.tsx
725
+ import * as React3 from "react";
726
+ import { Button as Button2, Stack as Stack2, Typography as Typography3 } from "@elementor/ui";
727
+ import { __ as __5 } from "@wordpress/i18n";
728
+
729
+ // src/hooks/use-permissions.ts
730
+ import { useCurrentUserCapabilities } from "@elementor/editor-current-user";
731
+ var usePermissions = () => {
732
+ const { canUser } = useCurrentUserCapabilities();
733
+ return {
734
+ canAssign: () => canUser("edit_posts"),
735
+ canUnlink: () => canUser("edit_posts"),
736
+ canAdd: () => canUser("manage_options"),
737
+ canDelete: () => canUser("manage_options"),
738
+ canEdit: () => canUser("manage_options"),
739
+ canRestore: () => canUser("manage_options"),
740
+ canManageSettings: () => canUser("manage_options")
741
+ };
742
+ };
743
+
744
+ // src/components/ui/empty-state.tsx
745
+ var EmptyState = ({ icon, title, message, onAdd }) => {
746
+ const canAdd = usePermissions().canAdd();
747
+ return /* @__PURE__ */ React3.createElement(
748
+ Stack2,
749
+ {
750
+ gap: 1,
751
+ alignItems: "center",
752
+ justifyContent: "flex-start",
753
+ height: "100%",
754
+ color: "text.secondary",
755
+ sx: { p: 2.5, pt: 8, pb: 5.5 }
756
+ },
757
+ icon,
758
+ canAdd ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(Content, { title, message }), onAdd && /* @__PURE__ */ React3.createElement(Button2, { variant: "outlined", color: "secondary", size: "small", onClick: onAdd }, __5("Create a variable", "elementor"))) : /* @__PURE__ */ React3.createElement(
759
+ Content,
760
+ {
761
+ title: __5("There are no variables", "elementor"),
762
+ message: __5("With your current role, you can only connect and detach variables.", "elementor")
763
+ }
764
+ )
765
+ );
766
+ };
767
+ function Content({ title, message }) {
768
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(Typography3, { align: "center", variant: "subtitle2" }, title), /* @__PURE__ */ React3.createElement(Typography3, { align: "center", variant: "caption", maxWidth: "180px" }, message));
769
+ }
770
+
771
+ // src/components/ui/no-search-results.tsx
772
+ import * as React4 from "react";
773
+ import { Link, Stack as Stack3, Typography as Typography4 } from "@elementor/ui";
774
+ import { __ as __6 } from "@wordpress/i18n";
775
+ var NoSearchResults = ({ searchValue, onClear, icon }) => {
776
+ return /* @__PURE__ */ React4.createElement(
777
+ Stack3,
778
+ {
779
+ gap: 1,
780
+ alignItems: "center",
781
+ justifyContent: "center",
782
+ p: 2.5,
783
+ color: "text.secondary",
784
+ sx: { pb: 3.5, pt: 8 }
785
+ },
786
+ icon,
787
+ /* @__PURE__ */ React4.createElement(Typography4, { align: "center", variant: "subtitle2" }, __6("Sorry, nothing matched", "elementor"), /* @__PURE__ */ React4.createElement("br", null), "\u201C", searchValue, "\u201D."),
788
+ /* @__PURE__ */ React4.createElement(Typography4, { align: "center", variant: "caption", sx: { display: "flex", flexDirection: "column" } }, __6("Try something else.", "elementor"), /* @__PURE__ */ React4.createElement(Link, { color: "text.secondary", variant: "caption", component: "button", onClick: onClear }, __6("Clear & try again", "elementor")))
789
+ );
790
+ };
791
+
792
+ // src/components/variables-manager/hooks/use-auto-edit.ts
793
+ import { useCallback, useState } from "react";
794
+ var useAutoEdit = () => {
795
+ const [autoEditVariableId, setAutoEditVariableId] = useState(void 0);
796
+ const startAutoEdit = useCallback((variableId) => {
797
+ setAutoEditVariableId(variableId);
798
+ }, []);
799
+ const handleAutoEditComplete = useCallback(() => {
800
+ setTimeout(() => {
801
+ setAutoEditVariableId(void 0);
802
+ }, 100);
803
+ }, []);
804
+ return {
805
+ autoEditVariableId,
806
+ startAutoEdit,
807
+ handleAutoEditComplete
808
+ };
809
+ };
810
+
811
+ // src/components/variables-manager/hooks/use-error-navigation.ts
812
+ import { useCallback as useCallback2, useRef } from "react";
813
+ var useErrorNavigation = () => {
814
+ const currentIndexRef = useRef(0);
815
+ const createNavigationCallback = useCallback2(
816
+ (ids, onNavigate, onComplete) => {
817
+ return () => {
818
+ if (!ids?.length) {
819
+ return;
820
+ }
821
+ const currentIndex = currentIndexRef.current;
822
+ const currentId = ids[currentIndex];
823
+ if (currentId) {
824
+ onNavigate(currentId);
825
+ const nextIndex = currentIndex + 1;
826
+ if (nextIndex >= ids.length) {
827
+ onComplete();
828
+ currentIndexRef.current = 0;
829
+ } else {
830
+ currentIndexRef.current = nextIndex;
831
+ }
832
+ }
833
+ };
834
+ },
835
+ []
836
+ );
837
+ const resetNavigation = useCallback2(() => {
838
+ currentIndexRef.current = 0;
839
+ }, []);
840
+ return {
841
+ createNavigationCallback,
842
+ resetNavigation
843
+ };
844
+ };
845
+
846
+ // src/components/variables-manager/hooks/use-variables-manager-state.ts
847
+ import { useCallback as useCallback3, useState as useState2 } from "react";
848
+
849
+ // src/hooks/use-prop-variables.ts
850
+ import { useMemo } from "react";
851
+ import { useBoundProp } from "@elementor/editor-controls";
446
852
 
447
853
  // src/context/variable-type-context.tsx
854
+ import * as React5 from "react";
855
+ import { createContext, useContext } from "react";
448
856
  var VariableTypeContext = createContext(null);
449
857
  function VariableTypeProvider({ children, propTypeKey }) {
450
- return /* @__PURE__ */ React2.createElement(VariableTypeContext.Provider, { value: propTypeKey }, children);
858
+ return /* @__PURE__ */ React5.createElement(VariableTypeContext.Provider, { value: propTypeKey }, children);
451
859
  }
452
860
  function useVariableType() {
453
861
  const context = useContext(VariableTypeContext);
@@ -457,6 +865,12 @@ function useVariableType() {
457
865
  return getVariableType(context);
458
866
  }
459
867
 
868
+ // src/utils/filter-by-search.ts
869
+ function filterBySearch(variables, searchValue) {
870
+ const lowerSearchValue = searchValue.toLowerCase();
871
+ return variables.filter((variable) => variable.label.toLowerCase().includes(lowerSearchValue));
872
+ }
873
+
460
874
  // src/hooks/use-prop-variables.ts
461
875
  var getVariables = (includeDeleted = true) => {
462
876
  const variables = service.variables();
@@ -478,11 +892,17 @@ var useVariable = (key) => {
478
892
  var useFilteredVariables = (searchValue, propTypeKey) => {
479
893
  const baseVariables = usePropVariables(propTypeKey);
480
894
  const typeFilteredVariables = useVariableSelectionFilter(baseVariables);
481
- const searchFilteredVariables = filterVariablesBySearchValue(typeFilteredVariables, searchValue);
895
+ const searchFilteredVariables = filterBySearch(typeFilteredVariables, searchValue);
896
+ const sortedVariables = searchFilteredVariables.sort((a, b) => {
897
+ const orderA = a.order ?? Number.MAX_SAFE_INTEGER;
898
+ const orderB = b.order ?? Number.MAX_SAFE_INTEGER;
899
+ return orderA - orderB;
900
+ });
482
901
  return {
483
- list: searchFilteredVariables,
902
+ list: sortedVariables,
484
903
  hasMatches: searchFilteredVariables.length > 0,
485
- isSourceNotEmpty: typeFilteredVariables.length > 0
904
+ isSourceNotEmpty: typeFilteredVariables.length > 0,
905
+ hasNoCompatibleVariables: baseVariables.length > 0 && typeFilteredVariables.length === 0
486
906
  };
487
907
  };
488
908
  var useVariableSelectionFilter = (variables) => {
@@ -490,19 +910,28 @@ var useVariableSelectionFilter = (variables) => {
490
910
  const { propType } = useBoundProp();
491
911
  return selectionFilter ? selectionFilter(variables, propType) : variables;
492
912
  };
493
- var filterVariablesBySearchValue = (variables, searchValue) => {
494
- const lowerSearchValue = searchValue.toLowerCase();
495
- return variables.filter(({ label }) => label.toLowerCase().includes(lowerSearchValue));
496
- };
497
913
  var usePropVariables = (propKey) => {
498
914
  return useMemo(() => normalizeVariables(propKey), [propKey]);
499
915
  };
916
+ var getMatchingTypes = (propKey) => {
917
+ const matchingTypes = [];
918
+ const allTypes = getVariableTypes();
919
+ const variableType = getVariableType(propKey);
920
+ Object.entries(allTypes).forEach(([key, typeOptions]) => {
921
+ if (variableType.variableType === typeOptions.variableType) {
922
+ matchingTypes.push(key);
923
+ }
924
+ });
925
+ return matchingTypes;
926
+ };
500
927
  var normalizeVariables = (propKey) => {
501
928
  const variables = getVariables(false);
502
- return Object.entries(variables).filter(([, variable]) => variable.type === propKey).map(([key, { label, value }]) => ({
929
+ const matchingTypes = getMatchingTypes(propKey);
930
+ return Object.entries(variables).filter(([, variable]) => matchingTypes.includes(variable.type)).map(([key, { label, value, order }]) => ({
503
931
  key,
504
932
  label,
505
- value
933
+ value,
934
+ order
506
935
  }));
507
936
  };
508
937
  var extractId = ({ id: id2 }) => id2;
@@ -519,87 +948,195 @@ var restoreVariable = (restoreId, label, value) => {
519
948
  return service.restore(restoreId, label, value).then(extractId);
520
949
  };
521
950
 
522
- // src/components/variables-manager/variables-manager-table.tsx
523
- import * as React7 from "react";
524
- import { createElement as createElement9, useState as useState3 } from "react";
525
- import { EllipsisWithTooltip } from "@elementor/editor-ui";
526
- import { GripVerticalIcon } from "@elementor/icons";
527
- import {
528
- IconButton as IconButton2,
529
- Stack as Stack3,
530
- Table,
531
- TableBody,
532
- TableContainer,
533
- TableHead,
534
- TableRow,
535
- UnstableSortableItem,
536
- UnstableSortableProvider
537
- } from "@elementor/ui";
538
- import { __ as __4 } from "@wordpress/i18n";
539
-
540
- // src/components/fields/label-field.tsx
541
- import * as React3 from "react";
542
- import { useState } from "react";
543
- import { TextField } from "@elementor/ui";
544
-
545
- // src/utils/validations.ts
546
- import { __ as __3 } from "@wordpress/i18n";
547
- var ERROR_MESSAGES = {
548
- MISSING_VARIABLE_NAME: __3("Give your variable a name.", "elementor"),
549
- MISSING_VARIABLE_VALUE: __3("Add a value to complete your variable.", "elementor"),
550
- INVALID_CHARACTERS: __3("Use letters, numbers, dashes (-), or underscores (_) for the name.", "elementor"),
551
- NO_NON_SPECIAL_CHARACTER: __3("Names have to include at least one non-special character.", "elementor"),
552
- VARIABLE_LABEL_MAX_LENGTH: __3("Keep names up to 50 characters.", "elementor"),
553
- DUPLICATED_LABEL: __3("This variable name already exists. Please choose a unique name.", "elementor"),
554
- UNEXPECTED_ERROR: __3("There was a glitch. Try saving your variable again.", "elementor")
951
+ // src/components/variables-manager/hooks/use-variables-manager-state.ts
952
+ var useVariablesManagerState = () => {
953
+ const [variables, setVariables] = useState2(() => getVariables(false));
954
+ const [deletedVariables, setDeletedVariables] = useState2([]);
955
+ const [isSaveDisabled, setIsSaveDisabled] = useState2(false);
956
+ const [isDirty, setIsDirty] = useState2(false);
957
+ const [isSaving, setIsSaving] = useState2(false);
958
+ const [searchValue, setSearchValue] = useState2("");
959
+ const handleOnChange = useCallback3(
960
+ (newVariables) => {
961
+ setVariables({ ...variables, ...newVariables });
962
+ setIsDirty(true);
963
+ },
964
+ [variables]
965
+ );
966
+ const createVariable2 = useCallback3((type, defaultName, defaultValue) => {
967
+ const newId = generateTempId();
968
+ const newVariable = {
969
+ id: newId,
970
+ label: defaultName.trim(),
971
+ value: defaultValue.trim(),
972
+ type
973
+ };
974
+ setVariables((prev) => ({ ...prev, [newId]: newVariable }));
975
+ setIsDirty(true);
976
+ return newId;
977
+ }, []);
978
+ const handleDeleteVariable = useCallback3((itemId) => {
979
+ setDeletedVariables((prev) => [...prev, itemId]);
980
+ setVariables((prev) => ({ ...prev, [itemId]: { ...prev[itemId], deleted: true } }));
981
+ setIsDirty(true);
982
+ }, []);
983
+ const handleSearch = (searchTerm) => {
984
+ setSearchValue(searchTerm);
985
+ };
986
+ const handleSave = useCallback3(async () => {
987
+ const originalVariables = getVariables(false);
988
+ setIsSaving(true);
989
+ const result = await service.batchSave(originalVariables, variables);
990
+ if (result.success) {
991
+ await service.load();
992
+ const updatedVariables = service.variables();
993
+ setVariables(updatedVariables);
994
+ setDeletedVariables([]);
995
+ setIsDirty(false);
996
+ }
997
+ return { success: result.success };
998
+ }, [variables]);
999
+ const filteredVariables = () => {
1000
+ const list = Object.entries(variables).map(([id2, value]) => ({ ...value, id: id2 }));
1001
+ const filtered = filterBySearch(list, searchValue);
1002
+ return Object.fromEntries(filtered.map(({ id: id2, ...rest }) => [id2, rest]));
1003
+ };
1004
+ return {
1005
+ variables: filteredVariables(),
1006
+ deletedVariables,
1007
+ isDirty,
1008
+ isSaveDisabled,
1009
+ handleOnChange,
1010
+ createVariable: createVariable2,
1011
+ handleDeleteVariable,
1012
+ handleSave,
1013
+ isSaving,
1014
+ handleSearch,
1015
+ searchValue,
1016
+ setIsSaving,
1017
+ setIsSaveDisabled
1018
+ };
555
1019
  };
556
- var VARIABLE_LABEL_MAX_LENGTH = 50;
557
- var mapServerError = (error) => {
558
- if (error?.response?.data?.code === "duplicated_label") {
1020
+
1021
+ // src/components/variables-manager/variables-manager-create-menu.tsx
1022
+ import * as React6 from "react";
1023
+ import { createElement as createElement7, useRef as useRef2 } from "react";
1024
+ import { PlusIcon } from "@elementor/icons";
1025
+ import { bindMenu, bindTrigger, IconButton, Menu, MenuItem, Typography as Typography5 } from "@elementor/ui";
1026
+ import { __ as __7 } from "@wordpress/i18n";
1027
+ var SIZE = "tiny";
1028
+ var VariableManagerCreateMenu = ({
1029
+ variables,
1030
+ onCreate,
1031
+ disabled,
1032
+ menuState
1033
+ }) => {
1034
+ const buttonRef = useRef2(null);
1035
+ const variableTypes = getVariableTypes();
1036
+ const menuOptions = Object.entries(variableTypes).filter(([, variable]) => !!variable.defaultValue).map(([key, variable]) => {
1037
+ const displayName = variable.variableType.charAt(0).toUpperCase() + variable.variableType.slice(1);
559
1038
  return {
560
- field: "label",
561
- message: ERROR_MESSAGES.DUPLICATED_LABEL
1039
+ key,
1040
+ name: displayName,
1041
+ icon: variable.icon,
1042
+ onClick: () => {
1043
+ const defaultName = getDefaultName(variables, key, variable.variableType);
1044
+ onCreate(key, defaultName, variable.defaultValue || "");
1045
+ trackVariablesManagerEvent({ action: "add", varType: variable.variableType });
1046
+ }
562
1047
  };
563
- }
564
- return void 0;
565
- };
566
- var validateLabel = (name) => {
567
- if (!name.trim()) {
568
- return ERROR_MESSAGES.MISSING_VARIABLE_NAME;
569
- }
570
- const allowedChars = /^[a-zA-Z0-9_-]+$/;
571
- if (!allowedChars.test(name)) {
572
- return ERROR_MESSAGES.INVALID_CHARACTERS;
573
- }
574
- const hasAlphanumeric = /[a-zA-Z0-9]/;
575
- if (!hasAlphanumeric.test(name)) {
576
- return ERROR_MESSAGES.NO_NON_SPECIAL_CHARACTER;
577
- }
578
- if (VARIABLE_LABEL_MAX_LENGTH < name.length) {
579
- return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
580
- }
581
- return "";
582
- };
583
- var labelHint = (name) => {
584
- const hintThreshold = VARIABLE_LABEL_MAX_LENGTH * 0.8 - 1;
585
- if (hintThreshold < name.length) {
586
- return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
587
- }
588
- return "";
1048
+ });
1049
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(
1050
+ IconButton,
1051
+ {
1052
+ ...bindTrigger(menuState),
1053
+ ref: buttonRef,
1054
+ disabled,
1055
+ size: SIZE,
1056
+ "aria-label": __7("Add variable", "elementor")
1057
+ },
1058
+ /* @__PURE__ */ React6.createElement(PlusIcon, { fontSize: SIZE })
1059
+ ), /* @__PURE__ */ React6.createElement(
1060
+ Menu,
1061
+ {
1062
+ disablePortal: true,
1063
+ MenuListProps: {
1064
+ dense: true
1065
+ },
1066
+ PaperProps: {
1067
+ elevation: 6
1068
+ },
1069
+ ...bindMenu(menuState),
1070
+ anchorEl: buttonRef.current,
1071
+ anchorOrigin: {
1072
+ vertical: "bottom",
1073
+ horizontal: "right"
1074
+ },
1075
+ transformOrigin: {
1076
+ vertical: "top",
1077
+ horizontal: "right"
1078
+ },
1079
+ "data-testid": "variable-manager-create-menu"
1080
+ },
1081
+ menuOptions.map((option) => /* @__PURE__ */ React6.createElement(
1082
+ MenuItem,
1083
+ {
1084
+ key: option.key,
1085
+ onClick: () => {
1086
+ option.onClick?.();
1087
+ menuState.close();
1088
+ },
1089
+ sx: {
1090
+ gap: 1.5
1091
+ }
1092
+ },
1093
+ createElement7(option.icon, {
1094
+ fontSize: SIZE,
1095
+ color: "action"
1096
+ }),
1097
+ /* @__PURE__ */ React6.createElement(Typography5, { variant: "caption", color: "text.primary" }, option.name)
1098
+ ))
1099
+ ));
589
1100
  };
590
- var validateValue = (value) => {
591
- if (!value.trim()) {
592
- return ERROR_MESSAGES.MISSING_VARIABLE_VALUE;
1101
+ var getDefaultName = (variables, type, baseName) => {
1102
+ const existingNames = Object.values(variables).filter((variable) => variable.type === type).map((variable) => variable.label);
1103
+ let counter = 1;
1104
+ let name = `${baseName}-${counter}`;
1105
+ while (existingNames.includes(name)) {
1106
+ counter++;
1107
+ name = `${baseName}-${counter}`;
593
1108
  }
594
- return "";
1109
+ return name;
595
1110
  };
596
1111
 
1112
+ // src/components/variables-manager/variables-manager-table.tsx
1113
+ import * as React11 from "react";
1114
+ import { createElement as createElement14, useEffect as useEffect2, useRef as useRef5 } from "react";
1115
+ import { EllipsisWithTooltip } from "@elementor/editor-ui";
1116
+ import { GripVerticalIcon } from "@elementor/icons";
1117
+ import {
1118
+ IconButton as IconButton3,
1119
+ Stack as Stack5,
1120
+ Table,
1121
+ TableBody,
1122
+ TableContainer,
1123
+ TableHead,
1124
+ TableRow,
1125
+ UnstableSortableItem,
1126
+ UnstableSortableProvider
1127
+ } from "@elementor/ui";
1128
+ import { __ as __8 } from "@wordpress/i18n";
1129
+
597
1130
  // src/components/fields/label-field.tsx
1131
+ import * as React7 from "react";
1132
+ import { useRef as useRef3, useState as useState3 } from "react";
1133
+ import { WarningInfotip } from "@elementor/editor-ui";
1134
+ import { TextField } from "@elementor/ui";
598
1135
  function isLabelEqual(a, b) {
599
1136
  return a.trim().toLowerCase() === b.trim().toLowerCase();
600
1137
  }
601
1138
  var useLabelError = (initialError) => {
602
- const [error, setError] = useState(initialError ?? { value: "", message: "" });
1139
+ const [error, setError] = useState3(initialError ?? { value: "", message: "" });
603
1140
  return {
604
1141
  labelFieldError: error,
605
1142
  setLabelFieldError: setError
@@ -612,13 +1149,17 @@ var LabelField = ({
612
1149
  id: id2,
613
1150
  onErrorChange,
614
1151
  size = "tiny",
615
- focusOnShow = false
1152
+ focusOnShow = false,
1153
+ selectOnShow = false,
1154
+ showWarningInfotip = false,
1155
+ variables
616
1156
  }) => {
617
- const [label, setLabel] = useState(value);
618
- const [errorMessage, setErrorMessage] = useState("");
1157
+ const [label, setLabel] = useState3(value);
1158
+ const [errorMessage, setErrorMessage] = useState3("");
1159
+ const fieldRef = useRef3(null);
619
1160
  const handleChange = (newValue) => {
620
1161
  setLabel(newValue);
621
- const errorMsg2 = validateLabel(newValue);
1162
+ const errorMsg2 = validateLabel(newValue, variables);
622
1163
  setErrorMessage(errorMsg2);
623
1164
  onErrorChange?.(errorMsg2);
624
1165
  onChange(isLabelEqual(newValue, error?.value ?? "") || errorMsg2 ? "" : newValue);
@@ -627,32 +1168,54 @@ var LabelField = ({
627
1168
  if (isLabelEqual(label, error?.value ?? "") && error?.message) {
628
1169
  errorMsg = error.message;
629
1170
  }
630
- return /* @__PURE__ */ React3.createElement(
1171
+ const hintMsg = !errorMsg ? labelHint(label) : "";
1172
+ const textField = /* @__PURE__ */ React7.createElement(
631
1173
  TextField,
632
1174
  {
1175
+ ref: fieldRef,
633
1176
  id: id2,
634
1177
  size,
635
1178
  fullWidth: true,
636
1179
  value: label,
637
1180
  error: !!errorMsg,
638
1181
  onChange: (e) => handleChange(e.target.value),
639
- inputProps: { maxLength: VARIABLE_LABEL_MAX_LENGTH },
1182
+ inputProps: {
1183
+ maxLength: VARIABLE_LABEL_MAX_LENGTH,
1184
+ ...selectOnShow && { onFocus: (e) => e.target.select() },
1185
+ "aria-label": "Name"
1186
+ },
640
1187
  autoFocus: focusOnShow
641
1188
  }
642
1189
  );
1190
+ if (showWarningInfotip) {
1191
+ const tooltipWidth = Math.max(240, fieldRef.current?.getBoundingClientRect().width ?? 240);
1192
+ return /* @__PURE__ */ React7.createElement(
1193
+ WarningInfotip,
1194
+ {
1195
+ open: Boolean(errorMsg || hintMsg),
1196
+ text: errorMsg || hintMsg,
1197
+ placement: "bottom-start",
1198
+ width: tooltipWidth,
1199
+ offset: [0, -15],
1200
+ ...hintMsg && { hasError: false }
1201
+ },
1202
+ textField
1203
+ );
1204
+ }
1205
+ return textField;
643
1206
  };
644
1207
 
645
- // src/components/variables-manager/variable-edit-menu.tsx
646
- import * as React4 from "react";
647
- import { createElement as createElement5 } from "react";
1208
+ // src/components/variables-manager/ui/variable-edit-menu.tsx
1209
+ import * as React8 from "react";
1210
+ import { createElement as createElement10 } from "react";
648
1211
  import { DotsVerticalIcon } from "@elementor/icons";
649
- import { bindMenu, bindTrigger, IconButton, Menu, MenuItem, usePopupState } from "@elementor/ui";
1212
+ import { bindMenu as bindMenu2, bindTrigger as bindTrigger2, IconButton as IconButton2, Menu as Menu2, MenuItem as MenuItem2, usePopupState } from "@elementor/ui";
650
1213
  var VariableEditMenu = ({ menuActions, disabled, itemId }) => {
651
1214
  const menuState = usePopupState({
652
1215
  variant: "popover"
653
1216
  });
654
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(IconButton, { ...bindTrigger(menuState), disabled, size: "tiny" }, /* @__PURE__ */ React4.createElement(DotsVerticalIcon, { fontSize: "tiny" })), /* @__PURE__ */ React4.createElement(
655
- Menu,
1217
+ return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(IconButton2, { ...bindTrigger2(menuState), disabled, size: "tiny" }, /* @__PURE__ */ React8.createElement(DotsVerticalIcon, { fontSize: "tiny" })), /* @__PURE__ */ React8.createElement(
1218
+ Menu2,
656
1219
  {
657
1220
  disablePortal: true,
658
1221
  MenuListProps: {
@@ -661,7 +1224,7 @@ var VariableEditMenu = ({ menuActions, disabled, itemId }) => {
661
1224
  PaperProps: {
662
1225
  elevation: 6
663
1226
  },
664
- ...bindMenu(menuState),
1227
+ ...bindMenu2(menuState),
665
1228
  anchorEl: menuState.anchorEl,
666
1229
  anchorOrigin: {
667
1230
  vertical: "bottom",
@@ -674,8 +1237,8 @@ var VariableEditMenu = ({ menuActions, disabled, itemId }) => {
674
1237
  open: menuState.isOpen,
675
1238
  onClose: menuState.close
676
1239
  },
677
- menuActions.map((action) => /* @__PURE__ */ React4.createElement(
678
- MenuItem,
1240
+ menuActions.map((action) => /* @__PURE__ */ React8.createElement(
1241
+ MenuItem2,
679
1242
  {
680
1243
  key: action.name,
681
1244
  onClick: () => {
@@ -687,7 +1250,7 @@ var VariableEditMenu = ({ menuActions, disabled, itemId }) => {
687
1250
  gap: 1
688
1251
  }
689
1252
  },
690
- action.icon && createElement5(action.icon, {
1253
+ action.icon && createElement10(action.icon, {
691
1254
  fontSize: "inherit"
692
1255
  }),
693
1256
  " ",
@@ -696,77 +1259,8 @@ var VariableEditMenu = ({ menuActions, disabled, itemId }) => {
696
1259
  ));
697
1260
  };
698
1261
 
699
- // src/components/variables-manager/variable-editable-cell.tsx
700
- import * as React5 from "react";
701
- import { useState as useState2 } from "react";
702
- import { ClickAwayListener, Stack as Stack2 } from "@elementor/ui";
703
- var VariableEditableCell = ({
704
- initialValue,
705
- children,
706
- editableElement,
707
- onChange,
708
- prefixElement
709
- }) => {
710
- const [value, setValue] = useState2(initialValue);
711
- const [isEditing, setIsEditing] = useState2(false);
712
- const handleDoubleClick = () => {
713
- setIsEditing(true);
714
- };
715
- const handleSave = () => {
716
- onChange(value);
717
- setIsEditing(false);
718
- };
719
- const handleKeyDown = (event) => {
720
- if (event.key === "Enter") {
721
- handleSave();
722
- } else if (event.key === "Escape") {
723
- setIsEditing(false);
724
- }
725
- if (event.key === " " && !isEditing) {
726
- event.preventDefault();
727
- setIsEditing(true);
728
- }
729
- };
730
- const handleChange = (newValue) => {
731
- setValue(newValue);
732
- };
733
- const editableContent = editableElement({ value, onChange: handleChange });
734
- if (isEditing) {
735
- return /* @__PURE__ */ React5.createElement(ClickAwayListener, { onClickAway: handleSave }, /* @__PURE__ */ React5.createElement(
736
- Stack2,
737
- {
738
- direction: "row",
739
- alignItems: "center",
740
- gap: 1,
741
- onDoubleClick: handleDoubleClick,
742
- onKeyDown: handleKeyDown,
743
- tabIndex: 0,
744
- role: "button",
745
- "aria-label": "Double click or press Space to edit"
746
- },
747
- prefixElement,
748
- editableContent
749
- ));
750
- }
751
- return /* @__PURE__ */ React5.createElement(
752
- Stack2,
753
- {
754
- direction: "row",
755
- alignItems: "center",
756
- gap: 1,
757
- onDoubleClick: handleDoubleClick,
758
- onKeyDown: handleKeyDown,
759
- tabIndex: 0,
760
- role: "button",
761
- "aria-label": "Double click or press Space to edit"
762
- },
763
- prefixElement,
764
- children
765
- );
766
- };
767
-
768
- // src/components/variables-manager/variable-table-cell.tsx
769
- import * as React6 from "react";
1262
+ // src/components/variables-manager/ui/variable-table-cell.tsx
1263
+ import * as React9 from "react";
770
1264
  import { TableCell } from "@elementor/ui";
771
1265
  var VariableTableCell = ({
772
1266
  children,
@@ -786,20 +1280,167 @@ var VariableTableCell = ({
786
1280
  ...width && { width },
787
1281
  ...sx
788
1282
  };
789
- return /* @__PURE__ */ React6.createElement(TableCell, { size: "small", padding: noPadding ? "none" : void 0, align, sx: baseSx }, children);
1283
+ return /* @__PURE__ */ React9.createElement(TableCell, { size: "small", padding: noPadding ? "none" : void 0, align, sx: baseSx }, children);
790
1284
  };
791
1285
 
1286
+ // src/components/variables-manager/variable-editable-cell.tsx
1287
+ import * as React10 from "react";
1288
+ import { useCallback as useCallback4, useEffect, useRef as useRef4, useState as useState4 } from "react";
1289
+ import { ClickAwayListener, Stack as Stack4 } from "@elementor/ui";
1290
+ var VariableEditableCell = React10.memo(
1291
+ ({
1292
+ initialValue,
1293
+ children,
1294
+ editableElement,
1295
+ onChange,
1296
+ prefixElement,
1297
+ autoEdit = false,
1298
+ onRowRef,
1299
+ onAutoEditComplete,
1300
+ gap = 1,
1301
+ fieldType
1302
+ }) => {
1303
+ const [value, setValue] = useState4(initialValue);
1304
+ const [isEditing, setIsEditing] = useState4(false);
1305
+ const { labelFieldError, setLabelFieldError } = useLabelError();
1306
+ const [valueFieldError, setValueFieldError] = useState4("");
1307
+ const rowRef = useRef4(null);
1308
+ const handleSave = useCallback4(() => {
1309
+ const hasError = fieldType === "label" && labelFieldError?.message || fieldType === "value" && valueFieldError;
1310
+ if (!hasError) {
1311
+ onChange(value);
1312
+ }
1313
+ setIsEditing(false);
1314
+ }, [value, onChange, fieldType, labelFieldError, valueFieldError]);
1315
+ useEffect(() => {
1316
+ onRowRef?.(rowRef?.current);
1317
+ }, [onRowRef]);
1318
+ useEffect(() => {
1319
+ if (autoEdit && !isEditing) {
1320
+ setIsEditing(true);
1321
+ onAutoEditComplete?.();
1322
+ }
1323
+ }, [autoEdit, isEditing, onAutoEditComplete]);
1324
+ const handleDoubleClick = () => {
1325
+ setIsEditing(true);
1326
+ };
1327
+ const handleKeyDown = (event) => {
1328
+ if (event.key === "Enter") {
1329
+ handleSave();
1330
+ } else if (event.key === "Escape") {
1331
+ setIsEditing(false);
1332
+ }
1333
+ if (event.key === " " && !isEditing) {
1334
+ event.preventDefault();
1335
+ setIsEditing(true);
1336
+ }
1337
+ };
1338
+ const handleChange = useCallback4((newValue) => {
1339
+ setValue(newValue);
1340
+ }, []);
1341
+ const handleValidationChange = useCallback4(
1342
+ (errorMsg) => {
1343
+ if (fieldType === "label") {
1344
+ setLabelFieldError({
1345
+ value,
1346
+ message: errorMsg
1347
+ });
1348
+ } else {
1349
+ setValueFieldError(errorMsg);
1350
+ }
1351
+ },
1352
+ [fieldType, value, setLabelFieldError, setValueFieldError]
1353
+ );
1354
+ let currentError;
1355
+ if (fieldType === "label") {
1356
+ currentError = labelFieldError;
1357
+ } else if (fieldType === "value") {
1358
+ currentError = { value, message: valueFieldError };
1359
+ }
1360
+ const editableContent = editableElement({
1361
+ value,
1362
+ onChange: handleChange,
1363
+ onValidationChange: handleValidationChange,
1364
+ error: currentError
1365
+ });
1366
+ if (isEditing) {
1367
+ return /* @__PURE__ */ React10.createElement(ClickAwayListener, { onClickAway: handleSave }, /* @__PURE__ */ React10.createElement(
1368
+ Stack4,
1369
+ {
1370
+ ref: rowRef,
1371
+ direction: "row",
1372
+ alignItems: "center",
1373
+ gap,
1374
+ onDoubleClick: handleDoubleClick,
1375
+ onKeyDown: handleKeyDown,
1376
+ tabIndex: 0,
1377
+ role: "button",
1378
+ "aria-label": "Double click or press Space to edit"
1379
+ },
1380
+ prefixElement,
1381
+ editableContent
1382
+ ));
1383
+ }
1384
+ return /* @__PURE__ */ React10.createElement(
1385
+ Stack4,
1386
+ {
1387
+ ref: rowRef,
1388
+ direction: "row",
1389
+ alignItems: "center",
1390
+ gap,
1391
+ onDoubleClick: handleDoubleClick,
1392
+ onKeyDown: handleKeyDown,
1393
+ tabIndex: 0,
1394
+ role: "button",
1395
+ "aria-label": "Double click or press Space to edit"
1396
+ },
1397
+ prefixElement,
1398
+ children
1399
+ );
1400
+ }
1401
+ );
1402
+
792
1403
  // src/components/variables-manager/variables-manager-table.tsx
793
- var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange }) => {
794
- const [ids, setIds] = useState3(Object.keys(variables));
1404
+ var VariablesManagerTable = ({
1405
+ menuActions,
1406
+ variables,
1407
+ onChange: handleOnChange,
1408
+ autoEditVariableId,
1409
+ onAutoEditComplete,
1410
+ onFieldError
1411
+ }) => {
1412
+ const tableContainerRef = useRef5(null);
1413
+ const variableRowRefs = useRef5(/* @__PURE__ */ new Map());
1414
+ useEffect2(() => {
1415
+ if (autoEditVariableId && tableContainerRef.current) {
1416
+ const rowElement = variableRowRefs.current.get(autoEditVariableId);
1417
+ if (rowElement) {
1418
+ setTimeout(() => {
1419
+ rowElement.scrollIntoView({
1420
+ behavior: "smooth",
1421
+ block: "center",
1422
+ inline: "nearest"
1423
+ });
1424
+ }, 100);
1425
+ }
1426
+ }
1427
+ }, [autoEditVariableId]);
1428
+ const handleRowRef = (id2) => (ref) => {
1429
+ if (ref) {
1430
+ variableRowRefs.current.set(id2, ref);
1431
+ } else {
1432
+ variableRowRefs.current.delete(id2);
1433
+ }
1434
+ };
1435
+ const ids = Object.keys(variables).sort(sortVariablesOrder(variables));
795
1436
  const rows = ids.filter((id2) => !variables[id2].deleted).map((id2) => {
796
1437
  const variable = variables[id2];
797
1438
  const variableType = getVariableType(variable.type);
798
1439
  return {
799
1440
  id: id2,
1441
+ type: variable.type,
800
1442
  name: variable.label,
801
1443
  value: variable.value,
802
- type: variable.type,
803
1444
  ...variableType
804
1445
  };
805
1446
  });
@@ -807,16 +1448,27 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
807
1448
  minWidth: 250,
808
1449
  tableLayout: "fixed"
809
1450
  };
810
- return /* @__PURE__ */ React7.createElement(TableContainer, { sx: { overflow: "initial" } }, /* @__PURE__ */ React7.createElement(Table, { sx: tableSX, "aria-label": "Variables manager list with drag and drop reordering", stickyHeader: true }, /* @__PURE__ */ React7.createElement(TableHead, null, /* @__PURE__ */ React7.createElement(TableRow, null, /* @__PURE__ */ React7.createElement(VariableTableCell, { isHeader: true, noPadding: true, width: 10, maxWidth: 10 }), /* @__PURE__ */ React7.createElement(VariableTableCell, { isHeader: true }, __4("Name", "elementor")), /* @__PURE__ */ React7.createElement(VariableTableCell, { isHeader: true }, __4("Value", "elementor")), /* @__PURE__ */ React7.createElement(VariableTableCell, { isHeader: true, noPadding: true, width: 16, maxWidth: 16 }))), /* @__PURE__ */ React7.createElement(TableBody, null, /* @__PURE__ */ React7.createElement(
1451
+ const handleReorder = (newIds) => {
1452
+ const updatedVariables = { ...variables };
1453
+ newIds.forEach((id2, index) => {
1454
+ const current = updatedVariables[id2];
1455
+ if (!current) {
1456
+ return;
1457
+ }
1458
+ updatedVariables[id2] = Object.assign({}, current, { order: index + 1 });
1459
+ });
1460
+ handleOnChange(updatedVariables);
1461
+ };
1462
+ return /* @__PURE__ */ React11.createElement(TableContainer, { ref: tableContainerRef, sx: { overflow: "initial" } }, /* @__PURE__ */ React11.createElement(Table, { sx: tableSX, "aria-label": "Variables manager list with drag and drop reordering", stickyHeader: true }, /* @__PURE__ */ React11.createElement(TableHead, null, /* @__PURE__ */ React11.createElement(TableRow, null, /* @__PURE__ */ React11.createElement(VariableTableCell, { isHeader: true, noPadding: true, width: 10, maxWidth: 10 }), /* @__PURE__ */ React11.createElement(VariableTableCell, { isHeader: true }, __8("Name", "elementor")), /* @__PURE__ */ React11.createElement(VariableTableCell, { isHeader: true }, __8("Value", "elementor")), /* @__PURE__ */ React11.createElement(VariableTableCell, { isHeader: true, noPadding: true, width: 16, maxWidth: 16 }))), /* @__PURE__ */ React11.createElement(TableBody, null, /* @__PURE__ */ React11.createElement(
811
1463
  UnstableSortableProvider,
812
1464
  {
813
1465
  value: ids,
814
- onChange: setIds,
1466
+ onChange: handleReorder,
815
1467
  variant: "static",
816
1468
  restrictAxis: true,
817
- dragOverlay: ({ children: dragOverlayChildren, ...dragOverlayProps }) => /* @__PURE__ */ React7.createElement(Table, { sx: tableSX, ...dragOverlayProps }, /* @__PURE__ */ React7.createElement(TableBody, null, dragOverlayChildren))
1469
+ dragOverlay: ({ children: dragOverlayChildren, ...dragOverlayProps }) => /* @__PURE__ */ React11.createElement(Table, { sx: tableSX, ...dragOverlayProps }, /* @__PURE__ */ React11.createElement(TableBody, null, dragOverlayChildren))
818
1470
  },
819
- rows.map((row) => /* @__PURE__ */ React7.createElement(
1471
+ rows.map((row) => /* @__PURE__ */ React11.createElement(
820
1472
  UnstableSortableItem,
821
1473
  {
822
1474
  key: row.id,
@@ -830,16 +1482,15 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
830
1482
  isDragged,
831
1483
  dropPosition,
832
1484
  setTriggerRef,
833
- isDragOverlay,
834
- isSorting,
835
- index
1485
+ isSorting
836
1486
  }) => {
837
1487
  const showIndicationBefore = showDropIndication && dropPosition === "before";
838
1488
  const showIndicationAfter = showDropIndication && dropPosition === "after";
839
- return /* @__PURE__ */ React7.createElement(
1489
+ return /* @__PURE__ */ React11.createElement(
840
1490
  TableRow,
841
1491
  {
842
1492
  ...itemProps,
1493
+ ref: handleRowRef("table-ref-" + row.id),
843
1494
  selected: isDragged,
844
1495
  sx: {
845
1496
  ...showIndicationBefore && {
@@ -864,11 +1515,10 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
864
1515
  }
865
1516
  }
866
1517
  },
867
- style: { ...itemStyle, ...triggerStyle },
868
- disableDivider: isDragOverlay || index === rows.length - 1
1518
+ style: { ...itemStyle, ...triggerStyle }
869
1519
  },
870
- /* @__PURE__ */ React7.createElement(VariableTableCell, { noPadding: true, width: 10, maxWidth: 10 }, /* @__PURE__ */ React7.createElement(
871
- IconButton2,
1520
+ /* @__PURE__ */ React11.createElement(VariableTableCell, { noPadding: true, width: 10, maxWidth: 10 }, /* @__PURE__ */ React11.createElement(
1521
+ IconButton3,
872
1522
  {
873
1523
  size: "small",
874
1524
  ref: setTriggerRef,
@@ -876,9 +1526,9 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
876
1526
  disabled: isSorting,
877
1527
  draggable: true
878
1528
  },
879
- /* @__PURE__ */ React7.createElement(GripVerticalIcon, { fontSize: "inherit" })
1529
+ /* @__PURE__ */ React11.createElement(GripVerticalIcon, { fontSize: "inherit" })
880
1530
  )),
881
- /* @__PURE__ */ React7.createElement(VariableTableCell, null, /* @__PURE__ */ React7.createElement(
1531
+ /* @__PURE__ */ React11.createElement(VariableTableCell, null, /* @__PURE__ */ React11.createElement(
882
1532
  VariableEditableCell,
883
1533
  {
884
1534
  initialValue: row.name,
@@ -890,19 +1540,36 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
890
1540
  });
891
1541
  }
892
1542
  },
893
- prefixElement: createElement9(row.icon, { fontSize: "inherit" }),
894
- editableElement: ({ value, onChange }) => /* @__PURE__ */ React7.createElement(
1543
+ prefixElement: createElement14(row.icon, { fontSize: "inherit" }),
1544
+ editableElement: ({
1545
+ value,
1546
+ onChange,
1547
+ onValidationChange,
1548
+ error
1549
+ }) => /* @__PURE__ */ React11.createElement(
895
1550
  LabelField,
896
1551
  {
897
1552
  id: "variable-label-" + row.id,
898
1553
  size: "tiny",
899
1554
  value,
900
1555
  onChange,
901
- focusOnShow: true
1556
+ onErrorChange: (errorMsg) => {
1557
+ onValidationChange?.(errorMsg);
1558
+ onFieldError?.(!!errorMsg);
1559
+ },
1560
+ error,
1561
+ focusOnShow: true,
1562
+ selectOnShow: autoEditVariableId === row.id,
1563
+ showWarningInfotip: true,
1564
+ variables
902
1565
  }
903
- )
1566
+ ),
1567
+ autoEdit: autoEditVariableId === row.id,
1568
+ onRowRef: handleRowRef(row.id),
1569
+ onAutoEditComplete: autoEditVariableId === row.id ? onAutoEditComplete : void 0,
1570
+ fieldType: "label"
904
1571
  },
905
- /* @__PURE__ */ React7.createElement(
1572
+ /* @__PURE__ */ React11.createElement(
906
1573
  EllipsisWithTooltip,
907
1574
  {
908
1575
  title: row.name,
@@ -911,7 +1578,7 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
911
1578
  row.name
912
1579
  )
913
1580
  )),
914
- /* @__PURE__ */ React7.createElement(VariableTableCell, null, /* @__PURE__ */ React7.createElement(
1581
+ /* @__PURE__ */ React11.createElement(VariableTableCell, null, /* @__PURE__ */ React11.createElement(
915
1582
  VariableEditableCell,
916
1583
  {
917
1584
  initialValue: row.value,
@@ -923,19 +1590,51 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
923
1590
  });
924
1591
  }
925
1592
  },
926
- editableElement: row.valueField
1593
+ editableElement: ({
1594
+ value,
1595
+ onChange,
1596
+ onValidationChange,
1597
+ error
1598
+ }) => row.valueField({
1599
+ ref: {
1600
+ current: variableRowRefs.current.get(
1601
+ "table-ref-" + row.id
1602
+ )
1603
+ },
1604
+ value,
1605
+ onChange,
1606
+ onPropTypeKeyChange: (type) => {
1607
+ handleOnChange({
1608
+ ...variables,
1609
+ [row.id]: { ...variables[row.id], type }
1610
+ });
1611
+ },
1612
+ propTypeKey: row.type,
1613
+ onValidationChange: (errorMsg) => {
1614
+ onValidationChange?.(errorMsg);
1615
+ onFieldError?.(!!errorMsg);
1616
+ },
1617
+ error
1618
+ }),
1619
+ onRowRef: handleRowRef(row.id),
1620
+ gap: 0.25,
1621
+ fieldType: "value"
927
1622
  },
928
1623
  row.startIcon && row.startIcon({ value: row.value }),
929
- /* @__PURE__ */ React7.createElement(
1624
+ /* @__PURE__ */ React11.createElement(
930
1625
  EllipsisWithTooltip,
931
1626
  {
932
1627
  title: row.value,
933
- sx: { border: "4px solid transparent" }
1628
+ sx: {
1629
+ border: "4px solid transparent",
1630
+ lineHeight: "1",
1631
+ pt: 0.25
1632
+ }
934
1633
  },
935
1634
  row.value
936
1635
  )
937
1636
  )),
938
- /* @__PURE__ */ React7.createElement(
1637
+ /* @__PURE__ */ React11.createElement(
939
1638
  VariableTableCell,
940
1639
  {
941
1640
  align: "right",
@@ -944,7 +1643,7 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
944
1643
  maxWidth: 16,
945
1644
  sx: { paddingInlineEnd: 1 }
946
1645
  },
947
- /* @__PURE__ */ React7.createElement(Stack3, { role: "toolbar", direction: "row", justifyContent: "flex-end" }, /* @__PURE__ */ React7.createElement(
1646
+ /* @__PURE__ */ React11.createElement(Stack5, { role: "toolbar", direction: "row", justifyContent: "flex-end" }, /* @__PURE__ */ React11.createElement(
948
1647
  VariableEditMenu,
949
1648
  {
950
1649
  menuActions,
@@ -959,6 +1658,13 @@ var VariablesManagerTable = ({ menuActions, variables, onChange: handleOnChange
959
1658
  ))
960
1659
  ))));
961
1660
  };
1661
+ function sortVariablesOrder(variables) {
1662
+ return (a, b) => {
1663
+ const orderA = variables[a]?.order ?? Number.MAX_SAFE_INTEGER;
1664
+ const orderB = variables[b]?.order ?? Number.MAX_SAFE_INTEGER;
1665
+ return orderA - orderB;
1666
+ };
1667
+ }
962
1668
 
963
1669
  // src/components/variables-manager/variables-manager-panel.tsx
964
1670
  var id = "variables-manager";
@@ -971,39 +1677,134 @@ var { panel, usePanelActions } = createPanel({
971
1677
  },
972
1678
  onClose: () => {
973
1679
  changeEditMode("edit");
974
- }
1680
+ },
1681
+ isOpenPreviousElement: true
975
1682
  });
976
1683
  function VariablesManagerPanel() {
977
1684
  const { close: closePanel } = usePanelActions();
978
- const [isDirty, setIsDirty] = useState4(false);
979
- const [variables, setVariables] = useState4(getVariables(false));
980
- const [deletedVariables, setDeletedVariables] = useState4([]);
1685
+ const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
1686
+ const createMenuState = usePopupState2({
1687
+ variant: "popover"
1688
+ });
1689
+ const {
1690
+ variables,
1691
+ isDirty,
1692
+ searchValue,
1693
+ isSaveDisabled,
1694
+ handleOnChange,
1695
+ createVariable: createVariable2,
1696
+ handleDeleteVariable,
1697
+ handleSave,
1698
+ isSaving,
1699
+ handleSearch,
1700
+ setIsSaving,
1701
+ setIsSaveDisabled
1702
+ } = useVariablesManagerState();
1703
+ const { autoEditVariableId, startAutoEdit, handleAutoEditComplete } = useAutoEdit();
1704
+ const { createNavigationCallback, resetNavigation } = useErrorNavigation();
1705
+ const [deleteConfirmation, setDeleteConfirmation] = useState5(null);
1706
+ const [serverError, setServerError] = useState5(null);
981
1707
  usePreventUnload(isDirty);
1708
+ const handleClosePanel = () => {
1709
+ if (isDirty) {
1710
+ openSaveChangesDialog();
1711
+ return;
1712
+ }
1713
+ closePanel();
1714
+ };
1715
+ const handleCreateVariable = useCallback5(
1716
+ (type, defaultName, defaultValue) => {
1717
+ const newId = createVariable2(type, defaultName, defaultValue);
1718
+ if (newId) {
1719
+ startAutoEdit(newId);
1720
+ }
1721
+ },
1722
+ [createVariable2, startAutoEdit]
1723
+ );
1724
+ const handleSaveClick = async () => {
1725
+ try {
1726
+ setServerError(null);
1727
+ resetNavigation();
1728
+ const result = await handleSave();
1729
+ trackVariablesManagerEvent({ action: "saveChanges" });
1730
+ return result;
1731
+ } catch (error) {
1732
+ const mappedError = mapServerError(error);
1733
+ const duplicatedIds = mappedError?.action?.data?.duplicatedIds;
1734
+ if (mappedError && "label" === mappedError.field) {
1735
+ if (duplicatedIds && mappedError.action) {
1736
+ mappedError.action.callback = createNavigationCallback(duplicatedIds, startAutoEdit, () => {
1737
+ setIsSaveDisabled(false);
1738
+ });
1739
+ }
1740
+ setServerError(mappedError);
1741
+ setIsSaveDisabled(true);
1742
+ resetNavigation();
1743
+ }
1744
+ return { success: false, error: mappedError };
1745
+ } finally {
1746
+ setIsSaving(false);
1747
+ }
1748
+ };
1749
+ const handleDeleteVariableWithConfirmation = useCallback5(
1750
+ (itemId) => {
1751
+ handleDeleteVariable(itemId);
1752
+ setDeleteConfirmation(null);
1753
+ },
1754
+ [handleDeleteVariable]
1755
+ );
982
1756
  const menuActions = [
983
1757
  {
984
- name: __5("Delete", "elementor"),
1758
+ name: __9("Delete", "elementor"),
985
1759
  icon: TrashIcon,
986
1760
  color: "error.main",
987
1761
  onClick: (itemId) => {
988
- setDeletedVariables([...deletedVariables, itemId]);
989
- setVariables({ ...variables, [itemId]: { ...variables[itemId], deleted: true } });
990
- setIsDirty(true);
1762
+ const variable = variables[itemId];
1763
+ if (variable) {
1764
+ setDeleteConfirmation({ id: itemId, label: variable.label });
1765
+ const variableTypeOptions = getVariableType(variable.type);
1766
+ trackVariablesManagerEvent({ action: "delete", varType: variableTypeOptions?.variableType });
1767
+ }
991
1768
  }
992
1769
  }
993
1770
  ];
994
- const handleOnChange = (newVariables) => {
995
- setVariables(newVariables);
996
- setIsDirty(true);
997
- };
998
- return /* @__PURE__ */ React8.createElement(ThemeProvider, null, /* @__PURE__ */ React8.createElement(ErrorBoundary, { fallback: /* @__PURE__ */ React8.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React8.createElement(Panel, null, /* @__PURE__ */ React8.createElement(PanelHeader, null, /* @__PURE__ */ React8.createElement(Stack4, { width: "100%", direction: "column", alignItems: "center" }, /* @__PURE__ */ React8.createElement(Stack4, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React8.createElement(Stack4, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React8.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React8.createElement(ColorFilterIcon, { fontSize: "inherit" }), __5("Variable Manager", "elementor"))), /* @__PURE__ */ React8.createElement(
999
- CloseButton,
1771
+ const hasVariables = Object.values(variables).some((variable) => !variable.deleted);
1772
+ return /* @__PURE__ */ React12.createElement(ThemeProvider, null, /* @__PURE__ */ React12.createElement(Panel, null, /* @__PURE__ */ React12.createElement(
1773
+ PanelHeader,
1000
1774
  {
1001
- sx: { marginLeft: "auto" },
1002
- onClose: () => {
1003
- closePanel();
1775
+ sx: {
1776
+ height: "unset"
1004
1777
  }
1005
- }
1006
- )), /* @__PURE__ */ React8.createElement(Divider, { sx: { width: "100%" } }))), /* @__PURE__ */ React8.createElement(
1778
+ },
1779
+ /* @__PURE__ */ React12.createElement(Stack6, { width: "100%", direction: "column", alignItems: "center" }, /* @__PURE__ */ React12.createElement(Stack6, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React12.createElement(Stack6, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React12.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React12.createElement(ColorFilterIcon, { fontSize: "inherit" }), __9("Variables Manager", "elementor"))), /* @__PURE__ */ React12.createElement(Stack6, { direction: "row", gap: 0.5, alignItems: "center" }, /* @__PURE__ */ React12.createElement(
1780
+ VariableManagerCreateMenu,
1781
+ {
1782
+ onCreate: handleCreateVariable,
1783
+ variables,
1784
+ menuState: createMenuState
1785
+ }
1786
+ ), /* @__PURE__ */ React12.createElement(
1787
+ CloseButton,
1788
+ {
1789
+ "aria-label": "Close",
1790
+ slotProps: { icon: { fontSize: SIZE } },
1791
+ onClick: () => {
1792
+ handleClosePanel();
1793
+ }
1794
+ }
1795
+ ))), /* @__PURE__ */ React12.createElement(Stack6, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React12.createElement(
1796
+ SearchField,
1797
+ {
1798
+ sx: {
1799
+ display: "flex",
1800
+ flex: 1
1801
+ },
1802
+ placeholder: __9("Search", "elementor"),
1803
+ value: searchValue,
1804
+ onSearch: handleSearch
1805
+ }
1806
+ )), /* @__PURE__ */ React12.createElement(Divider, { sx: { width: "100%" } }))
1807
+ ), /* @__PURE__ */ React12.createElement(
1007
1808
  PanelBody,
1008
1809
  {
1009
1810
  sx: {
@@ -1012,20 +1813,116 @@ function VariablesManagerPanel() {
1012
1813
  height: "100%"
1013
1814
  }
1014
1815
  },
1015
- /* @__PURE__ */ React8.createElement(
1816
+ hasVariables && /* @__PURE__ */ React12.createElement(
1016
1817
  VariablesManagerTable,
1017
1818
  {
1018
1819
  menuActions,
1019
1820
  variables,
1020
- onChange: handleOnChange
1821
+ onChange: handleOnChange,
1822
+ autoEditVariableId,
1823
+ onAutoEditComplete: handleAutoEditComplete,
1824
+ onFieldError: setIsSaveDisabled
1825
+ }
1826
+ ),
1827
+ !hasVariables && searchValue && /* @__PURE__ */ React12.createElement(
1828
+ NoSearchResults,
1829
+ {
1830
+ searchValue,
1831
+ onClear: () => handleSearch(""),
1832
+ icon: /* @__PURE__ */ React12.createElement(ColorFilterIcon, { fontSize: "large" })
1833
+ }
1834
+ ),
1835
+ !hasVariables && !searchValue && /* @__PURE__ */ React12.createElement(
1836
+ EmptyState,
1837
+ {
1838
+ title: __9("Create your first variable", "elementor"),
1839
+ message: __9(
1840
+ "Variables are saved attributes that you can apply anywhere on your site.",
1841
+ "elementor"
1842
+ ),
1843
+ icon: /* @__PURE__ */ React12.createElement(ColorFilterIcon, { fontSize: "large" }),
1844
+ onAdd: createMenuState.open
1021
1845
  }
1022
1846
  )
1023
- ), /* @__PURE__ */ React8.createElement(PanelFooter, null, /* @__PURE__ */ React8.createElement(Button, { fullWidth: true, size: "small", color: "global", variant: "contained", disabled: !isDirty }, __5("Save changes", "elementor"))))));
1847
+ ), /* @__PURE__ */ React12.createElement(PanelFooter, null, /* @__PURE__ */ React12.createElement(
1848
+ Infotip,
1849
+ {
1850
+ placement: "right",
1851
+ open: !!serverError,
1852
+ content: serverError ? /* @__PURE__ */ React12.createElement(
1853
+ Alert,
1854
+ {
1855
+ severity: serverError.severity ?? "error",
1856
+ action: serverError.action?.label ? /* @__PURE__ */ React12.createElement(AlertAction, { onClick: serverError.action.callback }, serverError.action.label) : void 0,
1857
+ onClose: !serverError.action?.label ? () => {
1858
+ setServerError(null);
1859
+ setIsSaveDisabled(false);
1860
+ } : void 0,
1861
+ icon: serverError.IconComponent ? /* @__PURE__ */ React12.createElement(serverError.IconComponent, null) : /* @__PURE__ */ React12.createElement(AlertTriangleFilledIcon2, null)
1862
+ },
1863
+ /* @__PURE__ */ React12.createElement(AlertTitle, null, serverError.message),
1864
+ serverError.action?.message
1865
+ ) : null,
1866
+ arrow: false,
1867
+ slotProps: {
1868
+ popper: {
1869
+ modifiers: [
1870
+ {
1871
+ name: "offset",
1872
+ options: { offset: [-10, 10] }
1873
+ }
1874
+ ]
1875
+ }
1876
+ }
1877
+ },
1878
+ /* @__PURE__ */ React12.createElement(
1879
+ Button3,
1880
+ {
1881
+ fullWidth: true,
1882
+ size: "small",
1883
+ color: "global",
1884
+ variant: "contained",
1885
+ disabled: isSaveDisabled || !isDirty || isSaving,
1886
+ onClick: handleSaveClick,
1887
+ loading: isSaving
1888
+ },
1889
+ __9("Save changes", "elementor")
1890
+ )
1891
+ ))), deleteConfirmation && /* @__PURE__ */ React12.createElement(
1892
+ DeleteConfirmationDialog,
1893
+ {
1894
+ open: true,
1895
+ label: deleteConfirmation.label,
1896
+ onConfirm: () => handleDeleteVariableWithConfirmation(deleteConfirmation.id),
1897
+ closeDialog: () => setDeleteConfirmation(null)
1898
+ }
1899
+ ), isSaveChangesDialogOpen && /* @__PURE__ */ React12.createElement(SaveChangesDialog, null, /* @__PURE__ */ React12.createElement(SaveChangesDialog.Title, { onClose: closeSaveChangesDialog }, __9("You have unsaved changes", "elementor")), /* @__PURE__ */ React12.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React12.createElement(SaveChangesDialog.ContentText, null, __9("To avoid losing your updates, save your changes before leaving.", "elementor"))), /* @__PURE__ */ React12.createElement(
1900
+ SaveChangesDialog.Actions,
1901
+ {
1902
+ actions: {
1903
+ discard: {
1904
+ label: __9("Discard", "elementor"),
1905
+ action: () => {
1906
+ closeSaveChangesDialog();
1907
+ closePanel();
1908
+ }
1909
+ },
1910
+ confirm: {
1911
+ label: __9("Save", "elementor"),
1912
+ action: async () => {
1913
+ const result = await handleSaveClick();
1914
+ closeSaveChangesDialog();
1915
+ if (result?.success) {
1916
+ closePanel();
1917
+ }
1918
+ }
1919
+ }
1920
+ }
1921
+ }
1922
+ )));
1024
1923
  }
1025
- var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React8.createElement(IconButton3, { size: "small", color: "secondary", onClick: onClose, "aria-label": "Close", ...props }, /* @__PURE__ */ React8.createElement(XIcon, { fontSize: "small" }));
1026
- var ErrorBoundaryFallback = () => /* @__PURE__ */ React8.createElement(Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React8.createElement(Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React8.createElement("strong", null, __5("Something went wrong", "elementor"))));
1027
1924
  var usePreventUnload = (isDirty) => {
1028
- useEffect(() => {
1925
+ useEffect3(() => {
1029
1926
  const handleBeforeUnload = (event) => {
1030
1927
  if (isDirty) {
1031
1928
  event.preventDefault();
@@ -1039,21 +1936,21 @@ var usePreventUnload = (isDirty) => {
1039
1936
  };
1040
1937
 
1041
1938
  // src/controls/variable-control.tsx
1042
- import * as React32 from "react";
1939
+ import * as React31 from "react";
1043
1940
  import { useBoundProp as useBoundProp11 } from "@elementor/editor-controls";
1044
1941
 
1045
1942
  // src/components/ui/variable/assigned-variable.tsx
1046
- import { useId, useRef } from "react";
1047
- import * as React21 from "react";
1943
+ import { useId, useRef as useRef6 } from "react";
1944
+ import * as React22 from "react";
1048
1945
  import { useBoundProp as useBoundProp6 } from "@elementor/editor-controls";
1049
1946
  import { ColorFilterIcon as ColorFilterIcon3 } from "@elementor/icons";
1050
- import { bindPopover, bindTrigger as bindTrigger2, Box as Box5, Popover, usePopupState as usePopupState2 } from "@elementor/ui";
1947
+ import { bindPopover, bindTrigger as bindTrigger3, Box as Box4, Popover, usePopupState as usePopupState3 } from "@elementor/ui";
1051
1948
 
1052
1949
  // src/utils/unlink-variable.ts
1053
1950
  function transformValueBeforeUnlink(variable, propTypeKey) {
1054
1951
  const { valueTransformer } = getVariableType(propTypeKey);
1055
1952
  if (valueTransformer) {
1056
- return valueTransformer(variable.value);
1953
+ return valueTransformer(variable);
1057
1954
  }
1058
1955
  return variable.value;
1059
1956
  }
@@ -1066,96 +1963,92 @@ function createUnlinkHandler(variable, propTypeKey, setValue) {
1066
1963
  }
1067
1964
 
1068
1965
  // src/components/variable-selection-popover.tsx
1069
- import * as React19 from "react";
1070
- import { useState as useState10 } from "react";
1966
+ import * as React20 from "react";
1967
+ import { useState as useState11 } from "react";
1071
1968
  import { isExperimentActive } from "@elementor/editor-v1-adapters";
1072
1969
 
1073
1970
  // src/context/variable-selection-popover.context.tsx
1074
- import * as React9 from "react";
1075
- import { createContext as createContext2, useContext as useContext2, useState as useState5 } from "react";
1076
- import { Box as Box2 } from "@elementor/ui";
1971
+ import * as React13 from "react";
1972
+ import { createContext as createContext2, useContext as useContext2, useState as useState6 } from "react";
1973
+ import { Box } from "@elementor/ui";
1077
1974
  var PopoverContentRefContext = createContext2(null);
1078
1975
  var PopoverContentRefContextProvider = ({ children }) => {
1079
- const [anchorRef, setAnchorRef] = useState5(null);
1080
- return /* @__PURE__ */ React9.createElement(PopoverContentRefContext.Provider, { value: anchorRef }, /* @__PURE__ */ React9.createElement(Box2, { ref: setAnchorRef }, children));
1976
+ const [anchorRef, setAnchorRef] = useState6(null);
1977
+ return /* @__PURE__ */ React13.createElement(PopoverContentRefContext.Provider, { value: anchorRef }, /* @__PURE__ */ React13.createElement(Box, { ref: setAnchorRef }, children));
1081
1978
  };
1082
1979
  var usePopoverContentRef = () => {
1083
1980
  return useContext2(PopoverContentRefContext);
1084
1981
  };
1085
1982
 
1086
- // src/hooks/use-permissions.ts
1087
- import { useCurrentUserCapabilities } from "@elementor/editor-current-user";
1088
- var usePermissions = () => {
1089
- const { canUser } = useCurrentUserCapabilities();
1090
- return {
1091
- canAssign: () => canUser("edit_posts"),
1092
- canUnlink: () => canUser("edit_posts"),
1093
- canAdd: () => canUser("manage_options"),
1094
- canDelete: () => canUser("manage_options"),
1095
- canEdit: () => canUser("manage_options"),
1096
- canRestore: () => canUser("manage_options"),
1097
- canManageSettings: () => canUser("manage_options")
1098
- };
1099
- };
1100
-
1101
1983
  // src/components/variable-creation.tsx
1102
- import * as React11 from "react";
1103
- import { useState as useState6 } from "react";
1104
- import { PopoverContent, useBoundProp as useBoundProp3 } from "@elementor/editor-controls";
1984
+ import * as React15 from "react";
1985
+ import { useState as useState7 } from "react";
1986
+ import { PopoverContent, useBoundProp as useBoundProp4 } from "@elementor/editor-controls";
1105
1987
  import { PopoverBody } from "@elementor/editor-editing-panel";
1106
1988
  import { PopoverHeader } from "@elementor/editor-ui";
1107
1989
  import { ArrowLeftIcon } from "@elementor/icons";
1108
- import { Button as Button2, CardActions, Divider as Divider2, FormHelperText as FormHelperText2, IconButton as IconButton4, Typography as Typography2 } from "@elementor/ui";
1109
- import { __ as __6 } from "@wordpress/i18n";
1990
+ import { Button as Button4, CardActions, Divider as Divider2, FormHelperText as FormHelperText2, IconButton as IconButton4, Typography as Typography6 } from "@elementor/ui";
1991
+ import { __ as __10 } from "@wordpress/i18n";
1110
1992
 
1111
1993
  // src/hooks/use-initial-value.ts
1112
1994
  import { useBoundProp as useBoundProp2 } from "@elementor/editor-controls";
1113
1995
  var useInitialValue = () => {
1114
1996
  const { value: initial } = useBoundProp2();
1115
- const hasAssignedVariable2 = hasVariableType(initial?.$$type) && Boolean(initial?.value);
1116
- const variable = useVariable(hasAssignedVariable2 ? initial.value : "");
1117
- if (hasAssignedVariable2) {
1997
+ const hasAssignedVariable = hasVariableType(initial?.$$type) && Boolean(initial?.value);
1998
+ const variable = useVariable(hasAssignedVariable ? initial.value : "");
1999
+ if (hasAssignedVariable) {
1118
2000
  return variable ? variable.value : "";
1119
2001
  }
1120
2002
  return initial?.value ?? "";
1121
2003
  };
1122
2004
 
1123
- // src/utils/tracking.ts
1124
- var trackVariableEvent = ({ varType, controlPath, action }) => {
1125
- const extendedWindow = window;
1126
- const config = extendedWindow?.elementorCommon?.eventsManager?.config;
1127
- if (!config?.names?.variables?.[action]) {
1128
- return;
2005
+ // src/hooks/use-variable-bound-prop.ts
2006
+ import { useBoundProp as useBoundProp3 } from "@elementor/editor-controls";
2007
+ import { isTransformable } from "@elementor/editor-props";
2008
+ var useVariableBoundProp = () => {
2009
+ const { propTypeUtil } = useVariableType();
2010
+ const boundProp = useBoundProp3(propTypeUtil);
2011
+ return {
2012
+ ...boundProp,
2013
+ setVariableValue: (value) => resolveBoundPropAndSetValue(value, boundProp),
2014
+ variableId: boundProp.value ?? boundProp.placeholder
2015
+ };
2016
+ };
2017
+ var resolveBoundPropAndSetValue = (value, boundProp) => {
2018
+ const propValue = unwrapValue(boundProp.value);
2019
+ const placeholder = unwrapValue(boundProp.placeholder);
2020
+ const newValue = unwrapValue(value);
2021
+ if (!propValue && placeholder === newValue) {
2022
+ return boundProp.setValue(null);
1129
2023
  }
1130
- const name = config.names.variables[action];
1131
- extendedWindow.elementorCommon?.eventsManager?.dispatchEvent(name, {
1132
- location: config.locations.variables,
1133
- secondaryLocation: config.secondaryLocations.variablesPopover,
1134
- trigger: config.triggers.click,
1135
- var_type: varType,
1136
- control_path: controlPath,
1137
- action_type: name
1138
- });
2024
+ return boundProp.setValue(value);
2025
+ };
2026
+ var unwrapValue = (input) => {
2027
+ if (isTransformable(input)) {
2028
+ return input.value;
2029
+ }
2030
+ return input;
1139
2031
  };
1140
2032
 
1141
2033
  // src/components/ui/form-field.tsx
1142
- import * as React10 from "react";
2034
+ import * as React14 from "react";
1143
2035
  import { FormHelperText, FormLabel, Grid } from "@elementor/ui";
1144
2036
  var FormField = ({ id: id2, label, errorMsg, noticeMsg, children }) => {
1145
- return /* @__PURE__ */ React10.createElement(Grid, { container: true, gap: 0.75, alignItems: "center" }, /* @__PURE__ */ React10.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React10.createElement(FormLabel, { htmlFor: id2, size: "tiny" }, label)), /* @__PURE__ */ React10.createElement(Grid, { item: true, xs: 12 }, children, errorMsg && /* @__PURE__ */ React10.createElement(FormHelperText, { error: true }, errorMsg), noticeMsg && /* @__PURE__ */ React10.createElement(FormHelperText, null, noticeMsg)));
2037
+ return /* @__PURE__ */ React14.createElement(Grid, { container: true, gap: 0.75, alignItems: "center" }, /* @__PURE__ */ React14.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React14.createElement(FormLabel, { htmlFor: id2, size: "tiny" }, label)), /* @__PURE__ */ React14.createElement(Grid, { item: true, xs: 12 }, children, errorMsg && /* @__PURE__ */ React14.createElement(FormHelperText, { error: true }, errorMsg), noticeMsg && /* @__PURE__ */ React14.createElement(FormHelperText, null, noticeMsg)));
1146
2038
  };
1147
2039
 
1148
2040
  // src/components/variable-creation.tsx
1149
- var SIZE = "tiny";
2041
+ var SIZE2 = "tiny";
1150
2042
  var VariableCreation = ({ onGoBack, onClose }) => {
1151
2043
  const { icon: VariableIcon, valueField: ValueField, variableType, propTypeUtil } = useVariableType();
1152
- const { setValue: setVariable, path } = useBoundProp3(propTypeUtil);
1153
- const { propType } = useBoundProp3();
2044
+ const { setVariableValue: setVariable, path } = useVariableBoundProp();
2045
+ const { propType } = useBoundProp4();
1154
2046
  const initialValue = useInitialValue();
1155
- const [value, setValue] = useState6(initialValue);
1156
- const [label, setLabel] = useState6("");
1157
- const [errorMessage, setErrorMessage] = useState6("");
1158
- const [valueFieldError, setValueFieldError] = useState6("");
2047
+ const [value, setValue] = useState7(initialValue);
2048
+ const [label, setLabel] = useState7("");
2049
+ const [errorMessage, setErrorMessage] = useState7("");
2050
+ const [valueFieldError, setValueFieldError] = useState7("");
2051
+ const [propTypeKey, setPropTypeKey] = useState7(propTypeUtil.key);
1159
2052
  const { labelFieldError, setLabelFieldError } = useLabelError();
1160
2053
  const resetFields = () => {
1161
2054
  setValue("");
@@ -1171,7 +2064,7 @@ var VariableCreation = ({ onGoBack, onClose }) => {
1171
2064
  createVariable({
1172
2065
  value,
1173
2066
  label,
1174
- type: propTypeUtil.key
2067
+ type: propTypeKey
1175
2068
  }).then((key) => {
1176
2069
  setVariable(key);
1177
2070
  closePopover();
@@ -1206,22 +2099,22 @@ var VariableCreation = ({ onGoBack, onClose }) => {
1206
2099
  return !!errorMessage;
1207
2100
  };
1208
2101
  const isSubmitDisabled = hasEmptyFields() || hasErrors();
1209
- return /* @__PURE__ */ React11.createElement(PopoverBody, { height: "auto" }, /* @__PURE__ */ React11.createElement(
2102
+ return /* @__PURE__ */ React15.createElement(PopoverBody, { height: "auto" }, /* @__PURE__ */ React15.createElement(
1210
2103
  PopoverHeader,
1211
2104
  {
1212
- icon: /* @__PURE__ */ React11.createElement(React11.Fragment, null, onGoBack && /* @__PURE__ */ React11.createElement(IconButton4, { size: SIZE, "aria-label": __6("Go Back", "elementor"), onClick: onGoBack }, /* @__PURE__ */ React11.createElement(ArrowLeftIcon, { fontSize: SIZE })), /* @__PURE__ */ React11.createElement(VariableIcon, { fontSize: SIZE })),
1213
- title: __6("Create variable", "elementor"),
2105
+ icon: /* @__PURE__ */ React15.createElement(React15.Fragment, null, onGoBack && /* @__PURE__ */ React15.createElement(IconButton4, { size: SIZE2, "aria-label": __10("Go Back", "elementor"), onClick: onGoBack }, /* @__PURE__ */ React15.createElement(ArrowLeftIcon, { fontSize: SIZE2 })), /* @__PURE__ */ React15.createElement(VariableIcon, { fontSize: SIZE2 })),
2106
+ title: __10("Create variable", "elementor"),
1214
2107
  onClose: closePopover
1215
2108
  }
1216
- ), /* @__PURE__ */ React11.createElement(Divider2, null), /* @__PURE__ */ React11.createElement(PopoverContent, { p: 2 }, /* @__PURE__ */ React11.createElement(
2109
+ ), /* @__PURE__ */ React15.createElement(Divider2, null), /* @__PURE__ */ React15.createElement(PopoverContent, { p: 2 }, /* @__PURE__ */ React15.createElement(
1217
2110
  FormField,
1218
2111
  {
1219
2112
  id: "variable-label",
1220
- label: __6("Name", "elementor"),
2113
+ label: __10("Name", "elementor"),
1221
2114
  errorMsg: labelFieldError?.message,
1222
2115
  noticeMsg: labelHint(label)
1223
2116
  },
1224
- /* @__PURE__ */ React11.createElement(
2117
+ /* @__PURE__ */ React15.createElement(
1225
2118
  LabelField,
1226
2119
  {
1227
2120
  id: "variable-label",
@@ -1239,61 +2132,49 @@ var VariableCreation = ({ onGoBack, onClose }) => {
1239
2132
  }
1240
2133
  }
1241
2134
  )
1242
- ), /* @__PURE__ */ React11.createElement(FormField, { errorMsg: valueFieldError, label: __6("Value", "elementor") }, /* @__PURE__ */ React11.createElement(Typography2, { variant: "h5" }, /* @__PURE__ */ React11.createElement(
2135
+ ), /* @__PURE__ */ React15.createElement(FormField, { errorMsg: valueFieldError, label: __10("Value", "elementor") }, /* @__PURE__ */ React15.createElement(Typography6, { variant: "h5", id: "variable-value-wrapper" }, /* @__PURE__ */ React15.createElement(
1243
2136
  ValueField,
1244
2137
  {
1245
2138
  value,
2139
+ onPropTypeKeyChange: (key) => setPropTypeKey(key),
1246
2140
  onChange: (newValue) => {
1247
2141
  setValue(newValue);
1248
2142
  setErrorMessage("");
1249
2143
  setValueFieldError("");
1250
- },
1251
- onValidationChange: setValueFieldError,
1252
- propType
1253
- }
1254
- ))), errorMessage && /* @__PURE__ */ React11.createElement(FormHelperText2, { error: true }, errorMessage)), /* @__PURE__ */ React11.createElement(CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React11.createElement(Button2, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleCreateAndTrack }, __6("Create", "elementor"))));
1255
- };
1256
-
1257
- // src/components/variable-edit.tsx
1258
- import * as React14 from "react";
1259
- import { useEffect as useEffect2, useState as useState8 } from "react";
1260
- import { PopoverContent as PopoverContent2, useBoundProp as useBoundProp4 } from "@elementor/editor-controls";
1261
- import { useSuppressedMessage } from "@elementor/editor-current-user";
1262
- import { PopoverBody as PopoverBody2 } from "@elementor/editor-editing-panel";
1263
- import { PopoverHeader as PopoverHeader2 } from "@elementor/editor-ui";
1264
- import { ArrowLeftIcon as ArrowLeftIcon2, TrashIcon as TrashIcon2 } from "@elementor/icons";
1265
- import { Button as Button5, CardActions as CardActions2, Divider as Divider3, FormHelperText as FormHelperText3, IconButton as IconButton5, Typography as Typography5 } from "@elementor/ui";
1266
- import { __ as __9 } from "@wordpress/i18n";
1267
-
1268
- // src/components/ui/delete-confirmation-dialog.tsx
1269
- import * as React12 from "react";
1270
- import { AlertOctagonFilledIcon } from "@elementor/icons";
1271
- import {
1272
- Button as Button3,
1273
- Dialog,
1274
- DialogActions,
1275
- DialogContent,
1276
- DialogContentText,
1277
- DialogTitle,
1278
- Typography as Typography3
1279
- } from "@elementor/ui";
1280
- import { __ as __7 } from "@wordpress/i18n";
1281
- var TITLE_ID = "delete-variable-dialog";
1282
- var DeleteConfirmationDialog = ({
1283
- open,
1284
- label,
1285
- closeDialog,
1286
- onConfirm
1287
- }) => {
1288
- return /* @__PURE__ */ React12.createElement(Dialog, { open, onClose: closeDialog, "aria-labelledby": TITLE_ID, maxWidth: "xs" }, /* @__PURE__ */ React12.createElement(DialogTitle, { id: TITLE_ID, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React12.createElement(AlertOctagonFilledIcon, { color: "error" }), __7("Delete this variable?", "elementor")), /* @__PURE__ */ React12.createElement(DialogContent, null, /* @__PURE__ */ React12.createElement(DialogContentText, { variant: "body2", color: "textPrimary" }, __7("All elements using", "elementor"), "\xA0", /* @__PURE__ */ React12.createElement(Typography3, { variant: "subtitle2", component: "span", sx: { lineBreak: "anywhere" } }, label), "\xA0", __7("will keep their current values, but the variable itself will be removed.", "elementor"))), /* @__PURE__ */ React12.createElement(DialogActions, null, /* @__PURE__ */ React12.createElement(Button3, { color: "secondary", onClick: closeDialog }, __7("Not now", "elementor")), /* @__PURE__ */ React12.createElement(Button3, { variant: "contained", color: "error", onClick: onConfirm }, __7("Delete", "elementor"))));
2144
+ },
2145
+ onValidationChange: setValueFieldError,
2146
+ propType
2147
+ }
2148
+ ))), errorMessage && /* @__PURE__ */ React15.createElement(FormHelperText2, { error: true }, errorMessage)), /* @__PURE__ */ React15.createElement(CardActions, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React15.createElement(
2149
+ Button4,
2150
+ {
2151
+ id: "create-variable-button",
2152
+ size: "small",
2153
+ variant: "contained",
2154
+ disabled: isSubmitDisabled,
2155
+ onClick: handleCreateAndTrack
2156
+ },
2157
+ __10("Create", "elementor")
2158
+ )));
1289
2159
  };
1290
2160
 
2161
+ // src/components/variable-edit.tsx
2162
+ import * as React17 from "react";
2163
+ import { useEffect as useEffect4, useState as useState9 } from "react";
2164
+ import { PopoverContent as PopoverContent2, useBoundProp as useBoundProp5 } from "@elementor/editor-controls";
2165
+ import { useSuppressedMessage } from "@elementor/editor-current-user";
2166
+ import { PopoverBody as PopoverBody2 } from "@elementor/editor-editing-panel";
2167
+ import { PopoverHeader as PopoverHeader2 } from "@elementor/editor-ui";
2168
+ import { ArrowLeftIcon as ArrowLeftIcon2, TrashIcon as TrashIcon2 } from "@elementor/icons";
2169
+ import { Button as Button6, CardActions as CardActions2, Divider as Divider3, FormHelperText as FormHelperText3, IconButton as IconButton5, Tooltip, Typography as Typography8 } from "@elementor/ui";
2170
+ import { __ as __12 } from "@wordpress/i18n";
2171
+
1291
2172
  // src/components/ui/edit-confirmation-dialog.tsx
1292
- import * as React13 from "react";
1293
- import { useState as useState7 } from "react";
1294
- import { AlertTriangleFilledIcon } from "@elementor/icons";
2173
+ import * as React16 from "react";
2174
+ import { useState as useState8 } from "react";
2175
+ import { AlertTriangleFilledIcon as AlertTriangleFilledIcon3 } from "@elementor/icons";
1295
2176
  import {
1296
- Button as Button4,
2177
+ Button as Button5,
1297
2178
  Checkbox,
1298
2179
  Dialog as Dialog2,
1299
2180
  DialogActions as DialogActions2,
@@ -1301,29 +2182,29 @@ import {
1301
2182
  DialogContentText as DialogContentText2,
1302
2183
  DialogTitle as DialogTitle2,
1303
2184
  FormControlLabel,
1304
- Typography as Typography4
2185
+ Typography as Typography7
1305
2186
  } from "@elementor/ui";
1306
- import { __ as __8 } from "@wordpress/i18n";
2187
+ import { __ as __11 } from "@wordpress/i18n";
1307
2188
  var EDIT_CONFIRMATION_DIALOG_ID = "edit-confirmation-dialog";
1308
2189
  var EditConfirmationDialog = ({
1309
2190
  closeDialog,
1310
2191
  onConfirm,
1311
2192
  onSuppressMessage
1312
2193
  }) => {
1313
- const [dontShowAgain, setDontShowAgain] = useState7(false);
2194
+ const [dontShowAgain, setDontShowAgain] = useState8(false);
1314
2195
  const handleSave = () => {
1315
2196
  if (dontShowAgain) {
1316
2197
  onSuppressMessage?.();
1317
2198
  }
1318
2199
  onConfirm?.();
1319
2200
  };
1320
- return /* @__PURE__ */ React13.createElement(Dialog2, { open: true, onClose: closeDialog, maxWidth: "xs" }, /* @__PURE__ */ React13.createElement(DialogTitle2, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ React13.createElement(AlertTriangleFilledIcon, { color: "secondary" }), __8("Changes to variables go live right away.", "elementor")), /* @__PURE__ */ React13.createElement(DialogContent2, null, /* @__PURE__ */ React13.createElement(DialogContentText2, { variant: "body2", color: "textPrimary" }, __8(
2201
+ return /* @__PURE__ */ React16.createElement(Dialog2, { open: true, onClose: closeDialog, maxWidth: "xs" }, /* @__PURE__ */ React16.createElement(DialogTitle2, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ React16.createElement(AlertTriangleFilledIcon3, { color: "secondary" }), __11("Changes to variables go live right away.", "elementor")), /* @__PURE__ */ React16.createElement(DialogContent2, null, /* @__PURE__ */ React16.createElement(DialogContentText2, { variant: "body2", color: "textPrimary" }, __11(
1321
2202
  "Don't worry - all other changes you make will wait until you publish your site.",
1322
2203
  "elementor"
1323
- ))), /* @__PURE__ */ React13.createElement(DialogActions2, { sx: { justifyContent: "space-between", alignItems: "center" } }, /* @__PURE__ */ React13.createElement(
2204
+ ))), /* @__PURE__ */ React16.createElement(DialogActions2, { sx: { justifyContent: "space-between", alignItems: "center" } }, /* @__PURE__ */ React16.createElement(
1324
2205
  FormControlLabel,
1325
2206
  {
1326
- control: /* @__PURE__ */ React13.createElement(
2207
+ control: /* @__PURE__ */ React16.createElement(
1327
2208
  Checkbox,
1328
2209
  {
1329
2210
  checked: dontShowAgain,
@@ -1331,31 +2212,32 @@ var EditConfirmationDialog = ({
1331
2212
  size: "small"
1332
2213
  }
1333
2214
  ),
1334
- label: /* @__PURE__ */ React13.createElement(Typography4, { variant: "body2" }, __8("Don't show me again", "elementor"))
2215
+ label: /* @__PURE__ */ React16.createElement(Typography7, { variant: "body2" }, __11("Don't show me again", "elementor"))
1335
2216
  }
1336
- ), /* @__PURE__ */ React13.createElement("div", null, /* @__PURE__ */ React13.createElement(Button4, { color: "secondary", onClick: closeDialog }, __8("Keep editing", "elementor")), /* @__PURE__ */ React13.createElement(Button4, { variant: "contained", color: "secondary", onClick: handleSave, sx: { ml: 1 } }, __8("Save", "elementor")))));
2217
+ ), /* @__PURE__ */ React16.createElement("div", null, /* @__PURE__ */ React16.createElement(Button5, { color: "secondary", onClick: closeDialog }, __11("Keep editing", "elementor")), /* @__PURE__ */ React16.createElement(Button5, { variant: "contained", color: "secondary", onClick: handleSave, sx: { ml: 1 } }, __11("Save", "elementor")))));
1337
2218
  };
1338
2219
 
1339
2220
  // src/components/variable-edit.tsx
1340
- var SIZE2 = "tiny";
2221
+ var SIZE3 = "tiny";
2222
+ var DELETE_LABEL = __12("Delete variable", "elementor");
1341
2223
  var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1342
- const { icon: VariableIcon, valueField: ValueField, variableType, propTypeUtil } = useVariableType();
1343
- const { setValue: notifyBoundPropChange, value: assignedValue } = useBoundProp4(propTypeUtil);
1344
- const { propType } = useBoundProp4();
2224
+ const { icon: VariableIcon, valueField: ValueField, variableType } = useVariableType();
2225
+ const { setVariableValue: notifyBoundPropChange, variableId } = useVariableBoundProp();
2226
+ const { propType } = useBoundProp5();
1345
2227
  const [isMessageSuppressed, suppressMessage] = useSuppressedMessage(EDIT_CONFIRMATION_DIALOG_ID);
1346
- const [deleteConfirmation, setDeleteConfirmation] = useState8(false);
1347
- const [editConfirmation, setEditConfirmation] = useState8(false);
1348
- const [errorMessage, setErrorMessage] = useState8("");
1349
- const [valueFieldError, setValueFieldError] = useState8("");
2228
+ const [deleteConfirmation, setDeleteConfirmation] = useState9(false);
2229
+ const [editConfirmation, setEditConfirmation] = useState9(false);
2230
+ const [errorMessage, setErrorMessage] = useState9("");
2231
+ const [valueFieldError, setValueFieldError] = useState9("");
1350
2232
  const { labelFieldError, setLabelFieldError } = useLabelError();
1351
2233
  const variable = useVariable(editId);
1352
2234
  if (!variable) {
1353
2235
  throw new Error(`Global ${variableType} variable not found`);
1354
2236
  }
1355
2237
  const userPermissions = usePermissions();
1356
- const [value, setValue] = useState8(() => variable.value);
1357
- const [label, setLabel] = useState8(() => variable.label);
1358
- useEffect2(() => {
2238
+ const [value, setValue] = useState9(() => variable.value);
2239
+ const [label, setLabel] = useState9(() => variable.label);
2240
+ useEffect4(() => {
1359
2241
  styleVariablesRepository.update({
1360
2242
  [editId]: {
1361
2243
  ...variable,
@@ -1402,7 +2284,7 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1402
2284
  });
1403
2285
  };
1404
2286
  const maybeTriggerBoundPropChange = () => {
1405
- if (editId === assignedValue) {
2287
+ if (editId === variableId) {
1406
2288
  notifyBoundPropChange(editId);
1407
2289
  }
1408
2290
  };
@@ -1418,16 +2300,7 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1418
2300
  const actions = [];
1419
2301
  if (userPermissions.canDelete()) {
1420
2302
  actions.push(
1421
- /* @__PURE__ */ React14.createElement(
1422
- IconButton5,
1423
- {
1424
- key: "delete",
1425
- size: SIZE2,
1426
- "aria-label": __9("Delete", "elementor"),
1427
- onClick: handleDeleteConfirmation
1428
- },
1429
- /* @__PURE__ */ React14.createElement(TrashIcon2, { fontSize: SIZE2 })
1430
- )
2303
+ /* @__PURE__ */ React17.createElement(Tooltip, { key: "delete", placement: "top", title: DELETE_LABEL }, /* @__PURE__ */ React17.createElement(IconButton5, { size: SIZE3, onClick: handleDeleteConfirmation, "aria-label": DELETE_LABEL }, /* @__PURE__ */ React17.createElement(TrashIcon2, { fontSize: SIZE3 })))
1431
2304
  );
1432
2305
  }
1433
2306
  const hasEmptyFields = () => {
@@ -1446,31 +2319,31 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1446
2319
  return !!errorMessage;
1447
2320
  };
1448
2321
  const isSubmitDisabled = noValueChanged() || hasEmptyFields() || hasErrors();
1449
- return /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(PopoverBody2, { height: "auto" }, /* @__PURE__ */ React14.createElement(
2322
+ return /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(PopoverBody2, { height: "auto" }, /* @__PURE__ */ React17.createElement(
1450
2323
  PopoverHeader2,
1451
2324
  {
1452
- title: __9("Edit variable", "elementor"),
2325
+ title: __12("Edit variable", "elementor"),
1453
2326
  onClose,
1454
- icon: /* @__PURE__ */ React14.createElement(React14.Fragment, null, onGoBack && /* @__PURE__ */ React14.createElement(
2327
+ icon: /* @__PURE__ */ React17.createElement(React17.Fragment, null, onGoBack && /* @__PURE__ */ React17.createElement(
1455
2328
  IconButton5,
1456
2329
  {
1457
- size: SIZE2,
1458
- "aria-label": __9("Go Back", "elementor"),
2330
+ size: SIZE3,
2331
+ "aria-label": __12("Go Back", "elementor"),
1459
2332
  onClick: onGoBack
1460
2333
  },
1461
- /* @__PURE__ */ React14.createElement(ArrowLeftIcon2, { fontSize: SIZE2 })
1462
- ), /* @__PURE__ */ React14.createElement(VariableIcon, { fontSize: SIZE2 })),
2334
+ /* @__PURE__ */ React17.createElement(ArrowLeftIcon2, { fontSize: SIZE3 })
2335
+ ), /* @__PURE__ */ React17.createElement(VariableIcon, { fontSize: SIZE3 })),
1463
2336
  actions
1464
2337
  }
1465
- ), /* @__PURE__ */ React14.createElement(Divider3, null), /* @__PURE__ */ React14.createElement(PopoverContent2, { p: 2 }, /* @__PURE__ */ React14.createElement(
2338
+ ), /* @__PURE__ */ React17.createElement(Divider3, null), /* @__PURE__ */ React17.createElement(PopoverContent2, { p: 2 }, /* @__PURE__ */ React17.createElement(
1466
2339
  FormField,
1467
2340
  {
1468
2341
  id: "variable-label",
1469
- label: __9("Name", "elementor"),
2342
+ label: __12("Name", "elementor"),
1470
2343
  errorMsg: labelFieldError?.message,
1471
2344
  noticeMsg: labelHint(label)
1472
2345
  },
1473
- /* @__PURE__ */ React14.createElement(
2346
+ /* @__PURE__ */ React17.createElement(
1474
2347
  LabelField,
1475
2348
  {
1476
2349
  id: "variable-label",
@@ -1488,9 +2361,10 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1488
2361
  }
1489
2362
  }
1490
2363
  )
1491
- ), /* @__PURE__ */ React14.createElement(FormField, { errorMsg: valueFieldError, label: __9("Value", "elementor") }, /* @__PURE__ */ React14.createElement(Typography5, { variant: "h5" }, /* @__PURE__ */ React14.createElement(
2364
+ ), /* @__PURE__ */ React17.createElement(FormField, { errorMsg: valueFieldError, label: __12("Value", "elementor") }, /* @__PURE__ */ React17.createElement(Typography8, { variant: "h5" }, /* @__PURE__ */ React17.createElement(
1492
2365
  ValueField,
1493
2366
  {
2367
+ propTypeKey: variable.type,
1494
2368
  value,
1495
2369
  onChange: (newValue) => {
1496
2370
  setValue(newValue);
@@ -1500,7 +2374,7 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1500
2374
  onValidationChange: setValueFieldError,
1501
2375
  propType
1502
2376
  }
1503
- ))), errorMessage && /* @__PURE__ */ React14.createElement(FormHelperText3, { error: true }, errorMessage)), /* @__PURE__ */ React14.createElement(CardActions2, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React14.createElement(Button5, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleUpdate }, __9("Save", "elementor")))), deleteConfirmation && /* @__PURE__ */ React14.createElement(
2377
+ ))), errorMessage && /* @__PURE__ */ React17.createElement(FormHelperText3, { error: true }, errorMessage)), /* @__PURE__ */ React17.createElement(CardActions2, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React17.createElement(Button6, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleUpdate }, __12("Save", "elementor")))), deleteConfirmation && /* @__PURE__ */ React17.createElement(
1504
2378
  DeleteConfirmationDialog,
1505
2379
  {
1506
2380
  open: true,
@@ -1508,7 +2382,7 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1508
2382
  onConfirm: handleDelete,
1509
2383
  closeDialog: closeDeleteDialog()
1510
2384
  }
1511
- ), editConfirmation && !isMessageSuppressed && /* @__PURE__ */ React14.createElement(
2385
+ ), editConfirmation && !isMessageSuppressed && /* @__PURE__ */ React17.createElement(
1512
2386
  EditConfirmationDialog,
1513
2387
  {
1514
2388
  closeDialog: closeEditDialog(),
@@ -1519,26 +2393,26 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
1519
2393
  };
1520
2394
 
1521
2395
  // src/components/variables-selection.tsx
1522
- import * as React18 from "react";
1523
- import { useState as useState9 } from "react";
1524
- import { useBoundProp as useBoundProp5 } from "@elementor/editor-controls";
2396
+ import * as React19 from "react";
2397
+ import { useState as useState10 } from "react";
1525
2398
  import { PopoverBody as PopoverBody3 } from "@elementor/editor-editing-panel";
1526
- import { PopoverHeader as PopoverHeader3, PopoverMenuList, PopoverSearch } from "@elementor/editor-ui";
1527
- import { ColorFilterIcon as ColorFilterIcon2, PlusIcon, SettingsIcon } from "@elementor/icons";
1528
- import { Divider as Divider4, IconButton as IconButton7 } from "@elementor/ui";
1529
- import { __ as __13, sprintf } from "@wordpress/i18n";
2399
+ import { PopoverHeader as PopoverHeader3, PopoverMenuList, SearchField as SearchField2 } from "@elementor/editor-ui";
2400
+ import { ColorFilterIcon as ColorFilterIcon2, PlusIcon as PlusIcon2, SettingsIcon } from "@elementor/icons";
2401
+ import { Divider as Divider4, IconButton as IconButton7, Tooltip as Tooltip3 } from "@elementor/ui";
2402
+ import { __ as __14, sprintf as sprintf2 } from "@wordpress/i18n";
1530
2403
 
1531
2404
  // src/components/ui/menu-item-content.tsx
1532
- import * as React15 from "react";
2405
+ import * as React18 from "react";
1533
2406
  import { EllipsisWithTooltip as EllipsisWithTooltip2 } from "@elementor/editor-ui";
1534
2407
  import { EditIcon } from "@elementor/icons";
1535
- import { Box as Box3, IconButton as IconButton6, ListItemIcon, Typography as Typography6 } from "@elementor/ui";
1536
- import { __ as __10 } from "@wordpress/i18n";
1537
- var SIZE3 = "tiny";
2408
+ import { Box as Box2, IconButton as IconButton6, ListItemIcon, Tooltip as Tooltip2, Typography as Typography9 } from "@elementor/ui";
2409
+ import { __ as __13 } from "@wordpress/i18n";
2410
+ var SIZE4 = "tiny";
2411
+ var EDIT_LABEL = __13("Edit variable", "elementor");
1538
2412
  var MenuItemContent = ({ item }) => {
1539
2413
  const onEdit = item.onEdit;
1540
- return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(ListItemIcon, null, item.icon), /* @__PURE__ */ React15.createElement(
1541
- Box3,
2414
+ return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(ListItemIcon, null, item.icon), /* @__PURE__ */ React18.createElement(
2415
+ Box2,
1542
2416
  {
1543
2417
  sx: {
1544
2418
  flex: 1,
@@ -1548,29 +2422,29 @@ var MenuItemContent = ({ item }) => {
1548
2422
  gap: 1
1549
2423
  }
1550
2424
  },
1551
- /* @__PURE__ */ React15.createElement(
2425
+ /* @__PURE__ */ React18.createElement(
1552
2426
  EllipsisWithTooltip2,
1553
2427
  {
1554
2428
  title: item.label || item.value,
1555
- as: Typography6,
2429
+ as: Typography9,
1556
2430
  variant: "caption",
1557
2431
  color: "text.primary",
1558
2432
  sx: { marginTop: "1px", lineHeight: "2" },
1559
2433
  maxWidth: "50%"
1560
2434
  }
1561
2435
  ),
1562
- item.secondaryText && /* @__PURE__ */ React15.createElement(
2436
+ item.secondaryText && /* @__PURE__ */ React18.createElement(
1563
2437
  EllipsisWithTooltip2,
1564
2438
  {
1565
2439
  title: item.secondaryText,
1566
- as: Typography6,
2440
+ as: Typography9,
1567
2441
  variant: "caption",
1568
2442
  color: "text.tertiary",
1569
2443
  sx: { marginTop: "1px", lineHeight: "1" },
1570
2444
  maxWidth: "50%"
1571
2445
  }
1572
2446
  )
1573
- ), !!onEdit && /* @__PURE__ */ React15.createElement(
2447
+ ), !!onEdit && /* @__PURE__ */ React18.createElement(Tooltip2, { placement: "top", title: EDIT_LABEL }, /* @__PURE__ */ React18.createElement(
1574
2448
  IconButton6,
1575
2449
  {
1576
2450
  sx: { mx: 1, opacity: "0" },
@@ -1578,72 +2452,11 @@ var MenuItemContent = ({ item }) => {
1578
2452
  e.stopPropagation();
1579
2453
  onEdit(item.value);
1580
2454
  },
1581
- "aria-label": __10("Edit", "elementor")
1582
- },
1583
- /* @__PURE__ */ React15.createElement(EditIcon, { color: "action", fontSize: SIZE3 })
1584
- ));
1585
- };
1586
-
1587
- // src/components/ui/no-search-results.tsx
1588
- import * as React16 from "react";
1589
- import { Link, Stack as Stack5, Typography as Typography7 } from "@elementor/ui";
1590
- import { __ as __11 } from "@wordpress/i18n";
1591
- var NoSearchResults = ({ searchValue, onClear, icon }) => {
1592
- return /* @__PURE__ */ React16.createElement(
1593
- Stack5,
1594
- {
1595
- gap: 1,
1596
- alignItems: "center",
1597
- justifyContent: "center",
1598
- height: "100%",
1599
- p: 2.5,
1600
- color: "text.secondary",
1601
- sx: { pb: 3.5 }
1602
- },
1603
- icon,
1604
- /* @__PURE__ */ React16.createElement(Typography7, { align: "center", variant: "subtitle2" }, __11("Sorry, nothing matched", "elementor"), /* @__PURE__ */ React16.createElement("br", null), "\u201C", searchValue, "\u201D."),
1605
- /* @__PURE__ */ React16.createElement(Typography7, { align: "center", variant: "caption", sx: { display: "flex", flexDirection: "column" } }, __11("Try something else.", "elementor"), /* @__PURE__ */ React16.createElement(Link, { color: "text.secondary", variant: "caption", component: "button", onClick: onClear }, __11("Clear & try again", "elementor")))
1606
- );
1607
- };
1608
-
1609
- // src/components/ui/no-variables.tsx
1610
- import * as React17 from "react";
1611
- import { Button as Button6, Stack as Stack6, Typography as Typography8 } from "@elementor/ui";
1612
- import { __ as __12 } from "@wordpress/i18n";
1613
- var NoVariables = ({ icon, title, onAdd }) => {
1614
- const canAdd = usePermissions().canAdd();
1615
- return /* @__PURE__ */ React17.createElement(
1616
- Stack6,
1617
- {
1618
- gap: 1,
1619
- alignItems: "center",
1620
- justifyContent: "center",
1621
- height: "100%",
1622
- color: "text.secondary",
1623
- sx: { p: 2.5, pb: 5.5 }
2455
+ "aria-label": EDIT_LABEL
1624
2456
  },
1625
- icon,
1626
- canAdd ? /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(
1627
- NoVariablesContent,
1628
- {
1629
- title: title || __12("Create your first variable", "elementor"),
1630
- message: __12(
1631
- "Variables are saved attributes that you can apply anywhere on your site.",
1632
- "elementor"
1633
- )
1634
- }
1635
- ), onAdd && /* @__PURE__ */ React17.createElement(Button6, { variant: "outlined", color: "secondary", size: "small", onClick: onAdd }, __12("Create a variable", "elementor"))) : /* @__PURE__ */ React17.createElement(
1636
- NoVariablesContent,
1637
- {
1638
- title: __12("There are no variables", "elementor"),
1639
- message: __12("With your current role, you can only connect and detach variables.", "elementor")
1640
- }
1641
- )
1642
- );
2457
+ /* @__PURE__ */ React18.createElement(EditIcon, { color: "action", fontSize: SIZE4 })
2458
+ )));
1643
2459
  };
1644
- function NoVariablesContent({ title, message }) {
1645
- return /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(Typography8, { align: "center", variant: "subtitle2" }, title), /* @__PURE__ */ React17.createElement(Typography8, { align: "center", variant: "caption", maxWidth: "180px" }, message));
1646
- }
1647
2460
 
1648
2461
  // src/components/ui/styled-menu-list.tsx
1649
2462
  import { MenuList, styled as styled2 } from "@elementor/ui";
@@ -1678,15 +2491,18 @@ var VariablesStyledMenuList = styled2(MenuList)(({ theme }) => ({
1678
2491
  }));
1679
2492
 
1680
2493
  // src/components/variables-selection.tsx
1681
- var SIZE4 = "tiny";
2494
+ var SIZE5 = "tiny";
2495
+ var CREATE_LABEL = __14("Create variable", "elementor");
2496
+ var MANAGER_LABEL = __14("Variables Manager", "elementor");
1682
2497
  var VariablesSelection = ({ closePopover, onAdd, onEdit, onSettings }) => {
1683
2498
  const { icon: VariableIcon, startIcon, variableType, propTypeUtil } = useVariableType();
1684
- const { value: variable, setValue: setVariable, path } = useBoundProp5(propTypeUtil);
1685
- const [searchValue, setSearchValue] = useState9("");
2499
+ const { value: variable, setValue: setVariable, path } = useVariableBoundProp();
2500
+ const [searchValue, setSearchValue] = useState10("");
1686
2501
  const {
1687
2502
  list: variables,
1688
2503
  hasMatches: hasSearchResults,
1689
- isSourceNotEmpty: hasVariables
2504
+ isSourceNotEmpty: hasVariables,
2505
+ hasNoCompatibleVariables
1690
2506
  } = useFilteredVariables(searchValue, propTypeUtil.key);
1691
2507
  const handleSetVariable = (key) => {
1692
2508
  setVariable(key);
@@ -1708,20 +2524,46 @@ var VariablesSelection = ({ closePopover, onAdd, onEdit, onSettings }) => {
1708
2524
  const actions = [];
1709
2525
  if (onAdd) {
1710
2526
  actions.push(
1711
- /* @__PURE__ */ React18.createElement(IconButton7, { key: "add", size: SIZE4, onClick: onAddAndTrack }, /* @__PURE__ */ React18.createElement(PlusIcon, { fontSize: SIZE4 }))
2527
+ /* @__PURE__ */ React19.createElement(Tooltip3, { key: "add", placement: "top", title: CREATE_LABEL }, /* @__PURE__ */ React19.createElement(
2528
+ IconButton7,
2529
+ {
2530
+ id: "add-variable-button",
2531
+ size: SIZE5,
2532
+ onClick: onAddAndTrack,
2533
+ "aria-label": CREATE_LABEL
2534
+ },
2535
+ /* @__PURE__ */ React19.createElement(PlusIcon2, { fontSize: SIZE5 })
2536
+ ))
1712
2537
  );
1713
2538
  }
1714
2539
  if (onSettings) {
2540
+ const handleOpenManager = () => {
2541
+ onSettings();
2542
+ trackVariablesManagerEvent({
2543
+ action: "openManager",
2544
+ varType: variableType,
2545
+ controlPath: path.join(".")
2546
+ });
2547
+ };
1715
2548
  actions.push(
1716
- /* @__PURE__ */ React18.createElement(IconButton7, { key: "settings", size: SIZE4, onClick: onSettings }, /* @__PURE__ */ React18.createElement(SettingsIcon, { fontSize: SIZE4 }))
2549
+ /* @__PURE__ */ React19.createElement(Tooltip3, { key: "settings", placement: "top", title: MANAGER_LABEL }, /* @__PURE__ */ React19.createElement(
2550
+ IconButton7,
2551
+ {
2552
+ id: "variables-manager-button",
2553
+ size: SIZE5,
2554
+ onClick: handleOpenManager,
2555
+ "aria-label": MANAGER_LABEL
2556
+ },
2557
+ /* @__PURE__ */ React19.createElement(SettingsIcon, { fontSize: SIZE5 })
2558
+ ))
1717
2559
  );
1718
2560
  }
1719
- const StartIcon = startIcon || (() => /* @__PURE__ */ React18.createElement(VariableIcon, { fontSize: SIZE4 }));
2561
+ const StartIcon = startIcon || (() => /* @__PURE__ */ React19.createElement(VariableIcon, { fontSize: SIZE5 }));
1720
2562
  const items = variables.map(({ value, label, key }) => ({
1721
2563
  type: "item",
1722
2564
  value: key,
1723
2565
  label,
1724
- icon: /* @__PURE__ */ React18.createElement(StartIcon, { value }),
2566
+ icon: /* @__PURE__ */ React19.createElement(StartIcon, { value }),
1725
2567
  secondaryText: value,
1726
2568
  onEdit: onEdit ? () => onEdit?.(key) : void 0
1727
2569
  }));
@@ -1731,27 +2573,27 @@ var VariablesSelection = ({ closePopover, onAdd, onEdit, onSettings }) => {
1731
2573
  const handleClearSearch = () => {
1732
2574
  setSearchValue("");
1733
2575
  };
1734
- const noVariableTitle = sprintf(
2576
+ const noVariableTitle = sprintf2(
1735
2577
  /* translators: %s: Variable Type. */
1736
- __13("Create your first %s variable", "elementor"),
2578
+ __14("Create your first %s variable", "elementor"),
1737
2579
  variableType
1738
2580
  );
1739
- return /* @__PURE__ */ React18.createElement(PopoverBody3, null, /* @__PURE__ */ React18.createElement(
2581
+ return /* @__PURE__ */ React19.createElement(PopoverBody3, null, /* @__PURE__ */ React19.createElement(
1740
2582
  PopoverHeader3,
1741
2583
  {
1742
- title: __13("Variables", "elementor"),
1743
- icon: /* @__PURE__ */ React18.createElement(ColorFilterIcon2, { fontSize: SIZE4 }),
2584
+ title: __14("Variables", "elementor"),
2585
+ icon: /* @__PURE__ */ React19.createElement(ColorFilterIcon2, { fontSize: SIZE5 }),
1744
2586
  onClose: closePopover,
1745
2587
  actions
1746
2588
  }
1747
- ), hasVariables && /* @__PURE__ */ React18.createElement(
1748
- PopoverSearch,
2589
+ ), hasVariables && /* @__PURE__ */ React19.createElement(
2590
+ SearchField2,
1749
2591
  {
1750
2592
  value: searchValue,
1751
2593
  onSearch: handleSearch,
1752
- placeholder: __13("Search", "elementor")
2594
+ placeholder: __14("Search", "elementor")
1753
2595
  }
1754
- ), /* @__PURE__ */ React18.createElement(Divider4, null), hasVariables && hasSearchResults && /* @__PURE__ */ React18.createElement(
2596
+ ), /* @__PURE__ */ React19.createElement(Divider4, null), hasVariables && hasSearchResults && /* @__PURE__ */ React19.createElement(
1755
2597
  PopoverMenuList,
1756
2598
  {
1757
2599
  items,
@@ -1761,16 +2603,38 @@ var VariablesSelection = ({ closePopover, onAdd, onEdit, onSettings }) => {
1761
2603
  selectedValue: variable,
1762
2604
  "data-testid": `${variableType}-variables-list`,
1763
2605
  menuListTemplate: VariablesStyledMenuList,
1764
- menuItemContentTemplate: (item) => /* @__PURE__ */ React18.createElement(MenuItemContent, { item })
2606
+ menuItemContentTemplate: (item) => /* @__PURE__ */ React19.createElement(MenuItemContent, { item })
1765
2607
  }
1766
- ), !hasSearchResults && hasVariables && /* @__PURE__ */ React18.createElement(
2608
+ ), !hasSearchResults && hasVariables && /* @__PURE__ */ React19.createElement(
1767
2609
  NoSearchResults,
1768
2610
  {
1769
2611
  searchValue,
1770
2612
  onClear: handleClearSearch,
1771
- icon: /* @__PURE__ */ React18.createElement(VariableIcon, { fontSize: "large" })
2613
+ icon: /* @__PURE__ */ React19.createElement(VariableIcon, { fontSize: "large" })
2614
+ }
2615
+ ), !hasVariables && !hasNoCompatibleVariables && /* @__PURE__ */ React19.createElement(
2616
+ EmptyState,
2617
+ {
2618
+ title: noVariableTitle,
2619
+ message: __14(
2620
+ "Variables are saved attributes that you can apply anywhere on your site.",
2621
+ "elementor"
2622
+ ),
2623
+ icon: /* @__PURE__ */ React19.createElement(VariableIcon, { fontSize: "large" }),
2624
+ onAdd
2625
+ }
2626
+ ), hasNoCompatibleVariables && /* @__PURE__ */ React19.createElement(
2627
+ EmptyState,
2628
+ {
2629
+ title: __14("No compatible variables", "elementor"),
2630
+ message: __14(
2631
+ "Looks like none of your variables work with this control. Create a new variable to use it here.",
2632
+ "elementor"
2633
+ ),
2634
+ icon: /* @__PURE__ */ React19.createElement(VariableIcon, { fontSize: "large" }),
2635
+ onAdd
1772
2636
  }
1773
- ), !hasVariables && /* @__PURE__ */ React18.createElement(NoVariables, { title: noVariableTitle, icon: /* @__PURE__ */ React18.createElement(VariableIcon, { fontSize: "large" }), onAdd }));
2637
+ ));
1774
2638
  };
1775
2639
 
1776
2640
  // src/components/variable-selection-popover.tsx
@@ -1778,13 +2642,13 @@ var VIEW_LIST = "list";
1778
2642
  var VIEW_ADD = "add";
1779
2643
  var VIEW_EDIT = "edit";
1780
2644
  var VariableSelectionPopover = ({ closePopover, propTypeKey, selectedVariable }) => {
1781
- const [currentView, setCurrentView] = useState10(VIEW_LIST);
1782
- const [editId, setEditId] = useState10("");
2645
+ const [currentView, setCurrentView] = useState11(VIEW_LIST);
2646
+ const [editId, setEditId] = useState11("");
1783
2647
  const { open } = usePanelActions();
1784
2648
  const onSettingsAvailable = isExperimentActive("e_variables_manager") ? () => {
1785
2649
  open();
1786
2650
  } : void 0;
1787
- return /* @__PURE__ */ React19.createElement(VariableTypeProvider, { propTypeKey }, /* @__PURE__ */ React19.createElement(PopoverContentRefContextProvider, null, RenderView({
2651
+ return /* @__PURE__ */ React20.createElement(VariableTypeProvider, { propTypeKey }, /* @__PURE__ */ React20.createElement(PopoverContentRefContextProvider, null, RenderView({
1788
2652
  propTypeKey,
1789
2653
  currentView,
1790
2654
  selectedVariable,
@@ -1830,7 +2694,7 @@ function RenderView(props) {
1830
2694
  }
1831
2695
  };
1832
2696
  if (VIEW_LIST === props.currentView) {
1833
- return /* @__PURE__ */ React19.createElement(
2697
+ return /* @__PURE__ */ React20.createElement(
1834
2698
  VariablesSelection,
1835
2699
  {
1836
2700
  closePopover: handlers.onClose,
@@ -1841,10 +2705,10 @@ function RenderView(props) {
1841
2705
  );
1842
2706
  }
1843
2707
  if (VIEW_ADD === props.currentView) {
1844
- return /* @__PURE__ */ React19.createElement(VariableCreation, { onGoBack: handlers.onGoBack, onClose: handlers.onClose });
2708
+ return /* @__PURE__ */ React20.createElement(VariableCreation, { onGoBack: handlers.onGoBack, onClose: handlers.onClose });
1845
2709
  }
1846
2710
  if (VIEW_EDIT === props.currentView) {
1847
- return /* @__PURE__ */ React19.createElement(
2711
+ return /* @__PURE__ */ React20.createElement(
1848
2712
  VariableEdit,
1849
2713
  {
1850
2714
  editId: props.editId,
@@ -1858,25 +2722,26 @@ function RenderView(props) {
1858
2722
  }
1859
2723
 
1860
2724
  // src/components/ui/tags/assigned-tag.tsx
1861
- import * as React20 from "react";
2725
+ import * as React21 from "react";
1862
2726
  import { DetachIcon } from "@elementor/icons";
1863
- import { Box as Box4, IconButton as IconButton8, Stack as Stack7, Tooltip, Typography as Typography9, UnstableTag as Tag } from "@elementor/ui";
1864
- import { __ as __14 } from "@wordpress/i18n";
1865
- var SIZE5 = "tiny";
2727
+ import { Box as Box3, IconButton as IconButton8, Stack as Stack7, Tooltip as Tooltip4, Typography as Typography10, UnstableTag as Tag } from "@elementor/ui";
2728
+ import { __ as __15 } from "@wordpress/i18n";
2729
+ var SIZE6 = "tiny";
2730
+ var UNLINK_LABEL = __15("Unlink variable", "elementor");
1866
2731
  var AssignedTag = ({ startIcon, label, onUnlink, ...props }) => {
1867
2732
  const actions = [];
1868
2733
  if (onUnlink) {
1869
2734
  actions.push(
1870
- /* @__PURE__ */ React20.createElement(IconButton8, { key: "unlink", size: SIZE5, onClick: onUnlink, "aria-label": __14("Unlink", "elementor") }, /* @__PURE__ */ React20.createElement(DetachIcon, { fontSize: SIZE5 }))
2735
+ /* @__PURE__ */ React21.createElement(Tooltip4, { key: "unlink", title: UNLINK_LABEL, placement: "bottom" }, /* @__PURE__ */ React21.createElement(IconButton8, { size: SIZE6, onClick: onUnlink, "aria-label": UNLINK_LABEL }, /* @__PURE__ */ React21.createElement(DetachIcon, { fontSize: SIZE6 })))
1871
2736
  );
1872
2737
  }
1873
- return /* @__PURE__ */ React20.createElement(Tooltip, { title: label, placement: "top" }, /* @__PURE__ */ React20.createElement(
2738
+ return /* @__PURE__ */ React21.createElement(Tooltip4, { title: label, placement: "top" }, /* @__PURE__ */ React21.createElement(
1874
2739
  Tag,
1875
2740
  {
1876
2741
  fullWidth: true,
1877
2742
  showActionsOnHover: true,
1878
- startIcon: /* @__PURE__ */ React20.createElement(Stack7, { gap: 0.5, direction: "row", alignItems: "center" }, startIcon),
1879
- label: /* @__PURE__ */ React20.createElement(Box4, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React20.createElement(Typography9, { sx: { lineHeight: 1.34 }, variant: "caption", noWrap: true }, label)),
2743
+ startIcon: /* @__PURE__ */ React21.createElement(Stack7, { gap: 0.5, direction: "row", alignItems: "center" }, startIcon),
2744
+ label: /* @__PURE__ */ React21.createElement(Box3, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React21.createElement(Typography10, { sx: { lineHeight: 1.34 }, variant: "caption", noWrap: true }, label)),
1880
2745
  actions,
1881
2746
  ...props
1882
2747
  }
@@ -1887,23 +2752,23 @@ var AssignedTag = ({ startIcon, label, onUnlink, ...props }) => {
1887
2752
  var AssignedVariable = ({ variable, propTypeKey }) => {
1888
2753
  const { startIcon, propTypeUtil } = getVariableType(propTypeKey);
1889
2754
  const { setValue } = useBoundProp6();
1890
- const anchorRef = useRef(null);
2755
+ const anchorRef = useRef6(null);
1891
2756
  const popupId = useId();
1892
- const popupState = usePopupState2({
2757
+ const popupState = usePopupState3({
1893
2758
  variant: "popover",
1894
2759
  popupId: `elementor-variables-list-${popupId}`
1895
2760
  });
1896
2761
  const unlinkVariable = createUnlinkHandler(variable, propTypeKey, setValue);
1897
2762
  const StartIcon = startIcon || (() => null);
1898
- return /* @__PURE__ */ React21.createElement(Box5, { ref: anchorRef }, /* @__PURE__ */ React21.createElement(
2763
+ return /* @__PURE__ */ React22.createElement(Box4, { ref: anchorRef }, /* @__PURE__ */ React22.createElement(
1899
2764
  AssignedTag,
1900
2765
  {
1901
2766
  label: variable.label,
1902
- startIcon: /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(ColorFilterIcon3, { fontSize: SIZE5 }), /* @__PURE__ */ React21.createElement(StartIcon, { value: variable.value })),
2767
+ startIcon: /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(ColorFilterIcon3, { fontSize: SIZE6 }), /* @__PURE__ */ React22.createElement(StartIcon, { value: variable.value })),
1903
2768
  onUnlink: unlinkVariable,
1904
- ...bindTrigger2(popupState)
2769
+ ...bindTrigger3(popupState)
1905
2770
  }
1906
- ), /* @__PURE__ */ React21.createElement(
2771
+ ), /* @__PURE__ */ React22.createElement(
1907
2772
  Popover,
1908
2773
  {
1909
2774
  disableScrollLock: true,
@@ -1915,7 +2780,7 @@ var AssignedVariable = ({ variable, propTypeKey }) => {
1915
2780
  },
1916
2781
  ...bindPopover(popupState)
1917
2782
  },
1918
- /* @__PURE__ */ React21.createElement(
2783
+ /* @__PURE__ */ React22.createElement(
1919
2784
  VariableSelectionPopover,
1920
2785
  {
1921
2786
  selectedVariable: variable,
@@ -1927,32 +2792,33 @@ var AssignedVariable = ({ variable, propTypeKey }) => {
1927
2792
  };
1928
2793
 
1929
2794
  // src/components/ui/variable/deleted-variable.tsx
1930
- import * as React25 from "react";
1931
- import { useId as useId2, useRef as useRef2, useState as useState12 } from "react";
2795
+ import * as React26 from "react";
2796
+ import { useId as useId2, useRef as useRef7, useState as useState13 } from "react";
1932
2797
  import { useBoundProp as useBoundProp8 } from "@elementor/editor-controls";
1933
- import { Backdrop, bindPopover as bindPopover2, Box as Box7, Infotip, Popover as Popover2, usePopupState as usePopupState3 } from "@elementor/ui";
2798
+ import { Backdrop, bindPopover as bindPopover2, Box as Box6, Infotip as Infotip2, Popover as Popover2, usePopupState as usePopupState4 } from "@elementor/ui";
2799
+ import { __ as __18 } from "@wordpress/i18n";
1934
2800
 
1935
2801
  // src/components/variable-restore.tsx
1936
- import * as React22 from "react";
1937
- import { useState as useState11 } from "react";
2802
+ import * as React23 from "react";
2803
+ import { useState as useState12 } from "react";
1938
2804
  import { PopoverContent as PopoverContent3, useBoundProp as useBoundProp7 } from "@elementor/editor-controls";
1939
2805
  import { PopoverBody as PopoverBody4 } from "@elementor/editor-editing-panel";
1940
2806
  import { PopoverHeader as PopoverHeader4 } from "@elementor/editor-ui";
1941
- import { Button as Button7, CardActions as CardActions3, Divider as Divider5, FormHelperText as FormHelperText4, Typography as Typography10 } from "@elementor/ui";
1942
- import { __ as __15 } from "@wordpress/i18n";
1943
- var SIZE6 = "tiny";
2807
+ import { Button as Button7, CardActions as CardActions3, Divider as Divider5, FormHelperText as FormHelperText4, Typography as Typography11 } from "@elementor/ui";
2808
+ import { __ as __16 } from "@wordpress/i18n";
2809
+ var SIZE7 = "tiny";
1944
2810
  var VariableRestore = ({ variableId, onClose, onSubmit }) => {
1945
- const { icon: VariableIcon, valueField: ValueField, variableType, propTypeUtil } = useVariableType();
1946
- const { setValue: notifyBoundPropChange } = useBoundProp7(propTypeUtil);
2811
+ const { icon: VariableIcon, valueField: ValueField, variableType } = useVariableType();
2812
+ const { setVariableValue: notifyBoundPropChange } = useVariableBoundProp();
1947
2813
  const { propType } = useBoundProp7();
1948
2814
  const variable = useVariable(variableId);
1949
2815
  if (!variable) {
1950
2816
  throw new Error(`Global ${variableType} variable not found`);
1951
2817
  }
1952
- const [errorMessage, setErrorMessage] = useState11("");
1953
- const [valueFieldError, setValueFieldError] = useState11("");
1954
- const [label, setLabel] = useState11(variable.label);
1955
- const [value, setValue] = useState11(variable.value);
2818
+ const [errorMessage, setErrorMessage] = useState12("");
2819
+ const [valueFieldError, setValueFieldError] = useState12("");
2820
+ const [label, setLabel] = useState12(variable.label);
2821
+ const [value, setValue] = useState12(variable.value);
1956
2822
  const { labelFieldError, setLabelFieldError } = useLabelError({
1957
2823
  value: variable.label,
1958
2824
  message: ERROR_MESSAGES.DUPLICATED_LABEL
@@ -1990,22 +2856,22 @@ var VariableRestore = ({ variableId, onClose, onSubmit }) => {
1990
2856
  return !!errorMessage;
1991
2857
  };
1992
2858
  const isSubmitDisabled = noValueChanged() || hasEmptyFields() || hasErrors();
1993
- return /* @__PURE__ */ React22.createElement(PopoverContentRefContextProvider, null, /* @__PURE__ */ React22.createElement(PopoverBody4, { height: "auto" }, /* @__PURE__ */ React22.createElement(
2859
+ return /* @__PURE__ */ React23.createElement(PopoverContentRefContextProvider, null, /* @__PURE__ */ React23.createElement(PopoverBody4, { height: "auto" }, /* @__PURE__ */ React23.createElement(
1994
2860
  PopoverHeader4,
1995
2861
  {
1996
- icon: /* @__PURE__ */ React22.createElement(VariableIcon, { fontSize: SIZE6 }),
1997
- title: __15("Restore variable", "elementor"),
2862
+ icon: /* @__PURE__ */ React23.createElement(VariableIcon, { fontSize: SIZE7 }),
2863
+ title: __16("Restore variable", "elementor"),
1998
2864
  onClose
1999
2865
  }
2000
- ), /* @__PURE__ */ React22.createElement(Divider5, null), /* @__PURE__ */ React22.createElement(PopoverContent3, { p: 2 }, /* @__PURE__ */ React22.createElement(
2866
+ ), /* @__PURE__ */ React23.createElement(Divider5, null), /* @__PURE__ */ React23.createElement(PopoverContent3, { p: 2 }, /* @__PURE__ */ React23.createElement(
2001
2867
  FormField,
2002
2868
  {
2003
2869
  id: "variable-label",
2004
- label: __15("Name", "elementor"),
2870
+ label: __16("Name", "elementor"),
2005
2871
  errorMsg: labelFieldError?.message,
2006
2872
  noticeMsg: labelHint(label)
2007
2873
  },
2008
- /* @__PURE__ */ React22.createElement(
2874
+ /* @__PURE__ */ React23.createElement(
2009
2875
  LabelField,
2010
2876
  {
2011
2877
  id: "variable-label",
@@ -2023,7 +2889,7 @@ var VariableRestore = ({ variableId, onClose, onSubmit }) => {
2023
2889
  }
2024
2890
  }
2025
2891
  )
2026
- ), /* @__PURE__ */ React22.createElement(FormField, { errorMsg: valueFieldError, label: __15("Value", "elementor") }, /* @__PURE__ */ React22.createElement(Typography10, { variant: "h5" }, /* @__PURE__ */ React22.createElement(
2892
+ ), /* @__PURE__ */ React23.createElement(FormField, { errorMsg: valueFieldError, label: __16("Value", "elementor") }, /* @__PURE__ */ React23.createElement(Typography11, { variant: "h5" }, /* @__PURE__ */ React23.createElement(
2027
2893
  ValueField,
2028
2894
  {
2029
2895
  value,
@@ -2035,91 +2901,87 @@ var VariableRestore = ({ variableId, onClose, onSubmit }) => {
2035
2901
  onValidationChange: setValueFieldError,
2036
2902
  propType
2037
2903
  }
2038
- ))), errorMessage && /* @__PURE__ */ React22.createElement(FormHelperText4, { error: true }, errorMessage)), /* @__PURE__ */ React22.createElement(CardActions3, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React22.createElement(Button7, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleRestore }, __15("Restore", "elementor")))));
2904
+ ))), errorMessage && /* @__PURE__ */ React23.createElement(FormHelperText4, { error: true }, errorMessage)), /* @__PURE__ */ React23.createElement(CardActions3, { sx: { pt: 0.5, pb: 1 } }, /* @__PURE__ */ React23.createElement(Button7, { size: "small", variant: "contained", disabled: isSubmitDisabled, onClick: handleRestore }, __16("Restore", "elementor")))));
2039
2905
  };
2040
2906
 
2041
2907
  // src/components/ui/deleted-variable-alert.tsx
2042
- import * as React23 from "react";
2043
- import { useSectionWidth } from "@elementor/editor-editing-panel";
2044
- import { Alert as Alert2, AlertAction, AlertTitle, ClickAwayListener as ClickAwayListener2 } from "@elementor/ui";
2045
- import { __ as __16 } from "@wordpress/i18n";
2908
+ import * as React24 from "react";
2909
+ import { Alert as Alert2, AlertAction as AlertAction2, AlertTitle as AlertTitle2, ClickAwayListener as ClickAwayListener2, Typography as Typography12 } from "@elementor/ui";
2910
+ import { __ as __17 } from "@wordpress/i18n";
2046
2911
  var DeletedVariableAlert = ({ onClose, onUnlink, onRestore, label }) => {
2047
- const sectionWidth = useSectionWidth();
2048
- return /* @__PURE__ */ React23.createElement(ClickAwayListener2, { onClickAway: onClose }, /* @__PURE__ */ React23.createElement(
2912
+ return /* @__PURE__ */ React24.createElement(ClickAwayListener2, { onClickAway: onClose }, /* @__PURE__ */ React24.createElement(
2049
2913
  Alert2,
2050
2914
  {
2051
2915
  variant: "standard",
2052
2916
  severity: "warning",
2053
2917
  onClose,
2054
- action: /* @__PURE__ */ React23.createElement(React23.Fragment, null, onUnlink && /* @__PURE__ */ React23.createElement(AlertAction, { variant: "contained", onClick: onUnlink }, __16("Unlink", "elementor")), onRestore && /* @__PURE__ */ React23.createElement(AlertAction, { variant: "outlined", onClick: onRestore }, __16("Restore", "elementor"))),
2055
- sx: { width: sectionWidth }
2918
+ action: /* @__PURE__ */ React24.createElement(React24.Fragment, null, onUnlink && /* @__PURE__ */ React24.createElement(AlertAction2, { variant: "contained", onClick: onUnlink }, __17("Unlink", "elementor")), onRestore && /* @__PURE__ */ React24.createElement(AlertAction2, { variant: "outlined", onClick: onRestore }, __17("Restore", "elementor"))),
2919
+ sx: { maxWidth: 300 }
2056
2920
  },
2057
- /* @__PURE__ */ React23.createElement(AlertTitle, null, __16("Deleted variable", "elementor")),
2058
- __16("The variable", "elementor"),
2059
- " '",
2060
- label,
2061
- "'",
2062
- " ",
2063
- __16(
2921
+ /* @__PURE__ */ React24.createElement(AlertTitle2, null, __17("Deleted variable", "elementor")),
2922
+ /* @__PURE__ */ React24.createElement(Typography12, { variant: "body2", color: "textPrimary" }, __17("The variable", "elementor"), "\xA0'", /* @__PURE__ */ React24.createElement(Typography12, { variant: "body2", component: "span", sx: { lineBreak: "anywhere" } }, label), "'\xA0", __17(
2064
2923
  "has been deleted, but it is still referenced in this location. You may restore the variable or unlink it to assign a different value.",
2065
2924
  "elementor"
2066
- )
2925
+ ))
2067
2926
  ));
2068
2927
  };
2069
2928
 
2070
- // src/components/ui/tags/deleted-tag.tsx
2071
- import * as React24 from "react";
2072
- import { AlertTriangleFilledIcon as AlertTriangleFilledIcon2 } from "@elementor/icons";
2073
- import { Box as Box6, Chip, Tooltip as Tooltip2, Typography as Typography11 } from "@elementor/ui";
2074
- import { __ as __17 } from "@wordpress/i18n";
2075
- var DeletedTag = React24.forwardRef(({ label, onClick, ...props }, ref) => {
2076
- return /* @__PURE__ */ React24.createElement(
2077
- Chip,
2078
- {
2079
- ref,
2080
- size: "tiny",
2081
- color: "warning",
2082
- shape: "rounded",
2083
- variant: "standard",
2084
- onClick,
2085
- icon: /* @__PURE__ */ React24.createElement(AlertTriangleFilledIcon2, null),
2086
- label: /* @__PURE__ */ React24.createElement(Tooltip2, { title: label, placement: "top" }, /* @__PURE__ */ React24.createElement(Box6, { sx: { display: "flex", gap: 0.5, alignItems: "center" } }, /* @__PURE__ */ React24.createElement(Typography11, { variant: "caption", noWrap: true }, label), /* @__PURE__ */ React24.createElement(Typography11, { variant: "caption", noWrap: true, sx: { textOverflow: "initial", overflow: "visible" } }, "(", __17("deleted", "elementor"), ")"))),
2087
- sx: {
2088
- height: (theme) => theme.spacing(3.5),
2089
- borderRadius: (theme) => theme.spacing(1),
2090
- justifyContent: "flex-start",
2091
- width: "100%"
2092
- },
2093
- ...props
2094
- }
2095
- );
2096
- });
2929
+ // src/components/ui/tags/warning-variable-tag.tsx
2930
+ import * as React25 from "react";
2931
+ import { AlertTriangleFilledIcon as AlertTriangleFilledIcon4 } from "@elementor/icons";
2932
+ import { Box as Box5, Chip, Tooltip as Tooltip5, Typography as Typography13 } from "@elementor/ui";
2933
+ var WarningVariableTag = React25.forwardRef(
2934
+ ({ label, suffix, onClick, icon, ...props }, ref) => {
2935
+ const displayText = suffix ? `${label} (${suffix})` : label;
2936
+ return /* @__PURE__ */ React25.createElement(
2937
+ Chip,
2938
+ {
2939
+ ref,
2940
+ size: "tiny",
2941
+ color: "warning",
2942
+ shape: "rounded",
2943
+ variant: "standard",
2944
+ onClick,
2945
+ icon: /* @__PURE__ */ React25.createElement(AlertTriangleFilledIcon4, null),
2946
+ label: /* @__PURE__ */ React25.createElement(Tooltip5, { title: displayText, placement: "top" }, /* @__PURE__ */ React25.createElement(Box5, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React25.createElement(Typography13, { variant: "caption", noWrap: true, sx: { lineHeight: 1.34 } }, displayText))),
2947
+ sx: {
2948
+ height: (theme) => theme.spacing(3.5),
2949
+ borderRadius: (theme) => theme.spacing(1),
2950
+ justifyContent: "flex-start",
2951
+ width: "100%"
2952
+ },
2953
+ ...props
2954
+ }
2955
+ );
2956
+ }
2957
+ );
2958
+ WarningVariableTag.displayName = "WarningVariableTag";
2097
2959
 
2098
2960
  // src/components/ui/variable/deleted-variable.tsx
2099
2961
  var DeletedVariable = ({ variable, propTypeKey }) => {
2100
2962
  const { propTypeUtil } = getVariableType(propTypeKey);
2101
- const { setValue } = useBoundProp8();
2963
+ const boundProp = useBoundProp8();
2102
2964
  const userPermissions = usePermissions();
2103
- const [showInfotip, setShowInfotip] = useState12(false);
2965
+ const [showInfotip, setShowInfotip] = useState13(false);
2104
2966
  const toggleInfotip = () => setShowInfotip((prev) => !prev);
2105
2967
  const closeInfotip = () => setShowInfotip(false);
2106
- const deletedChipAnchorRef = useRef2(null);
2968
+ const deletedChipAnchorRef = useRef7(null);
2107
2969
  const popupId = useId2();
2108
- const popupState = usePopupState3({
2970
+ const popupState = usePopupState4({
2109
2971
  variant: "popover",
2110
2972
  popupId: `elementor-variables-restore-${popupId}`
2111
2973
  });
2112
2974
  const handlers = {};
2113
2975
  if (userPermissions.canUnlink()) {
2114
- handlers.onUnlink = createUnlinkHandler(variable, propTypeKey, setValue);
2976
+ handlers.onUnlink = createUnlinkHandler(variable, propTypeKey, boundProp.setValue);
2115
2977
  }
2116
2978
  if (userPermissions.canRestore()) {
2117
2979
  handlers.onRestore = () => {
2118
2980
  if (!variable.key) {
2119
2981
  return;
2120
2982
  }
2121
- restoreVariable(variable.key).then((key) => {
2122
- setValue(propTypeUtil.create(key));
2983
+ restoreVariable(variable.key).then((id2) => {
2984
+ resolveBoundPropAndSetValue(propTypeUtil.create(id2), boundProp);
2123
2985
  closeInfotip();
2124
2986
  }).catch(() => {
2125
2987
  closeInfotip();
@@ -2131,15 +2993,15 @@ var DeletedVariable = ({ variable, propTypeKey }) => {
2131
2993
  const handleRestoreWithOverrides = () => {
2132
2994
  popupState.close();
2133
2995
  };
2134
- return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(Box7, { ref: deletedChipAnchorRef }, showInfotip && /* @__PURE__ */ React25.createElement(Backdrop, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React25.createElement(
2135
- Infotip,
2996
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Box6, { ref: deletedChipAnchorRef }, showInfotip && /* @__PURE__ */ React26.createElement(Backdrop, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React26.createElement(
2997
+ Infotip2,
2136
2998
  {
2137
2999
  color: "warning",
2138
3000
  placement: "right-start",
2139
3001
  open: showInfotip,
2140
3002
  disableHoverListener: true,
2141
3003
  onClose: closeInfotip,
2142
- content: /* @__PURE__ */ React25.createElement(
3004
+ content: /* @__PURE__ */ React26.createElement(
2143
3005
  DeletedVariableAlert,
2144
3006
  {
2145
3007
  onClose: closeInfotip,
@@ -2159,8 +3021,15 @@ var DeletedVariable = ({ variable, propTypeKey }) => {
2159
3021
  }
2160
3022
  }
2161
3023
  },
2162
- /* @__PURE__ */ React25.createElement(DeletedTag, { label: variable.label, onClick: toggleInfotip })
2163
- ), /* @__PURE__ */ React25.createElement(
3024
+ /* @__PURE__ */ React26.createElement(
3025
+ WarningVariableTag,
3026
+ {
3027
+ label: variable.label,
3028
+ onClick: toggleInfotip,
3029
+ suffix: __18("deleted", "elementor")
3030
+ }
3031
+ )
3032
+ ), /* @__PURE__ */ React26.createElement(
2164
3033
  Popover2,
2165
3034
  {
2166
3035
  disableScrollLock: true,
@@ -2171,7 +3040,7 @@ var DeletedVariable = ({ variable, propTypeKey }) => {
2171
3040
  },
2172
3041
  ...bindPopover2(popupState)
2173
3042
  },
2174
- /* @__PURE__ */ React25.createElement(VariableTypeProvider, { propTypeKey }, /* @__PURE__ */ React25.createElement(
3043
+ /* @__PURE__ */ React26.createElement(VariableTypeProvider, { propTypeKey }, /* @__PURE__ */ React26.createElement(
2175
3044
  VariableRestore,
2176
3045
  {
2177
3046
  variableId: variable.key ?? "",
@@ -2184,83 +3053,51 @@ var DeletedVariable = ({ variable, propTypeKey }) => {
2184
3053
 
2185
3054
  // src/components/ui/variable/mismatch-variable.tsx
2186
3055
  import * as React28 from "react";
2187
- import { useId as useId3, useRef as useRef3, useState as useState13 } from "react";
3056
+ import { useId as useId3, useRef as useRef8, useState as useState14 } from "react";
2188
3057
  import { useBoundProp as useBoundProp9 } from "@elementor/editor-controls";
2189
- import { Backdrop as Backdrop2, bindPopover as bindPopover3, Box as Box9, Infotip as Infotip2, Popover as Popover3, usePopupState as usePopupState4 } from "@elementor/ui";
3058
+ import { Backdrop as Backdrop2, bindPopover as bindPopover3, Box as Box7, Infotip as Infotip3, Popover as Popover3, usePopupState as usePopupState5 } from "@elementor/ui";
3059
+ import { __ as __20 } from "@wordpress/i18n";
2190
3060
 
2191
3061
  // src/components/ui/mismatch-variable-alert.tsx
2192
- import * as React26 from "react";
2193
- import { useSectionWidth as useSectionWidth2 } from "@elementor/editor-editing-panel";
2194
- import { Alert as Alert3, AlertAction as AlertAction2, AlertTitle as AlertTitle2, ClickAwayListener as ClickAwayListener3 } from "@elementor/ui";
2195
- import { __ as __18 } from "@wordpress/i18n";
3062
+ import * as React27 from "react";
3063
+ import { Alert as Alert3, AlertAction as AlertAction3, AlertTitle as AlertTitle3, ClickAwayListener as ClickAwayListener3, Typography as Typography14 } from "@elementor/ui";
3064
+ import { __ as __19 } from "@wordpress/i18n";
2196
3065
  var i18n = {
2197
- title: __18("Variable has changed", "elementor"),
2198
- message: __18(
3066
+ title: __19("Variable has changed", "elementor"),
3067
+ message: __19(
2199
3068
  `This variable is no longer compatible with this property. You can clear it or select a different one.`,
2200
3069
  "elementor"
2201
3070
  ),
2202
3071
  buttons: {
2203
- clear: __18("Clear", "elementor"),
2204
- select: __18("Select variable", "elementor")
3072
+ clear: __19("Clear", "elementor"),
3073
+ select: __19("Select variable", "elementor")
2205
3074
  }
2206
3075
  };
2207
3076
  var MismatchVariableAlert = ({ onClose, onClear, triggerSelect }) => {
2208
- const sectionWidth = useSectionWidth2();
2209
- return /* @__PURE__ */ React26.createElement(ClickAwayListener3, { onClickAway: onClose }, /* @__PURE__ */ React26.createElement(
3077
+ return /* @__PURE__ */ React27.createElement(ClickAwayListener3, { onClickAway: onClose }, /* @__PURE__ */ React27.createElement(
2210
3078
  Alert3,
2211
3079
  {
2212
3080
  variant: "standard",
2213
3081
  severity: "warning",
2214
3082
  onClose,
2215
- action: /* @__PURE__ */ React26.createElement(React26.Fragment, null, onClear && /* @__PURE__ */ React26.createElement(AlertAction2, { variant: "contained", onClick: onClear }, i18n.buttons.clear), triggerSelect && /* @__PURE__ */ React26.createElement(AlertAction2, { variant: "outlined", onClick: triggerSelect }, i18n.buttons.select)),
2216
- sx: {
2217
- width: sectionWidth,
2218
- minWidth: 300
2219
- }
3083
+ action: /* @__PURE__ */ React27.createElement(React27.Fragment, null, onClear && /* @__PURE__ */ React27.createElement(AlertAction3, { variant: "contained", onClick: onClear }, i18n.buttons.clear), triggerSelect && /* @__PURE__ */ React27.createElement(AlertAction3, { variant: "outlined", onClick: triggerSelect }, i18n.buttons.select)),
3084
+ sx: { maxWidth: 300 }
2220
3085
  },
2221
- /* @__PURE__ */ React26.createElement(AlertTitle2, null, i18n.title),
2222
- i18n.message
3086
+ /* @__PURE__ */ React27.createElement(AlertTitle3, null, i18n.title),
3087
+ /* @__PURE__ */ React27.createElement(Typography14, { variant: "body2", color: "textPrimary" }, i18n.message)
2223
3088
  ));
2224
3089
  };
2225
3090
 
2226
- // src/components/ui/tags/mismatch-tag.tsx
2227
- import * as React27 from "react";
2228
- import { AlertTriangleFilledIcon as AlertTriangleFilledIcon3 } from "@elementor/icons";
2229
- import { Box as Box8, Chip as Chip2, Tooltip as Tooltip3, Typography as Typography12 } from "@elementor/ui";
2230
- import { __ as __19 } from "@wordpress/i18n";
2231
- var MismatchTag = React27.forwardRef(({ label, onClick, ...props }, ref) => {
2232
- return /* @__PURE__ */ React27.createElement(
2233
- Chip2,
2234
- {
2235
- ref,
2236
- size: "tiny",
2237
- color: "warning",
2238
- shape: "rounded",
2239
- variant: "standard",
2240
- onClick,
2241
- icon: /* @__PURE__ */ React27.createElement(AlertTriangleFilledIcon3, null),
2242
- label: /* @__PURE__ */ React27.createElement(Tooltip3, { title: label, placement: "top" }, /* @__PURE__ */ React27.createElement(Box8, { sx: { display: "flex", gap: 0.5, alignItems: "center" } }, /* @__PURE__ */ React27.createElement(Typography12, { variant: "caption", noWrap: true }, label), /* @__PURE__ */ React27.createElement(Typography12, { variant: "caption", noWrap: true, sx: { textOverflow: "initial", overflow: "visible" } }, "(", __19("changed", "elementor"), ")"))),
2243
- sx: {
2244
- height: (theme) => theme.spacing(3.5),
2245
- borderRadius: (theme) => theme.spacing(1),
2246
- justifyContent: "flex-start",
2247
- width: "100%"
2248
- },
2249
- ...props
2250
- }
2251
- );
2252
- });
2253
-
2254
3091
  // src/components/ui/variable/mismatch-variable.tsx
2255
3092
  var MismatchVariable = ({ variable }) => {
2256
- const { setValue } = useBoundProp9();
2257
- const anchorRef = useRef3(null);
3093
+ const { setValue, value } = useBoundProp9();
3094
+ const anchorRef = useRef8(null);
2258
3095
  const popupId = useId3();
2259
- const popupState = usePopupState4({
3096
+ const popupState = usePopupState5({
2260
3097
  variant: "popover",
2261
3098
  popupId: `elementor-variables-list-${popupId}`
2262
3099
  });
2263
- const [infotipVisible, setInfotipVisible] = useState13(false);
3100
+ const [infotipVisible, setInfotipVisible] = useState14(false);
2264
3101
  const toggleInfotip = () => setInfotipVisible((prev) => !prev);
2265
3102
  const closeInfotip = () => setInfotipVisible(false);
2266
3103
  const triggerSelect = () => {
@@ -2272,8 +3109,9 @@ var MismatchVariable = ({ variable }) => {
2272
3109
  closeInfotip();
2273
3110
  setValue(null);
2274
3111
  };
2275
- return /* @__PURE__ */ React28.createElement(Box9, { ref: anchorRef }, infotipVisible && /* @__PURE__ */ React28.createElement(Backdrop2, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React28.createElement(
2276
- Infotip2,
3112
+ const showClearButton = !!value;
3113
+ return /* @__PURE__ */ React28.createElement(Box7, { ref: anchorRef }, infotipVisible && /* @__PURE__ */ React28.createElement(Backdrop2, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React28.createElement(
3114
+ Infotip3,
2277
3115
  {
2278
3116
  color: "warning",
2279
3117
  placement: "right-start",
@@ -2284,7 +3122,7 @@ var MismatchVariable = ({ variable }) => {
2284
3122
  MismatchVariableAlert,
2285
3123
  {
2286
3124
  onClose: closeInfotip,
2287
- onClear: clearValue,
3125
+ onClear: showClearButton ? clearValue : void 0,
2288
3126
  triggerSelect
2289
3127
  }
2290
3128
  ),
@@ -2299,7 +3137,14 @@ var MismatchVariable = ({ variable }) => {
2299
3137
  }
2300
3138
  }
2301
3139
  },
2302
- /* @__PURE__ */ React28.createElement(MismatchTag, { label: variable.label, onClick: toggleInfotip })
3140
+ /* @__PURE__ */ React28.createElement(
3141
+ WarningVariableTag,
3142
+ {
3143
+ label: variable.label,
3144
+ onClick: toggleInfotip,
3145
+ suffix: __20("changed", "elementor")
3146
+ }
3147
+ )
2303
3148
  ), /* @__PURE__ */ React28.createElement(
2304
3149
  Popover3,
2305
3150
  {
@@ -2324,79 +3169,50 @@ var MismatchVariable = ({ variable }) => {
2324
3169
  };
2325
3170
 
2326
3171
  // src/components/ui/variable/missing-variable.tsx
2327
- import * as React31 from "react";
2328
- import { useState as useState14 } from "react";
3172
+ import * as React30 from "react";
3173
+ import { useState as useState15 } from "react";
2329
3174
  import { useBoundProp as useBoundProp10 } from "@elementor/editor-controls";
2330
- import { Backdrop as Backdrop3, Infotip as Infotip3 } from "@elementor/ui";
2331
- import { __ as __21 } from "@wordpress/i18n";
3175
+ import { Backdrop as Backdrop3, Infotip as Infotip4 } from "@elementor/ui";
3176
+ import { __ as __22 } from "@wordpress/i18n";
2332
3177
 
2333
3178
  // src/components/ui/missing-variable-alert.tsx
2334
3179
  import * as React29 from "react";
2335
- import { useSectionWidth as useSectionWidth3 } from "@elementor/editor-editing-panel";
2336
- import { Alert as Alert4, AlertAction as AlertAction3, AlertTitle as AlertTitle3, ClickAwayListener as ClickAwayListener4 } from "@elementor/ui";
2337
- import { __ as __20 } from "@wordpress/i18n";
3180
+ import { Alert as Alert4, AlertAction as AlertAction4, AlertTitle as AlertTitle4, ClickAwayListener as ClickAwayListener4, Typography as Typography15 } from "@elementor/ui";
3181
+ import { __ as __21 } from "@wordpress/i18n";
2338
3182
  var MissingVariableAlert = ({ onClose, onClear }) => {
2339
- const sectionWidth = useSectionWidth3();
2340
3183
  return /* @__PURE__ */ React29.createElement(ClickAwayListener4, { onClickAway: onClose }, /* @__PURE__ */ React29.createElement(
2341
3184
  Alert4,
2342
3185
  {
2343
3186
  variant: "standard",
2344
3187
  severity: "warning",
2345
3188
  onClose,
2346
- action: /* @__PURE__ */ React29.createElement(React29.Fragment, null, onClear && /* @__PURE__ */ React29.createElement(AlertAction3, { variant: "contained", onClick: onClear }, __20("Clear", "elementor"))),
2347
- sx: { width: sectionWidth }
3189
+ action: /* @__PURE__ */ React29.createElement(React29.Fragment, null, onClear && /* @__PURE__ */ React29.createElement(AlertAction4, { variant: "contained", onClick: onClear }, __21("Clear", "elementor"))),
3190
+ sx: { maxWidth: 300 }
2348
3191
  },
2349
- /* @__PURE__ */ React29.createElement(AlertTitle3, null, __20("This variable is missing", "elementor")),
2350
- __20(
3192
+ /* @__PURE__ */ React29.createElement(AlertTitle4, null, __21("This variable is missing", "elementor")),
3193
+ /* @__PURE__ */ React29.createElement(Typography15, { variant: "body2", color: "textPrimary" }, __21(
2351
3194
  "It may have been deleted. Try clearing this field and select a different value or variable.",
2352
3195
  "elementor"
2353
- )
3196
+ ))
2354
3197
  ));
2355
3198
  };
2356
3199
 
2357
- // src/components/ui/tags/missing-tag.tsx
2358
- import * as React30 from "react";
2359
- import { AlertTriangleFilledIcon as AlertTriangleFilledIcon4 } from "@elementor/icons";
2360
- import { Chip as Chip3 } from "@elementor/ui";
2361
- var MissingTag = React30.forwardRef(({ label, onClick, ...props }, ref) => {
2362
- return /* @__PURE__ */ React30.createElement(
2363
- Chip3,
2364
- {
2365
- ref,
2366
- size: "tiny",
2367
- color: "warning",
2368
- shape: "rounded",
2369
- variant: "standard",
2370
- onClick,
2371
- icon: /* @__PURE__ */ React30.createElement(AlertTriangleFilledIcon4, null),
2372
- label,
2373
- sx: {
2374
- height: (theme) => theme.spacing(3.5),
2375
- borderRadius: (theme) => theme.spacing(1),
2376
- justifyContent: "flex-start",
2377
- width: "100%"
2378
- },
2379
- ...props
2380
- }
2381
- );
2382
- });
2383
-
2384
3200
  // src/components/ui/variable/missing-variable.tsx
2385
3201
  var MissingVariable = () => {
2386
3202
  const { setValue } = useBoundProp10();
2387
- const [infotipVisible, setInfotipVisible] = useState14(false);
3203
+ const [infotipVisible, setInfotipVisible] = useState15(false);
2388
3204
  const toggleInfotip = () => setInfotipVisible((prev) => !prev);
2389
3205
  const closeInfotip = () => setInfotipVisible(false);
2390
3206
  const clearValue = () => setValue(null);
2391
- return /* @__PURE__ */ React31.createElement(React31.Fragment, null, infotipVisible && /* @__PURE__ */ React31.createElement(Backdrop3, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React31.createElement(
2392
- Infotip3,
3207
+ return /* @__PURE__ */ React30.createElement(React30.Fragment, null, infotipVisible && /* @__PURE__ */ React30.createElement(Backdrop3, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React30.createElement(
3208
+ Infotip4,
2393
3209
  {
2394
3210
  color: "warning",
2395
3211
  placement: "right-start",
2396
3212
  open: infotipVisible,
2397
3213
  disableHoverListener: true,
2398
3214
  onClose: closeInfotip,
2399
- content: /* @__PURE__ */ React31.createElement(MissingVariableAlert, { onClose: closeInfotip, onClear: clearValue }),
3215
+ content: /* @__PURE__ */ React30.createElement(MissingVariableAlert, { onClose: closeInfotip, onClear: clearValue }),
2400
3216
  slotProps: {
2401
3217
  popper: {
2402
3218
  modifiers: [
@@ -2408,47 +3224,47 @@ var MissingVariable = () => {
2408
3224
  }
2409
3225
  }
2410
3226
  },
2411
- /* @__PURE__ */ React31.createElement(MissingTag, { label: __21("Missing variable", "elementor"), onClick: toggleInfotip })
3227
+ /* @__PURE__ */ React30.createElement(WarningVariableTag, { label: __22("Missing variable", "elementor"), onClick: toggleInfotip })
2412
3228
  ));
2413
3229
  };
2414
3230
 
2415
3231
  // src/controls/variable-control.tsx
2416
3232
  var VariableControl = () => {
2417
3233
  const boundProp = useBoundProp11();
2418
- const boundPropValue = boundProp.value;
3234
+ const boundPropValue = boundProp.value ?? boundProp.placeholder;
2419
3235
  const assignedVariable = useVariable(boundPropValue?.value);
2420
3236
  if (!assignedVariable) {
2421
- return /* @__PURE__ */ React32.createElement(MissingVariable, null);
3237
+ return /* @__PURE__ */ React31.createElement(MissingVariable, null);
2422
3238
  }
2423
3239
  const { $$type: propTypeKey } = boundPropValue;
2424
3240
  if (assignedVariable?.deleted) {
2425
- return /* @__PURE__ */ React32.createElement(DeletedVariable, { variable: assignedVariable, propTypeKey });
3241
+ return /* @__PURE__ */ React31.createElement(DeletedVariable, { variable: assignedVariable, propTypeKey });
2426
3242
  }
2427
3243
  const { isCompatible } = getVariableType(assignedVariable.type);
2428
3244
  if (isCompatible && !isCompatible(boundProp?.propType, assignedVariable)) {
2429
- return /* @__PURE__ */ React32.createElement(MismatchVariable, { variable: assignedVariable });
3245
+ return /* @__PURE__ */ React31.createElement(MismatchVariable, { variable: assignedVariable });
2430
3246
  }
2431
- return /* @__PURE__ */ React32.createElement(AssignedVariable, { variable: assignedVariable, propTypeKey });
3247
+ return /* @__PURE__ */ React31.createElement(AssignedVariable, { variable: assignedVariable, propTypeKey });
2432
3248
  };
2433
3249
 
2434
3250
  // src/hooks/use-prop-variable-action.tsx
2435
- import * as React33 from "react";
3251
+ import * as React32 from "react";
2436
3252
  import { useBoundProp as useBoundProp12 } from "@elementor/editor-editing-panel";
2437
3253
  import { ColorFilterIcon as ColorFilterIcon4 } from "@elementor/icons";
2438
- import { __ as __22 } from "@wordpress/i18n";
3254
+ import { __ as __23 } from "@wordpress/i18n";
2439
3255
  var usePropVariableAction = () => {
2440
3256
  const { propType, path } = useBoundProp12();
2441
3257
  const variable = resolveVariableFromPropType(propType);
2442
3258
  return {
2443
3259
  visible: Boolean(variable),
2444
3260
  icon: ColorFilterIcon4,
2445
- title: __22("Variables", "elementor"),
3261
+ title: __23("Variables", "elementor"),
2446
3262
  content: ({ close: closePopover }) => {
2447
3263
  if (!variable) {
2448
3264
  return null;
2449
3265
  }
2450
3266
  trackOpenVariablePopover(path, variable.variableType);
2451
- return /* @__PURE__ */ React33.createElement(VariableSelectionPopover, { closePopover, propTypeKey: variable.propTypeUtil.key });
3267
+ return /* @__PURE__ */ React32.createElement(VariableSelectionPopover, { closePopover, propTypeKey: variable.propTypeUtil.key });
2452
3268
  }
2453
3269
  };
2454
3270
  };
@@ -2472,19 +3288,297 @@ var trackOpenVariablePopover = (path, variableType) => {
2472
3288
  });
2473
3289
  };
2474
3290
 
3291
+ // src/mcp/index.ts
3292
+ import { getMCPByDomain as getMCPByDomain6 } from "@elementor/editor-mcp";
3293
+
3294
+ // src/mcp/create-variable-tool.ts
3295
+ import { getMCPByDomain } from "@elementor/editor-mcp";
3296
+ import { z as z3 } from "@elementor/schema";
3297
+ var InputSchema = {
3298
+ type: z3.string().describe('The type of the variable. Example values: "global-color-variable" or "global-font-variable".'),
3299
+ label: z3.string().describe("The label of the variable, displayed to the user"),
3300
+ value: z3.string().describe("The value of the variable, should correspond to the type")
3301
+ };
3302
+ var OutputSchema = {
3303
+ status: z3.enum(["ok", "error"]).describe("The status of the operation"),
3304
+ message: z3.string().optional().describe("Optional message providing additional information about the operation")
3305
+ };
3306
+ var initCreateVariableTool = () => {
3307
+ getMCPByDomain("variables").addTool({
3308
+ name: "create-global-variable",
3309
+ schema: InputSchema,
3310
+ outputSchema: OutputSchema,
3311
+ description: `Create a new global variable
3312
+ ## When to use this tool:
3313
+ - When a user requests to create a new global variable in the Elementor editor.
3314
+ - When you need to add a new variable to be used in the editor.
3315
+
3316
+ ## Prequisites:
3317
+ - Ensure you have the most up-to-date list of existing global variables to avoid label duplication. You can use the "list-global-variables" tool to fetch the current variables.
3318
+ - Make sure when creating a new variable, the label is unique and not already in use.
3319
+ - If the user does not provide a label, ask them to provide one before proceeding.
3320
+ - If the user does not provide a type, ask them to provide one before proceeding.
3321
+ - If the user does not provide a value, ask them to provide one before proceeding.
3322
+
3323
+ ## Required parameters:
3324
+ - type: The type of the variable. Possible values are 'global-color-variable' or 'global-font-variable'.
3325
+ - label: The label of the variable, displayed to the user. Must be unique and not already in use.
3326
+ - value: The value of the variable. For color variables, this should be a valid CSS color (e.g., 'rgb(255,0,0)', '#ff0000', 'red'). For font variables, this should be a valid font family (e.g., 'Arial', 'serif').
3327
+
3328
+ ## Example tool call (JSON format):
3329
+ \`\`\`json
3330
+ { "type": "global-color-variable", "label": "My Cool Color", "value": "rgb(1,2,3)" }
3331
+ \`\`\`
3332
+
3333
+ ## Example tool response (JSON format):
3334
+ \`\`\`json
3335
+ { "status": "ok" }
3336
+ \`\`\`
3337
+
3338
+ ## Example to a failed tool response, which must be displayed to the end user. If the error message is not plain, attempt to find the most useful part of the message and display it.
3339
+ { "status": "error", "message": "Unsupported type 'global-kuku-variable'" }
3340
+
3341
+ In that case, inform the user the type is unsupported and they should try another type, perhaps consult to online documentation.
3342
+ `,
3343
+ handler: async (params) => {
3344
+ const { type, label, value } = params;
3345
+ try {
3346
+ await service.create({ type, label, value });
3347
+ } catch (error) {
3348
+ const message = error.message || "Unknown server error";
3349
+ return {
3350
+ status: "error",
3351
+ message: `There was an error creating the variable: ${message}`
3352
+ };
3353
+ }
3354
+ return { status: "ok" };
3355
+ }
3356
+ });
3357
+ };
3358
+
3359
+ // src/mcp/delete-variable-tool.ts
3360
+ import { getMCPByDomain as getMCPByDomain2 } from "@elementor/editor-mcp";
3361
+ import { z as z4 } from "@elementor/schema";
3362
+ var initDeleteVariableTool = () => {
3363
+ getMCPByDomain2("variables").addTool({
3364
+ name: "delete-global-variable",
3365
+ schema: {
3366
+ id: z4.string().describe("The unique identifier of the variable to be deleted.")
3367
+ },
3368
+ outputSchema: {
3369
+ status: z4.enum(["ok", "error"]).describe("The status of the operation")
3370
+ },
3371
+ description: `Delete an existing global variable
3372
+
3373
+ ## When to use this tool:
3374
+ - When a user requests to delete an existing global variable in the Elementor editor.
3375
+ - When you need to remove a variable that is no longer needed or relevant, with the user's confirmation.
3376
+
3377
+ ## Prerequisites:
3378
+ - Ensure you have the most up-to-date list of existing global variables. You can use the "list-global-variables" tool to fetch the current variables.
3379
+ - Reference the variable by the "id" property, given from the "list-global-variables" tool.
3380
+ - Make sure you have the unique identifier of the variable to be deleted before using this tool.
3381
+ - Confirm with the user that they want to proceed with the deletion, as this action is irreversible.
3382
+
3383
+ <notice>
3384
+ A use might reference a variable by it's label, but you must always use the unique identifier (id) to delete it.
3385
+ If you only have the label, use the "list-global-variables" tool to find the corresponding id.
3386
+ </notice>
3387
+
3388
+ <important>
3389
+ This operation is destructive and cannot be undone. Ensure that the user is fully aware of the consequences before proceeding.
3390
+ When a variable is deleted, all references to it in all pages accross the website will lose their effect.
3391
+ </important>`,
3392
+ handler: async (params) => {
3393
+ const { id: id2 } = params;
3394
+ try {
3395
+ await service.delete(id2);
3396
+ return { status: "ok" };
3397
+ } catch (err) {
3398
+ return {
3399
+ status: "error"
3400
+ };
3401
+ }
3402
+ },
3403
+ isDestrcutive: true
3404
+ });
3405
+ };
3406
+
3407
+ // src/mcp/list-variables-tool.ts
3408
+ import { getMCPByDomain as getMCPByDomain3 } from "@elementor/editor-mcp";
3409
+ import { z as z5 } from "@elementor/schema";
3410
+ var VariableSchema = {
3411
+ type: z5.string().describe("The type of the variable."),
3412
+ label: z5.string().describe("The label of the variable, displayed to the user"),
3413
+ value: z5.string().describe("The value of the variable."),
3414
+ id: z5.string().describe(
3415
+ "The unique identifier of the variable. Used for internal reference, not to be exposed to end users"
3416
+ )
3417
+ };
3418
+ var VariableListSchema = {
3419
+ variables: z5.array(z5.object(VariableSchema)).describe("List of variables")
3420
+ };
3421
+ var initListVariablesTool = () => {
3422
+ getMCPByDomain3("variables").addTool({
3423
+ name: "list-global-variables",
3424
+ description: `List editor global variables
3425
+
3426
+ ## When to use this tool:
3427
+ - When a user requests to see all available global variables in the Elementor editor.
3428
+ - When you need to be exact on a variable label, to avoid any mistakes.
3429
+ - When you want to see the most up-to-date list of global variables.
3430
+ - Before using any other variables related tools that makes changes, such as deletion, creation, or updates. This ensures you have the latest information and there is no naming collision or mismatching.
3431
+
3432
+ ## Example tool response (JSON format):
3433
+ \`\`\`json
3434
+ { variables: [
3435
+ { type: 'global-color-variable', label: 'Cool', value: 'rgb(1,2,3)', id: 'some-unique-id' },
3436
+ { type: 'global-font-variable', label: 'Headline', value: 'serif', id: 'some-other-unique-id' },
3437
+ ] }
3438
+ \`\`\`
3439
+
3440
+ Once you get the response, please display the variables in a user-friendly way, unless explicitly requested otherwise.
3441
+ Unless explicitly requested otherwise, response in HTML Format, prefer to use tables or unordered lists.
3442
+
3443
+ Note: **The label is most improtant to be seen as-is without any changes.**
3444
+
3445
+ <important>
3446
+ **Do not omit the label**. This is important for the user to identify the variable.
3447
+ **Do not change the label**, it must be displayed exactly as it is, in it's original characters as received from this tool.
3448
+ </important>
3449
+ `,
3450
+ outputSchema: VariableListSchema,
3451
+ handler: async () => {
3452
+ const variables = service.variables();
3453
+ return {
3454
+ variables: Object.entries(variables).map(([id2, varData]) => ({ id: id2, ...varData }))
3455
+ };
3456
+ }
3457
+ });
3458
+ };
3459
+
3460
+ // src/mcp/update-variable-tool.ts
3461
+ import { getMCPByDomain as getMCPByDomain4 } from "@elementor/editor-mcp";
3462
+ import { z as z6 } from "@elementor/schema";
3463
+ var initUpdateVariableTool = () => {
3464
+ getMCPByDomain4("variables").addTool({
3465
+ schema: {
3466
+ id: z6.string().describe("The unique identifier of the variable to be updated or renamed."),
3467
+ label: z6.string().describe(
3468
+ "The label of the variable to be stored after the change. If the user only wishes to update the value, this must be strictly equal to the current label."
3469
+ ),
3470
+ value: z6.string().describe(
3471
+ "The new value for the variable. For color variables, this should be a valid CSS color (e.g., 'rgb(255,0,0)', '#ff0000', 'red'). For font variables, this should be a valid font family (e.g., 'Arial', 'serif'). If the user wishes to rename only, make sure you provide the existing value."
3472
+ )
3473
+ },
3474
+ outputSchema: {
3475
+ status: z6.enum(["ok", "error"]).describe("The status of the operation"),
3476
+ message: z6.string().optional().describe("Optional message providing additional information about the operation")
3477
+ },
3478
+ name: "update-global-variable",
3479
+ description: `Update an existing global variable
3480
+
3481
+ ## When to use this tool:
3482
+ - When a user requests to update an existing global variable in the Elementor editor.
3483
+ - When you need to modify the value of an existing variable.
3484
+ - When you want to rename an existing variable (change its label).
3485
+ - When you want to both rename and modify the value of an existing variable.
3486
+
3487
+ ## Prerequisites:
3488
+ - Ensure you have the most up-to-date list of existing global variables to avoid label duplication. You can use the "list-global-variables" tool to fetch the current variables.
3489
+ - Make sure when updating a variable, the new label is unique and not already in use by another variable.
3490
+ - Make sure you understand whether you are updating a value, renaming, or both.
3491
+ - Reference the variable by the "id" property, given from the "list-global-variables" tool.
3492
+ - If the user wishes to rename, make sure you have the existing value.
3493
+ - If the user wishes to update the value, make sure you have to **correct label**.
3494
+ - You must have the unique identifier, the current label, the current value, and the new value or label or both, before using this tool.
3495
+
3496
+ ## Required parameters:
3497
+ - id: The unique identifier of the variable to be updated or renamed.
3498
+ - label: The label of the variable to be stored after the change. If the user only wishes to update the value, this must be strictly equal to the current label.
3499
+ - value: The new value for the variable. For color variables, this should be a valid CSS color (e.g., 'rgb(255,0,0)', '#ff0000', 'red'). For font variables, this should be a valid font family (e.g., 'Arial', 'serif'). If the user wishes to rename only, make sure you provide the existing value.
3500
+
3501
+ ## Example tool call (JSON format):
3502
+ \`\`\`json
3503
+ { "id": "some-unique-id", "label": "Cool", "value": "rgb(0,140,250)" }
3504
+ \`\`\`
3505
+
3506
+ ## Example responses (JSON format):
3507
+ Successful update:
3508
+ \`\`\`json
3509
+ { "status": "ok" }
3510
+ \`\`\`
3511
+
3512
+ Failed update, which must be displayed to the end user. If the error message is not plain, attempt to find the most useful part of the message and display it.
3513
+ \`\`\`json
3514
+ { "status": "error", "message": "Label 'Cool' is already in use by another variable." }
3515
+ \`\`\`
3516
+ `,
3517
+ handler: async (params) => {
3518
+ const { id: id2, label, value } = params;
3519
+ try {
3520
+ await service.update(id2, { label, value });
3521
+ return { status: "ok" };
3522
+ } catch (error) {
3523
+ const message = error.message || "Unknown server error";
3524
+ return {
3525
+ status: "error",
3526
+ message: `There was an error creating the variable: ${message}`
3527
+ };
3528
+ }
3529
+ }
3530
+ });
3531
+ };
3532
+
3533
+ // src/mcp/variables-resource.ts
3534
+ import { getMCPByDomain as getMCPByDomain5 } from "@elementor/editor-mcp";
3535
+ var GLOBAL_VARIABLES_URI = "elementor://variables";
3536
+ var initVariablesResource = () => {
3537
+ const { mcpServer } = getMCPByDomain5("variables");
3538
+ mcpServer.resource(
3539
+ "global-variables",
3540
+ GLOBAL_VARIABLES_URI,
3541
+ {
3542
+ description: "Global variables list. Variables are being used in this way: If it is directly in the schema, you need to put the ID which is the key inside the object."
3543
+ },
3544
+ async () => {
3545
+ return {
3546
+ contents: [{ uri: GLOBAL_VARIABLES_URI, text: localStorage["elementor-global-variables"] }]
3547
+ };
3548
+ }
3549
+ );
3550
+ window.addEventListener("variables:updated", () => {
3551
+ mcpServer.server.sendResourceUpdated({
3552
+ uri: GLOBAL_VARIABLES_URI,
3553
+ contents: [{ uri: GLOBAL_VARIABLES_URI, text: localStorage["elementor-global-variables"] }]
3554
+ });
3555
+ });
3556
+ };
3557
+
3558
+ // src/mcp/index.ts
3559
+ function initMcp() {
3560
+ const { setMCPDescription } = getMCPByDomain6("variables");
3561
+ setMCPDescription(`Elementor Editor Variables MCP`);
3562
+ initListVariablesTool();
3563
+ initCreateVariableTool();
3564
+ initUpdateVariableTool();
3565
+ initDeleteVariableTool();
3566
+ initVariablesResource();
3567
+ }
3568
+
2475
3569
  // src/register-variable-types.tsx
2476
- import * as React36 from "react";
3570
+ import * as React35 from "react";
2477
3571
  import { colorPropTypeUtil, stringPropTypeUtil } from "@elementor/editor-props";
2478
3572
  import { BrushIcon, TextIcon as TextIcon2 } from "@elementor/icons";
2479
3573
 
2480
3574
  // src/components/fields/color-field.tsx
2481
- import * as React34 from "react";
2482
- import { useRef as useRef4, useState as useState15 } from "react";
3575
+ import * as React33 from "react";
3576
+ import { useRef as useRef9, useState as useState16 } from "react";
2483
3577
  import { UnstableColorField } from "@elementor/ui";
2484
3578
  var ColorField = ({ value, onChange, onValidationChange }) => {
2485
- const [color, setColor] = useState15(value);
2486
- const [errorMessage, setErrorMessage] = useState15("");
2487
- const defaultRef = useRef4(null);
3579
+ const [color, setColor] = useState16(value);
3580
+ const [errorMessage, setErrorMessage] = useState16("");
3581
+ const defaultRef = useRef9(null);
2488
3582
  const anchorRef = usePopoverContentRef() ?? defaultRef.current;
2489
3583
  const handleChange = (newValue) => {
2490
3584
  setColor(newValue);
@@ -2493,9 +3587,10 @@ var ColorField = ({ value, onChange, onValidationChange }) => {
2493
3587
  onValidationChange?.(errorMsg);
2494
3588
  onChange(errorMsg ? "" : newValue);
2495
3589
  };
2496
- return /* @__PURE__ */ React34.createElement(
3590
+ return /* @__PURE__ */ React33.createElement(
2497
3591
  UnstableColorField,
2498
3592
  {
3593
+ id: "color-variable-field",
2499
3594
  size: "tiny",
2500
3595
  fullWidth: true,
2501
3596
  value: color,
@@ -2521,21 +3616,21 @@ var ColorField = ({ value, onChange, onValidationChange }) => {
2521
3616
  };
2522
3617
 
2523
3618
  // src/components/fields/font-field.tsx
2524
- import * as React35 from "react";
2525
- import { useId as useId4, useRef as useRef5, useState as useState16 } from "react";
3619
+ import * as React34 from "react";
3620
+ import { useId as useId4, useRef as useRef10, useState as useState17 } from "react";
2526
3621
  import { enqueueFont as enqueueFont2, ItemSelector } from "@elementor/editor-controls";
2527
- import { useFontFamilies, useSectionWidth as useSectionWidth4 } from "@elementor/editor-editing-panel";
3622
+ import { useFontFamilies, useSectionWidth } from "@elementor/editor-editing-panel";
2528
3623
  import { ChevronDownIcon, TextIcon } from "@elementor/icons";
2529
- import { bindPopover as bindPopover4, bindTrigger as bindTrigger3, Popover as Popover4, UnstableTag, usePopupState as usePopupState5 } from "@elementor/ui";
2530
- import { __ as __23 } from "@wordpress/i18n";
3624
+ import { bindPopover as bindPopover4, bindTrigger as bindTrigger4, Popover as Popover4, UnstableTag, usePopupState as usePopupState6 } from "@elementor/ui";
3625
+ import { __ as __24 } from "@wordpress/i18n";
2531
3626
  var FontField = ({ value, onChange, onValidationChange }) => {
2532
- const [fontFamily, setFontFamily] = useState16(value);
2533
- const defaultRef = useRef5(null);
3627
+ const [fontFamily, setFontFamily] = useState17(value);
3628
+ const defaultRef = useRef10(null);
2534
3629
  const anchorRef = usePopoverContentRef() ?? defaultRef.current;
2535
- const fontPopoverState = usePopupState5({ variant: "popover" });
3630
+ const fontPopoverState = usePopupState6({ variant: "popover" });
2536
3631
  const fontFamilies = useFontFamilies();
2537
- const sectionWidth = useSectionWidth4();
2538
- const mapFontSubs = React35.useMemo(() => {
3632
+ const sectionWidth = useSectionWidth();
3633
+ const mapFontSubs = React34.useMemo(() => {
2539
3634
  return fontFamilies.map(({ label, fonts }) => ({
2540
3635
  label,
2541
3636
  items: fonts
@@ -2552,17 +3647,17 @@ var FontField = ({ value, onChange, onValidationChange }) => {
2552
3647
  fontPopoverState.close();
2553
3648
  };
2554
3649
  const id2 = useId4();
2555
- return /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(
3650
+ return /* @__PURE__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement(
2556
3651
  UnstableTag,
2557
3652
  {
2558
3653
  id: id2,
2559
3654
  variant: "outlined",
2560
3655
  label: fontFamily,
2561
- endIcon: /* @__PURE__ */ React35.createElement(ChevronDownIcon, { fontSize: "tiny" }),
2562
- ...bindTrigger3(fontPopoverState),
3656
+ endIcon: /* @__PURE__ */ React34.createElement(ChevronDownIcon, { fontSize: "tiny" }),
3657
+ ...bindTrigger4(fontPopoverState),
2563
3658
  fullWidth: true
2564
3659
  }
2565
- ), /* @__PURE__ */ React35.createElement(
3660
+ ), /* @__PURE__ */ React34.createElement(
2566
3661
  Popover4,
2567
3662
  {
2568
3663
  disablePortal: true,
@@ -2572,15 +3667,16 @@ var FontField = ({ value, onChange, onValidationChange }) => {
2572
3667
  transformOrigin: { vertical: "top", horizontal: -28 },
2573
3668
  ...bindPopover4(fontPopoverState)
2574
3669
  },
2575
- /* @__PURE__ */ React35.createElement(
3670
+ /* @__PURE__ */ React34.createElement(
2576
3671
  ItemSelector,
2577
3672
  {
3673
+ id: "font-family-variables-selector",
2578
3674
  itemsList: mapFontSubs,
2579
3675
  selectedItem: fontFamily,
2580
3676
  onItemChange: handleFontFamilyChange,
2581
3677
  onClose: fontPopoverState.close,
2582
3678
  sectionWidth,
2583
- title: __23("Font Family", "elementor"),
3679
+ title: __24("Font family", "elementor"),
2584
3680
  itemStyle: (item) => ({ fontFamily: item.value }),
2585
3681
  onDebounce: enqueueFont2,
2586
3682
  icon: TextIcon
@@ -2592,25 +3688,29 @@ var FontField = ({ value, onChange, onValidationChange }) => {
2592
3688
  // src/register-variable-types.tsx
2593
3689
  function registerVariableTypes() {
2594
3690
  registerVariableType({
3691
+ key: colorVariablePropTypeUtil.key,
2595
3692
  valueField: ColorField,
2596
3693
  icon: BrushIcon,
2597
3694
  propTypeUtil: colorVariablePropTypeUtil,
2598
3695
  fallbackPropTypeUtil: colorPropTypeUtil,
2599
3696
  variableType: "color",
2600
- startIcon: ({ value }) => /* @__PURE__ */ React36.createElement(ColorIndicator, { size: "inherit", component: "span", value })
3697
+ startIcon: ({ value }) => /* @__PURE__ */ React35.createElement(ColorIndicator, { size: "inherit", component: "span", value }),
3698
+ defaultValue: "#ffffff"
2601
3699
  });
2602
3700
  registerVariableType({
3701
+ key: fontVariablePropTypeUtil.key,
2603
3702
  valueField: FontField,
2604
3703
  icon: TextIcon2,
2605
3704
  propTypeUtil: fontVariablePropTypeUtil,
2606
3705
  fallbackPropTypeUtil: stringPropTypeUtil,
2607
- variableType: "font"
3706
+ variableType: "font",
3707
+ defaultValue: "Roboto"
2608
3708
  });
2609
3709
  }
2610
3710
 
2611
3711
  // src/renderers/style-variables-renderer.tsx
2612
- import * as React37 from "react";
2613
- import { useEffect as useEffect3, useState as useState17 } from "react";
3712
+ import * as React36 from "react";
3713
+ import { useEffect as useEffect5, useState as useState18 } from "react";
2614
3714
  import { __privateUseListenTo as useListenTo, commandEndEvent } from "@elementor/editor-v1-adapters";
2615
3715
  import { Portal } from "@elementor/ui";
2616
3716
 
@@ -2631,14 +3731,14 @@ function StyleVariablesRenderer() {
2631
3731
  }
2632
3732
  const cssVariables = convertToCssVariables(styleVariables);
2633
3733
  const wrappedCss = `${VARIABLES_WRAPPER}{${cssVariables}}`;
2634
- return /* @__PURE__ */ React37.createElement(Portal, { container }, /* @__PURE__ */ React37.createElement("style", { "data-e-style-id": "e-variables", key: wrappedCss }, wrappedCss));
3734
+ return /* @__PURE__ */ React36.createElement(Portal, { container }, /* @__PURE__ */ React36.createElement("style", { "data-e-style-id": "e-variables", key: wrappedCss }, wrappedCss));
2635
3735
  }
2636
3736
  function usePortalContainer() {
2637
3737
  return useListenTo(commandEndEvent("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
2638
3738
  }
2639
3739
  function useStyleVariables() {
2640
- const [variables, setVariables] = useState17({});
2641
- useEffect3(() => {
3740
+ const [variables, setVariables] = useState18({});
3741
+ useEffect5(() => {
2642
3742
  const unsubscribe = styleVariablesRepository.subscribe(setVariables);
2643
3743
  return () => {
2644
3744
  unsubscribe();
@@ -2661,22 +3761,22 @@ import { injectIntoRepeaterItemIcon, injectIntoRepeaterItemLabel } from "@elemen
2661
3761
  import { backgroundColorOverlayPropTypeUtil, shadowPropTypeUtil } from "@elementor/editor-props";
2662
3762
 
2663
3763
  // src/components/variables-repeater-item-slot.tsx
2664
- import * as React38 from "react";
3764
+ import * as React37 from "react";
2665
3765
  var useColorVariable = (value) => {
2666
3766
  const variableId = value?.value?.color?.value;
2667
3767
  return useVariable(variableId || "");
2668
3768
  };
2669
3769
  var BackgroundRepeaterColorIndicator = ({ value }) => {
2670
3770
  const colorVariable = useColorVariable(value);
2671
- return /* @__PURE__ */ React38.createElement(ColorIndicator, { component: "span", size: "inherit", value: colorVariable?.value });
3771
+ return /* @__PURE__ */ React37.createElement(ColorIndicator, { component: "span", size: "inherit", value: colorVariable?.value });
2672
3772
  };
2673
3773
  var BackgroundRepeaterLabel = ({ value }) => {
2674
3774
  const colorVariable = useColorVariable(value);
2675
- return /* @__PURE__ */ React38.createElement("span", null, colorVariable?.label);
3775
+ return /* @__PURE__ */ React37.createElement("span", null, colorVariable?.label);
2676
3776
  };
2677
3777
  var BoxShadowRepeaterColorIndicator = ({ value }) => {
2678
3778
  const colorVariable = useColorVariable(value);
2679
- return /* @__PURE__ */ React38.createElement(ColorIndicator, { component: "span", size: "inherit", value: colorVariable?.value });
3779
+ return /* @__PURE__ */ React37.createElement(ColorIndicator, { component: "span", size: "inherit", value: colorVariable?.value });
2680
3780
  };
2681
3781
 
2682
3782
  // src/repeater-injections.ts
@@ -2714,27 +3814,30 @@ function init() {
2714
3814
  registerRepeaterInjections();
2715
3815
  registerControlReplacement({
2716
3816
  component: VariableControl,
2717
- condition: ({ value }) => hasAssignedVariable(value)
3817
+ condition: ({ value, placeholder }) => hasVariable(value) || hasVariable(placeholder)
2718
3818
  });
2719
3819
  registerPopoverAction({
2720
3820
  id: "variables",
2721
3821
  useProps: usePropVariableAction
2722
3822
  });
2723
- service.init();
3823
+ service.init().then(() => {
3824
+ initMcp();
3825
+ });
2724
3826
  injectIntoTop({
2725
3827
  id: "canvas-style-variables-render",
2726
3828
  component: StyleVariablesRenderer
2727
3829
  });
2728
3830
  registerPanel(panel);
2729
3831
  }
2730
- function hasAssignedVariable(propValue) {
2731
- if (propValue && typeof propValue === "object" && "$$type" in propValue) {
2732
- return hasVariableType(propValue.$$type);
3832
+ function hasVariable(value) {
3833
+ if (isTransformable2(value)) {
3834
+ return hasVariableType(value.$$type);
2733
3835
  }
2734
3836
  return false;
2735
3837
  }
2736
3838
  export {
2737
3839
  init,
2738
- registerVariableType
3840
+ registerVariableType,
3841
+ registerVariableTypes
2739
3842
  };
2740
3843
  //# sourceMappingURL=index.mjs.map