@elementor/editor-variables 4.1.0 → 4.2.0-840

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,16 +1,211 @@
1
- // src/init.ts
2
- import { injectIntoLogic, injectIntoTop } from "@elementor/editor";
3
- import { registerControlReplacement } from "@elementor/editor-controls";
4
- import { getMCPByDomain } from "@elementor/editor-mcp";
5
- import { __registerPanel as registerPanel } from "@elementor/editor-panels";
6
- import { isTransformable as isTransformable2 } from "@elementor/editor-props";
7
- import { controlActionsMenu } from "@elementor/menus";
1
+ // src/components/variables-manager/variables-manager-panel.tsx
2
+ import * as React14 from "react";
3
+ import { useCallback as useCallback6, useEffect as useEffect3, useMemo as useMemo3, useState as useState6 } from "react";
4
+ import { useSuppressedMessage } from "@elementor/editor-current-user";
5
+ import {
6
+ __createPanel as createPanel,
7
+ Panel,
8
+ PanelBody,
9
+ PanelFooter,
10
+ PanelHeader,
11
+ PanelHeaderTitle
12
+ } from "@elementor/editor-panels";
13
+ import { ConfirmationDialog as ConfirmationDialog2, SaveChangesDialog, SearchField, ThemeProvider, useDialog } from "@elementor/editor-ui";
14
+ import { changeEditMode } from "@elementor/editor-v1-adapters";
15
+ import { AlertTriangleFilledIcon as AlertTriangleFilledIcon2, ColorFilterIcon, CopyIcon, TrashIcon } from "@elementor/icons";
16
+ import {
17
+ Alert,
18
+ AlertAction,
19
+ AlertTitle,
20
+ Box as Box2,
21
+ Button as Button2,
22
+ CloseButton,
23
+ Divider,
24
+ Infotip,
25
+ Stack as Stack6,
26
+ usePopupState as usePopupState2
27
+ } from "@elementor/ui";
28
+ import { __ as __10 } from "@wordpress/i18n";
8
29
 
9
- // src/components/global-styles-import-listener.tsx
10
- import { useEffect } from "react";
30
+ // src/utils/tracking.ts
31
+ import { getMixpanel } from "@elementor/events";
32
+ var trackVariableEvent = ({ varType, controlPath, action }) => {
33
+ const { dispatchEvent, config } = getMixpanel();
34
+ if (!config?.names?.variables?.[action]) {
35
+ return;
36
+ }
37
+ const name = config.names.variables[action];
38
+ dispatchEvent?.(name, {
39
+ location: config?.locations?.variables || "",
40
+ secondaryLocation: config?.secondaryLocations?.variablesPopover || "",
41
+ trigger: config?.triggers?.click || "",
42
+ var_type: varType,
43
+ control_path: controlPath,
44
+ action_type: name
45
+ });
46
+ };
47
+ var trackVariablesManagerEvent = ({ action, varType, controlPath }) => {
48
+ const { dispatchEvent, config } = getMixpanel();
49
+ if (!config?.names?.variables?.[action]) {
50
+ return;
51
+ }
52
+ const name = config.names.variables[action];
53
+ const eventData = {
54
+ location: config?.locations?.variablesManager || "",
55
+ trigger: config?.triggers?.click || "",
56
+ action_type: name
57
+ };
58
+ if (varType) {
59
+ eventData.var_type = varType;
60
+ }
61
+ if (controlPath) {
62
+ eventData.style_control_path = controlPath;
63
+ }
64
+ dispatchEvent?.(name, eventData);
65
+ };
66
+ var trackVariableSyncToV3 = ({ variableLabel, action }) => {
67
+ try {
68
+ const { dispatchEvent, config } = getMixpanel();
69
+ if (!config?.names?.variables?.variableSyncToV3) {
70
+ return;
71
+ }
72
+ const name = config.names.variables.variableSyncToV3;
73
+ const isSync = action === "sync";
74
+ dispatchEvent?.(name, {
75
+ interaction_type: "click",
76
+ target_type: variableLabel,
77
+ target_name: isSync ? "sync_to_v3" : "unsync_to_v3",
78
+ interaction_result: isSync ? "var_is_synced_to_V3" : "var_is_unsynced_from_V3",
79
+ target_location: "widget_panel",
80
+ location_l1: "var_manager",
81
+ interaction_description: isSync ? `user_synced_${variableLabel}_to_v3` : `user_unsync_${variableLabel}_from_v3`
82
+ });
83
+ } catch {
84
+ }
85
+ };
86
+
87
+ // src/utils/validations.ts
88
+ import { AlertTriangleFilledIcon, InfoCircleFilledIcon } from "@elementor/icons";
89
+ import { __, sprintf } from "@wordpress/i18n";
90
+ var ERROR_MESSAGES = {
91
+ MISSING_VARIABLE_NAME: __("Give your variable a name.", "elementor"),
92
+ MISSING_VARIABLE_VALUE: __("Add a value to complete your variable.", "elementor"),
93
+ INVALID_CHARACTERS: __("Use letters, numbers, dashes (-), or underscores (_) for the name.", "elementor"),
94
+ NO_NON_SPECIAL_CHARACTER: __("Names have to include at least one non-special character.", "elementor"),
95
+ VARIABLE_LABEL_MAX_LENGTH: __("Keep names up to 50 characters.", "elementor"),
96
+ DUPLICATED_LABEL: __("This variable name already exists. Please choose a unique name.", "elementor"),
97
+ UNEXPECTED_ERROR: __("There was a glitch. Try saving your variable again.", "elementor"),
98
+ BATCH: {
99
+ DUPLICATED_LABELS: (count, name) => (
100
+ // eslint-disable-next-line @wordpress/i18n-translator-comments
101
+ sprintf(__("We found %1$d duplicated %2$s.", "elementor"), count, name)
102
+ ),
103
+ UNEXPECTED_ERROR: __("There was a glitch.", "elementor"),
104
+ DUPLICATED_LABEL_ACTION: __("Take me there", "elementor"),
105
+ DUPLICATED_LABEL_ACTION_MESSAGE: __("Please rename the variables.", "elementor"),
106
+ UNEXPECTED_ERROR_ACTION_MESSAGE: __("Try saving your variables again.", "elementor")
107
+ }
108
+ };
109
+ var VARIABLE_LABEL_MAX_LENGTH = 50;
110
+ var mapServerError = (error) => {
111
+ if (error?.response?.data?.code === "duplicated_label") {
112
+ return {
113
+ field: "label",
114
+ message: ERROR_MESSAGES.DUPLICATED_LABEL
115
+ };
116
+ }
117
+ if (error?.response?.data?.code === "batch_duplicated_label") {
118
+ const errorData = error?.response?.data?.data ?? {};
119
+ const count = Object.keys(errorData).length;
120
+ const name = count === 1 ? "name" : "names";
121
+ const duplicatedIds = Object.keys(errorData);
122
+ return {
123
+ field: "label",
124
+ message: ERROR_MESSAGES.BATCH.DUPLICATED_LABELS(count, name),
125
+ severity: "error",
126
+ IconComponent: AlertTriangleFilledIcon,
127
+ action: {
128
+ label: ERROR_MESSAGES.BATCH.DUPLICATED_LABEL_ACTION,
129
+ message: ERROR_MESSAGES.BATCH.DUPLICATED_LABEL_ACTION_MESSAGE,
130
+ data: {
131
+ duplicatedIds
132
+ }
133
+ }
134
+ };
135
+ }
136
+ if (error?.response?.data?.code === "batch_operation_failed") {
137
+ return {
138
+ field: "label",
139
+ message: ERROR_MESSAGES.BATCH.UNEXPECTED_ERROR,
140
+ severity: "secondary",
141
+ IconComponent: InfoCircleFilledIcon,
142
+ action: {
143
+ message: ERROR_MESSAGES.BATCH.UNEXPECTED_ERROR_ACTION_MESSAGE
144
+ }
145
+ };
146
+ }
147
+ return void 0;
148
+ };
149
+ var validateLabel = (name, variables) => {
150
+ if (!name.trim()) {
151
+ return ERROR_MESSAGES.MISSING_VARIABLE_NAME;
152
+ }
153
+ const allowedChars = /^[a-zA-Z0-9_-]+$/;
154
+ if (!allowedChars.test(name)) {
155
+ return ERROR_MESSAGES.INVALID_CHARACTERS;
156
+ }
157
+ const hasAlphanumeric = /[a-zA-Z0-9]/;
158
+ if (!hasAlphanumeric.test(name)) {
159
+ return ERROR_MESSAGES.NO_NON_SPECIAL_CHARACTER;
160
+ }
161
+ if (VARIABLE_LABEL_MAX_LENGTH < name.length) {
162
+ return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
163
+ }
164
+ if (Object.values(variables ?? {}).some((variable) => variable.label === name)) {
165
+ return ERROR_MESSAGES.DUPLICATED_LABEL;
166
+ }
167
+ return "";
168
+ };
169
+ var labelHint = (name) => {
170
+ const hintThreshold = VARIABLE_LABEL_MAX_LENGTH * 0.8 - 1;
171
+ if (hintThreshold < name.length) {
172
+ return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
173
+ }
174
+ return "";
175
+ };
176
+ var validateValue = (value) => {
177
+ if (!value.trim()) {
178
+ return ERROR_MESSAGES.MISSING_VARIABLE_VALUE;
179
+ }
180
+ return "";
181
+ };
182
+
183
+ // src/variables-registry/create-variable-type-registry.ts
184
+ import {
185
+ stylesInheritanceTransformersRegistry,
186
+ styleTransformersRegistry
187
+ } from "@elementor/editor-canvas";
188
+
189
+ // src/transformers/inheritance-transformer.tsx
190
+ import * as React from "react";
191
+ import { createTransformer } from "@elementor/editor-canvas";
192
+ import { Stack, Typography } from "@elementor/ui";
193
+ import { __ as __3 } from "@wordpress/i18n";
194
+
195
+ // src/components/ui/color-indicator.tsx
196
+ import { styled, UnstableColorIndicator } from "@elementor/ui";
197
+ var ColorIndicator = styled(UnstableColorIndicator)(({ theme }) => ({
198
+ borderRadius: `${theme.shape.borderRadius / 2}px`,
199
+ marginRight: theme.spacing(0.25)
200
+ }));
201
+
202
+ // src/prop-types/color-variable-prop-type.ts
203
+ import { createPropUtils } from "@elementor/editor-props";
204
+ import { z } from "@elementor/schema";
205
+ var colorVariablePropTypeUtil = createPropUtils("global-color-variable", z.string());
11
206
 
12
207
  // src/service.ts
13
- import { __ } from "@wordpress/i18n";
208
+ import { __ as __2 } from "@wordpress/i18n";
14
209
 
15
210
  // src/api.ts
16
211
  import { httpService } from "@elementor/http-client";
@@ -175,9 +370,9 @@ var Storage = class {
175
370
  import { enqueueFont } from "@elementor/editor-v1-adapters";
176
371
 
177
372
  // src/prop-types/font-variable-prop-type.ts
178
- import { createPropUtils } from "@elementor/editor-props";
179
- import { z } from "@elementor/schema";
180
- var fontVariablePropTypeUtil = createPropUtils("global-font-variable", z.string());
373
+ import { createPropUtils as createPropUtils2 } from "@elementor/editor-props";
374
+ import { z as z2 } from "@elementor/schema";
375
+ var fontVariablePropTypeUtil = createPropUtils2("global-font-variable", z2.string());
181
376
 
182
377
  // src/create-style-variables-repository.ts
183
378
  var createStyleVariablesRepository = () => {
@@ -289,7 +484,7 @@ var service = {
289
484
  return apiClient.create(type, label, value).then((response) => {
290
485
  const { success, data: payload } = response.data;
291
486
  if (!success) {
292
- const errorMessage = payload?.message || __("Unexpected response from server", "elementor");
487
+ const errorMessage = payload?.message || __2("Unexpected response from server", "elementor");
293
488
  throw new Error(errorMessage);
294
489
  }
295
490
  return payload;
@@ -311,7 +506,7 @@ var service = {
311
506
  return apiClient.update(id2, label, value, type).then((response) => {
312
507
  const { success, data: payload } = response.data;
313
508
  if (!success) {
314
- const errorMessage = payload?.message || __("Unexpected response from server", "elementor");
509
+ const errorMessage = payload?.message || __2("Unexpected response from server", "elementor");
315
510
  throw new Error(errorMessage);
316
511
  }
317
512
  return payload;
@@ -394,269 +589,32 @@ var service = {
394
589
  results.forEach((result) => {
395
590
  const variableId = result.id;
396
591
  if (result.variable) {
397
- if (result.type === "create") {
398
- storage.add(variableId, result.variable);
399
- } else {
400
- storage.update(variableId, result.variable);
401
- }
402
- styleVariablesRepository.update({
403
- [variableId]: result.variable
404
- });
405
- }
406
- });
407
- }
408
- return {
409
- success: true,
410
- watermark,
411
- operations: operations.length
412
- };
413
- });
414
- }
415
- };
416
- var handleWatermark = (operation, newWatermark) => {
417
- if (storage.watermarkDiff(operation, newWatermark)) {
418
- setTimeout(() => service.load(), 500);
419
- }
420
- storage.watermark(newWatermark);
421
- };
422
-
423
- // src/components/global-styles-import-listener.tsx
424
- function GlobalStylesImportListener() {
425
- useEffect(() => {
426
- const handleGlobalStylesImported = (event) => {
427
- const importedVars = event.detail?.global_variables;
428
- if (!importedVars) {
429
- return;
430
- }
431
- if (importedVars.data && typeof importedVars.data === "object") {
432
- styleVariablesRepository.update(importedVars.data);
433
- }
434
- service.load();
435
- };
436
- window.addEventListener("elementor/global-styles/imported", handleGlobalStylesImported);
437
- return () => {
438
- window.removeEventListener(
439
- "elementor/global-styles/imported",
440
- handleGlobalStylesImported
441
- );
442
- };
443
- }, []);
444
- return null;
445
- }
446
-
447
- // src/components/open-panel-from-event.tsx
448
- import { useEffect as useEffect5, useRef as useRef7, useState as useState7 } from "react";
449
- import {
450
- __privateListenTo as listenTo,
451
- __privateOpenRoute as openRoute,
452
- routeOpenEvent
453
- } from "@elementor/editor-v1-adapters";
454
-
455
- // src/components/variables-manager/variables-manager-panel.tsx
456
- import * as React14 from "react";
457
- import { useCallback as useCallback6, useEffect as useEffect4, useState as useState6 } from "react";
458
- import { useSuppressedMessage } from "@elementor/editor-current-user";
459
- import {
460
- __createPanel as createPanel,
461
- Panel,
462
- PanelBody,
463
- PanelFooter,
464
- PanelHeader,
465
- PanelHeaderTitle
466
- } from "@elementor/editor-panels";
467
- import { ConfirmationDialog as ConfirmationDialog2, SaveChangesDialog, SearchField, ThemeProvider, useDialog } from "@elementor/editor-ui";
468
- import { changeEditMode } from "@elementor/editor-v1-adapters";
469
- import { AlertTriangleFilledIcon as AlertTriangleFilledIcon2, ColorFilterIcon, CopyIcon, TrashIcon } from "@elementor/icons";
470
- import {
471
- Alert,
472
- AlertAction,
473
- AlertTitle,
474
- Button as Button2,
475
- CloseButton,
476
- Divider,
477
- Infotip,
478
- Stack as Stack6,
479
- usePopupState as usePopupState2
480
- } from "@elementor/ui";
481
- import { __ as __10 } from "@wordpress/i18n";
482
-
483
- // src/utils/tracking.ts
484
- import { getMixpanel } from "@elementor/events";
485
- var trackVariableEvent = ({ varType, controlPath, action }) => {
486
- const { dispatchEvent, config } = getMixpanel();
487
- if (!config?.names?.variables?.[action]) {
488
- return;
489
- }
490
- const name = config.names.variables[action];
491
- dispatchEvent?.(name, {
492
- location: config?.locations?.variables || "",
493
- secondaryLocation: config?.secondaryLocations?.variablesPopover || "",
494
- trigger: config?.triggers?.click || "",
495
- var_type: varType,
496
- control_path: controlPath,
497
- action_type: name
498
- });
499
- };
500
- var trackVariablesManagerEvent = ({ action, varType, controlPath }) => {
501
- const { dispatchEvent, config } = getMixpanel();
502
- if (!config?.names?.variables?.[action]) {
503
- return;
504
- }
505
- const name = config.names.variables[action];
506
- const eventData = {
507
- location: config?.locations?.variablesManager || "",
508
- trigger: config?.triggers?.click || "",
509
- action_type: name
510
- };
511
- if (varType) {
512
- eventData.var_type = varType;
513
- }
514
- if (controlPath) {
515
- eventData.style_control_path = controlPath;
516
- }
517
- dispatchEvent?.(name, eventData);
518
- };
519
- var trackVariableSyncToV3 = ({ variableLabel, action }) => {
520
- try {
521
- const { dispatchEvent, config } = getMixpanel();
522
- if (!config?.names?.variables?.variableSyncToV3) {
523
- return;
524
- }
525
- const name = config.names.variables.variableSyncToV3;
526
- const isSync = action === "sync";
527
- dispatchEvent?.(name, {
528
- interaction_type: "click",
529
- target_type: variableLabel,
530
- target_name: isSync ? "sync_to_v3" : "unsync_to_v3",
531
- interaction_result: isSync ? "var_is_synced_to_V3" : "var_is_unsynced_from_V3",
532
- target_location: "widget_panel",
533
- location_l1: "var_manager",
534
- interaction_description: isSync ? `user_synced_${variableLabel}_to_v3` : `user_unsync_${variableLabel}_from_v3`
535
- });
536
- } catch {
537
- }
538
- };
539
-
540
- // src/utils/validations.ts
541
- import { AlertTriangleFilledIcon, InfoCircleFilledIcon } from "@elementor/icons";
542
- import { __ as __2, sprintf } from "@wordpress/i18n";
543
- var ERROR_MESSAGES = {
544
- MISSING_VARIABLE_NAME: __2("Give your variable a name.", "elementor"),
545
- MISSING_VARIABLE_VALUE: __2("Add a value to complete your variable.", "elementor"),
546
- INVALID_CHARACTERS: __2("Use letters, numbers, dashes (-), or underscores (_) for the name.", "elementor"),
547
- NO_NON_SPECIAL_CHARACTER: __2("Names have to include at least one non-special character.", "elementor"),
548
- VARIABLE_LABEL_MAX_LENGTH: __2("Keep names up to 50 characters.", "elementor"),
549
- DUPLICATED_LABEL: __2("This variable name already exists. Please choose a unique name.", "elementor"),
550
- UNEXPECTED_ERROR: __2("There was a glitch. Try saving your variable again.", "elementor"),
551
- BATCH: {
552
- DUPLICATED_LABELS: (count, name) => (
553
- // eslint-disable-next-line @wordpress/i18n-translator-comments
554
- sprintf(__2("We found %1$d duplicated %2$s.", "elementor"), count, name)
555
- ),
556
- UNEXPECTED_ERROR: __2("There was a glitch.", "elementor"),
557
- DUPLICATED_LABEL_ACTION: __2("Take me there", "elementor"),
558
- DUPLICATED_LABEL_ACTION_MESSAGE: __2("Please rename the variables.", "elementor"),
559
- UNEXPECTED_ERROR_ACTION_MESSAGE: __2("Try saving your variables again.", "elementor")
560
- }
561
- };
562
- var VARIABLE_LABEL_MAX_LENGTH = 50;
563
- var mapServerError = (error) => {
564
- if (error?.response?.data?.code === "duplicated_label") {
565
- return {
566
- field: "label",
567
- message: ERROR_MESSAGES.DUPLICATED_LABEL
568
- };
569
- }
570
- if (error?.response?.data?.code === "batch_duplicated_label") {
571
- const errorData = error?.response?.data?.data ?? {};
572
- const count = Object.keys(errorData).length;
573
- const name = count === 1 ? "name" : "names";
574
- const duplicatedIds = Object.keys(errorData);
575
- return {
576
- field: "label",
577
- message: ERROR_MESSAGES.BATCH.DUPLICATED_LABELS(count, name),
578
- severity: "error",
579
- IconComponent: AlertTriangleFilledIcon,
580
- action: {
581
- label: ERROR_MESSAGES.BATCH.DUPLICATED_LABEL_ACTION,
582
- message: ERROR_MESSAGES.BATCH.DUPLICATED_LABEL_ACTION_MESSAGE,
583
- data: {
584
- duplicatedIds
585
- }
586
- }
587
- };
588
- }
589
- if (error?.response?.data?.code === "batch_operation_failed") {
590
- return {
591
- field: "label",
592
- message: ERROR_MESSAGES.BATCH.UNEXPECTED_ERROR,
593
- severity: "secondary",
594
- IconComponent: InfoCircleFilledIcon,
595
- action: {
596
- message: ERROR_MESSAGES.BATCH.UNEXPECTED_ERROR_ACTION_MESSAGE
597
- }
598
- };
599
- }
600
- return void 0;
601
- };
602
- var validateLabel = (name, variables) => {
603
- if (!name.trim()) {
604
- return ERROR_MESSAGES.MISSING_VARIABLE_NAME;
605
- }
606
- const allowedChars = /^[a-zA-Z0-9_-]+$/;
607
- if (!allowedChars.test(name)) {
608
- return ERROR_MESSAGES.INVALID_CHARACTERS;
609
- }
610
- const hasAlphanumeric = /[a-zA-Z0-9]/;
611
- if (!hasAlphanumeric.test(name)) {
612
- return ERROR_MESSAGES.NO_NON_SPECIAL_CHARACTER;
613
- }
614
- if (VARIABLE_LABEL_MAX_LENGTH < name.length) {
615
- return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
616
- }
617
- if (Object.values(variables ?? {}).some((variable) => variable.label === name)) {
618
- return ERROR_MESSAGES.DUPLICATED_LABEL;
619
- }
620
- return "";
621
- };
622
- var labelHint = (name) => {
623
- const hintThreshold = VARIABLE_LABEL_MAX_LENGTH * 0.8 - 1;
624
- if (hintThreshold < name.length) {
625
- return ERROR_MESSAGES.VARIABLE_LABEL_MAX_LENGTH;
592
+ if (result.type === "create") {
593
+ storage.add(variableId, result.variable);
594
+ } else {
595
+ storage.update(variableId, result.variable);
596
+ }
597
+ styleVariablesRepository.update({
598
+ [variableId]: result.variable
599
+ });
600
+ }
601
+ });
602
+ }
603
+ return {
604
+ success: true,
605
+ watermark,
606
+ operations: operations.length
607
+ };
608
+ });
626
609
  }
627
- return "";
628
610
  };
629
- var validateValue = (value) => {
630
- if (!value.trim()) {
631
- return ERROR_MESSAGES.MISSING_VARIABLE_VALUE;
611
+ var handleWatermark = (operation, newWatermark) => {
612
+ if (storage.watermarkDiff(operation, newWatermark)) {
613
+ setTimeout(() => service.load(), 500);
632
614
  }
633
- return "";
615
+ storage.watermark(newWatermark);
634
616
  };
635
617
 
636
- // src/variables-registry/create-variable-type-registry.ts
637
- import {
638
- stylesInheritanceTransformersRegistry,
639
- styleTransformersRegistry
640
- } from "@elementor/editor-canvas";
641
-
642
- // src/transformers/inheritance-transformer.tsx
643
- import * as React from "react";
644
- import { createTransformer } from "@elementor/editor-canvas";
645
- import { Stack, Typography } from "@elementor/ui";
646
- import { __ as __3 } from "@wordpress/i18n";
647
-
648
- // src/components/ui/color-indicator.tsx
649
- import { styled, UnstableColorIndicator } from "@elementor/ui";
650
- var ColorIndicator = styled(UnstableColorIndicator)(({ theme }) => ({
651
- borderRadius: `${theme.shape.borderRadius / 2}px`,
652
- marginRight: theme.spacing(0.25)
653
- }));
654
-
655
- // src/prop-types/color-variable-prop-type.ts
656
- import { createPropUtils as createPropUtils2 } from "@elementor/editor-props";
657
- import { z as z2 } from "@elementor/schema";
658
- var colorVariablePropTypeUtil = createPropUtils2("global-color-variable", z2.string());
659
-
660
618
  // src/transformers/utils/resolve-css-variable.ts
661
619
  var resolveCssVariable = (id2, variable) => {
662
620
  let name = id2;
@@ -1267,7 +1225,12 @@ var TRACKING_DATA = {
1267
1225
  location_l1: "create variable menu"
1268
1226
  };
1269
1227
  var SIZE = "tiny";
1270
- var VariableManagerCreateMenu = ({ variables, onCreate, menuState }) => {
1228
+ var VariableManagerCreateMenu = ({
1229
+ variables,
1230
+ onCreate,
1231
+ menuState,
1232
+ outlinedTrigger = false
1233
+ }) => {
1271
1234
  const buttonRef = useRef2(null);
1272
1235
  const variableTypes = getVariableTypes();
1273
1236
  const menuOptionConfigs = useMemo2(
@@ -1286,6 +1249,7 @@ var VariableManagerCreateMenu = ({ variables, onCreate, menuState }) => {
1286
1249
  ...bindTrigger(menuState),
1287
1250
  ref: buttonRef,
1288
1251
  size: SIZE,
1252
+ variant: outlinedTrigger ? "outlined" : void 0,
1289
1253
  "aria-label": __8("Add variable", "elementor")
1290
1254
  },
1291
1255
  /* @__PURE__ */ React7.createElement(PlusIcon, { fontSize: SIZE })
@@ -1371,7 +1335,7 @@ var getDefaultName = (variables, baseName) => {
1371
1335
 
1372
1336
  // src/components/variables-manager/variables-manager-table.tsx
1373
1337
  import * as React13 from "react";
1374
- import { useEffect as useEffect3, useRef as useRef6 } from "react";
1338
+ import { useEffect as useEffect2, useRef as useRef6 } from "react";
1375
1339
  import {
1376
1340
  Table,
1377
1341
  TableBody,
@@ -1496,7 +1460,7 @@ var LabelField = ({
1496
1460
 
1497
1461
  // src/components/variables-manager/variable-editable-cell.tsx
1498
1462
  import * as React10 from "react";
1499
- import { useCallback as useCallback5, useEffect as useEffect2, useRef as useRef4, useState as useState5 } from "react";
1463
+ import { useCallback as useCallback5, useEffect, useRef as useRef4, useState as useState5 } from "react";
1500
1464
  import { ClickAwayListener, Stack as Stack4 } from "@elementor/ui";
1501
1465
  var VariableEditableCell = React10.memo(
1502
1466
  ({
@@ -1524,10 +1488,10 @@ var VariableEditableCell = React10.memo(
1524
1488
  }
1525
1489
  setIsEditing(false);
1526
1490
  }, [value, onChange, fieldType, labelFieldError, valueFieldError]);
1527
- useEffect2(() => {
1491
+ useEffect(() => {
1528
1492
  onRowRef?.(rowRef?.current);
1529
1493
  }, [onRowRef]);
1530
- useEffect2(() => {
1494
+ useEffect(() => {
1531
1495
  if (autoEdit && !isEditing && !disabled) {
1532
1496
  setIsEditing(true);
1533
1497
  onAutoEditComplete?.();
@@ -1868,7 +1832,7 @@ var VariablesManagerTable = ({
1868
1832
  }) => {
1869
1833
  const tableContainerRef = useRef6(null);
1870
1834
  const variableRowRefs = useRef6(/* @__PURE__ */ new Map());
1871
- useEffect3(() => {
1835
+ useEffect2(() => {
1872
1836
  if (autoEditVariableId && tableContainerRef.current) {
1873
1837
  const rowElement = variableRowRefs.current.get(autoEditVariableId);
1874
1838
  if (rowElement) {
@@ -1974,8 +1938,33 @@ var { panel, usePanelActions } = createPanel({
1974
1938
  },
1975
1939
  isOpenPreviousElement: true
1976
1940
  });
1941
+ function VariablesManagerPanelEmbedded({
1942
+ onRequestClose,
1943
+ onExposeCloseAttempt
1944
+ }) {
1945
+ return /* @__PURE__ */ React14.createElement(
1946
+ VariablesManagerPanelRoot,
1947
+ {
1948
+ embedded: true,
1949
+ onRequestClose,
1950
+ onExposeCloseAttempt
1951
+ }
1952
+ );
1953
+ }
1977
1954
  function VariablesManagerPanel() {
1978
- const { close: closePanel } = usePanelActions();
1955
+ return /* @__PURE__ */ React14.createElement(VariablesManagerPanelRoot, null);
1956
+ }
1957
+ function VariablesManagerPanelRoot({
1958
+ embedded = false,
1959
+ onRequestClose,
1960
+ onExposeCloseAttempt
1961
+ } = {}) {
1962
+ const { close: closeStandalonePanel } = usePanelActions();
1963
+ const closePanel = useMemo3(
1964
+ () => embedded ? onRequestClose ?? (async () => {
1965
+ }) : closeStandalonePanel,
1966
+ [embedded, onRequestClose, closeStandalonePanel]
1967
+ );
1979
1968
  const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
1980
1969
  const [isStopSyncSuppressed] = useSuppressedMessage(STOP_SYNC_MESSAGE_KEY);
1981
1970
  const createMenuState = usePopupState2({
@@ -2004,13 +1993,20 @@ function VariablesManagerPanel() {
2004
1993
  const [stopSyncConfirmation, setStopSyncConfirmation] = useState6(null);
2005
1994
  const [serverError, setServerError] = useState6(null);
2006
1995
  usePreventUnload(isDirty);
2007
- const handleClosePanel = () => {
1996
+ const handleClosePanel = useCallback6(() => {
2008
1997
  if (isDirty) {
2009
1998
  openSaveChangesDialog();
2010
1999
  return;
2011
2000
  }
2012
- closePanel();
2013
- };
2001
+ void closePanel();
2002
+ }, [isDirty, openSaveChangesDialog, closePanel]);
2003
+ useEffect3(() => {
2004
+ if (!embedded || !onExposeCloseAttempt) {
2005
+ return;
2006
+ }
2007
+ onExposeCloseAttempt(() => handleClosePanel());
2008
+ return () => onExposeCloseAttempt(null);
2009
+ }, [embedded, onExposeCloseAttempt, handleClosePanel]);
2014
2010
  const handleCreateVariable = useCallback6(
2015
2011
  (type, defaultName, defaultValue) => {
2016
2012
  const newId = createVariable2(type, defaultName, defaultValue);
@@ -2128,82 +2124,57 @@ function VariablesManagerPanel() {
2128
2124
  [variables, handleStartSync, handleStopSync, duplicateVariable, startAutoEdit]
2129
2125
  );
2130
2126
  const hasVariables = Object.keys(variables).length > 0;
2131
- return /* @__PURE__ */ React14.createElement(ThemeProvider, null, /* @__PURE__ */ React14.createElement(Panel, null, /* @__PURE__ */ React14.createElement(
2132
- PanelHeader,
2127
+ const variablesSearchFieldSx = embedded ? {
2128
+ flex: 1,
2129
+ minWidth: 0,
2130
+ px: 0,
2131
+ py: 0,
2132
+ display: "flex",
2133
+ alignItems: "center",
2134
+ alignSelf: "stretch"
2135
+ } : {
2136
+ display: "flex",
2137
+ flex: 1
2138
+ };
2139
+ const searchField = /* @__PURE__ */ React14.createElement(
2140
+ SearchField,
2133
2141
  {
2134
- sx: {
2135
- height: "unset"
2136
- }
2137
- },
2138
- /* @__PURE__ */ React14.createElement(Stack6, { width: "100%", direction: "column", alignItems: "center" }, /* @__PURE__ */ React14.createElement(Stack6, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React14.createElement(Stack6, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React14.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React14.createElement(ColorFilterIcon, { fontSize: "inherit" }), __10("Variables Manager", "elementor"))), /* @__PURE__ */ React14.createElement(Stack6, { direction: "row", gap: 0.5, alignItems: "center" }, /* @__PURE__ */ React14.createElement(
2139
- VariableManagerCreateMenu,
2140
- {
2141
- onCreate: handleCreateVariable,
2142
- variables,
2143
- menuState: createMenuState
2144
- }
2145
- ), /* @__PURE__ */ React14.createElement(
2146
- CloseButton,
2147
- {
2148
- "aria-label": "Close",
2149
- slotProps: { icon: { fontSize: SIZE } },
2150
- onClick: () => {
2151
- handleClosePanel();
2152
- }
2153
- }
2154
- ))), /* @__PURE__ */ React14.createElement(Stack6, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React14.createElement(
2155
- SearchField,
2156
- {
2157
- sx: {
2158
- display: "flex",
2159
- flex: 1
2160
- },
2161
- placeholder: __10("Search", "elementor"),
2162
- value: searchValue,
2163
- onSearch: handleSearch
2164
- }
2165
- )), /* @__PURE__ */ React14.createElement(Divider, { sx: { width: "100%" } }))
2166
- ), /* @__PURE__ */ React14.createElement(
2167
- PanelBody,
2142
+ placeholder: __10("Search", "elementor"),
2143
+ value: searchValue,
2144
+ onSearch: handleSearch,
2145
+ sx: variablesSearchFieldSx
2146
+ }
2147
+ );
2148
+ const bodyInner = /* @__PURE__ */ React14.createElement(React14.Fragment, null, hasVariables && /* @__PURE__ */ React14.createElement(
2149
+ VariablesManagerTable,
2168
2150
  {
2169
- sx: {
2170
- display: "flex",
2171
- flexDirection: "column",
2172
- height: "100%"
2173
- }
2174
- },
2175
- hasVariables && /* @__PURE__ */ React14.createElement(
2176
- VariablesManagerTable,
2177
- {
2178
- menuActions: buildMenuActions,
2179
- variables,
2180
- onChange: handleOnChange,
2181
- autoEditVariableId,
2182
- onAutoEditComplete: handleAutoEditComplete,
2183
- onFieldError: setIsSaveDisabled
2184
- }
2185
- ),
2186
- !hasVariables && searchValue && /* @__PURE__ */ React14.createElement(
2187
- NoSearchResults,
2188
- {
2189
- searchValue,
2190
- onClear: () => handleSearch(""),
2191
- icon: /* @__PURE__ */ React14.createElement(ColorFilterIcon, { fontSize: "large" })
2192
- }
2193
- ),
2194
- !hasVariables && !searchValue && /* @__PURE__ */ React14.createElement(
2195
- EmptyState,
2196
- {
2197
- title: __10("Create your first variable", "elementor"),
2198
- message: __10(
2199
- "Variables are saved attributes that you can apply anywhere on your site.",
2200
- "elementor"
2201
- ),
2202
- icon: /* @__PURE__ */ React14.createElement(ColorFilterIcon, { fontSize: "large" }),
2203
- onAdd: createMenuState.open
2204
- }
2205
- )
2206
- ), /* @__PURE__ */ React14.createElement(PanelFooter, null, /* @__PURE__ */ React14.createElement(
2151
+ menuActions: buildMenuActions,
2152
+ variables,
2153
+ onChange: handleOnChange,
2154
+ autoEditVariableId,
2155
+ onAutoEditComplete: handleAutoEditComplete,
2156
+ onFieldError: setIsSaveDisabled
2157
+ }
2158
+ ), !hasVariables && searchValue && /* @__PURE__ */ React14.createElement(
2159
+ NoSearchResults,
2160
+ {
2161
+ searchValue,
2162
+ onClear: () => handleSearch(""),
2163
+ icon: /* @__PURE__ */ React14.createElement(ColorFilterIcon, { fontSize: "large" })
2164
+ }
2165
+ ), !hasVariables && !searchValue && /* @__PURE__ */ React14.createElement(
2166
+ EmptyState,
2167
+ {
2168
+ title: __10("Create your first variable", "elementor"),
2169
+ message: __10(
2170
+ "Variables are saved attributes that you can apply anywhere on your site.",
2171
+ "elementor"
2172
+ ),
2173
+ icon: /* @__PURE__ */ React14.createElement(ColorFilterIcon, { fontSize: "large" }),
2174
+ onAdd: createMenuState.open
2175
+ }
2176
+ ));
2177
+ const saveFooter = /* @__PURE__ */ React14.createElement(PanelFooter, null, /* @__PURE__ */ React14.createElement(
2207
2178
  Infotip,
2208
2179
  {
2209
2180
  placement: "right",
@@ -2247,7 +2218,8 @@ function VariablesManagerPanel() {
2247
2218
  },
2248
2219
  __10("Save changes", "elementor")
2249
2220
  )
2250
- ))), deleteConfirmation && /* @__PURE__ */ React14.createElement(
2221
+ ));
2222
+ const dialogs = /* @__PURE__ */ React14.createElement(React14.Fragment, null, deleteConfirmation && /* @__PURE__ */ React14.createElement(
2251
2223
  DeleteConfirmationDialog,
2252
2224
  {
2253
2225
  open: true,
@@ -2273,7 +2245,7 @@ function VariablesManagerPanel() {
2273
2245
  label: __10("Discard", "elementor"),
2274
2246
  action: () => {
2275
2247
  closeSaveChangesDialog();
2276
- closePanel();
2248
+ void closePanel();
2277
2249
  }
2278
2250
  },
2279
2251
  confirm: {
@@ -2282,16 +2254,104 @@ function VariablesManagerPanel() {
2282
2254
  const result = await handleSaveClick();
2283
2255
  closeSaveChangesDialog();
2284
2256
  if (result?.success) {
2285
- closePanel();
2257
+ void closePanel();
2286
2258
  }
2287
2259
  }
2288
2260
  }
2289
2261
  }
2290
2262
  }
2291
2263
  )));
2264
+ const panelChrome = embedded ? /* @__PURE__ */ React14.createElement(
2265
+ Stack6,
2266
+ {
2267
+ direction: "column",
2268
+ sx: {
2269
+ height: "100%",
2270
+ width: "100%",
2271
+ flex: 1,
2272
+ minHeight: 0,
2273
+ overflow: "hidden"
2274
+ }
2275
+ },
2276
+ /* @__PURE__ */ React14.createElement(
2277
+ Stack6,
2278
+ {
2279
+ direction: "row",
2280
+ alignItems: "center",
2281
+ spacing: 1,
2282
+ width: "100%",
2283
+ sx: {
2284
+ flexShrink: 0,
2285
+ px: 2,
2286
+ pb: 1
2287
+ }
2288
+ },
2289
+ searchField,
2290
+ /* @__PURE__ */ React14.createElement(Box2, { sx: { display: "flex", flexShrink: 0, alignItems: "center" } }, /* @__PURE__ */ React14.createElement(
2291
+ VariableManagerCreateMenu,
2292
+ {
2293
+ outlinedTrigger: true,
2294
+ onCreate: handleCreateVariable,
2295
+ variables,
2296
+ menuState: createMenuState
2297
+ }
2298
+ ))
2299
+ ),
2300
+ /* @__PURE__ */ React14.createElement(Divider, { sx: { width: "100%" } }),
2301
+ /* @__PURE__ */ React14.createElement(
2302
+ PanelBody,
2303
+ {
2304
+ sx: {
2305
+ display: "flex",
2306
+ flexDirection: "column",
2307
+ flex: 1,
2308
+ minHeight: 0,
2309
+ overflow: "hidden"
2310
+ }
2311
+ },
2312
+ bodyInner
2313
+ ),
2314
+ saveFooter
2315
+ ) : /* @__PURE__ */ React14.createElement(Panel, null, /* @__PURE__ */ React14.createElement(
2316
+ PanelHeader,
2317
+ {
2318
+ sx: {
2319
+ height: "unset"
2320
+ }
2321
+ },
2322
+ /* @__PURE__ */ React14.createElement(Stack6, { width: "100%", direction: "column", alignItems: "center" }, /* @__PURE__ */ React14.createElement(Stack6, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React14.createElement(Stack6, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React14.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React14.createElement(ColorFilterIcon, { fontSize: "inherit" }), __10("Variables Manager", "elementor"))), /* @__PURE__ */ React14.createElement(Stack6, { direction: "row", gap: 0.5, alignItems: "center" }, /* @__PURE__ */ React14.createElement(
2323
+ VariableManagerCreateMenu,
2324
+ {
2325
+ onCreate: handleCreateVariable,
2326
+ variables,
2327
+ menuState: createMenuState
2328
+ }
2329
+ ), /* @__PURE__ */ React14.createElement(
2330
+ CloseButton,
2331
+ {
2332
+ "aria-label": "Close",
2333
+ slotProps: { icon: { fontSize: SIZE } },
2334
+ onClick: () => {
2335
+ handleClosePanel();
2336
+ }
2337
+ }
2338
+ ))), /* @__PURE__ */ React14.createElement(Stack6, { width: "100%", direction: "row", gap: 1 }, searchField), /* @__PURE__ */ React14.createElement(Divider, { sx: { width: "100%" } }))
2339
+ ), /* @__PURE__ */ React14.createElement(
2340
+ PanelBody,
2341
+ {
2342
+ sx: {
2343
+ display: "flex",
2344
+ flexDirection: "column",
2345
+ height: "100%"
2346
+ }
2347
+ },
2348
+ bodyInner
2349
+ ), saveFooter);
2350
+ const core = /* @__PURE__ */ React14.createElement(React14.Fragment, null, panelChrome, dialogs);
2351
+ return embedded ? core : /* @__PURE__ */ React14.createElement(ThemeProvider, null, core);
2292
2352
  }
2293
2353
  var usePreventUnload = (isDirty) => {
2294
- useEffect4(() => {
2354
+ useEffect3(() => {
2295
2355
  const handleBeforeUnload = (event) => {
2296
2356
  if (isDirty) {
2297
2357
  event.preventDefault();
@@ -2322,7 +2382,45 @@ var StopSyncConfirmationDialog = ({ open, onClose, onConfirm }) => {
2322
2382
  ));
2323
2383
  };
2324
2384
 
2385
+ // src/init.ts
2386
+ import { injectIntoLogic, injectIntoTop } from "@elementor/editor";
2387
+ import { registerControlReplacement } from "@elementor/editor-controls";
2388
+ import { getMCPByDomain } from "@elementor/editor-mcp";
2389
+ import { __registerPanel as registerPanel } from "@elementor/editor-panels";
2390
+ import { isTransformable as isTransformable2 } from "@elementor/editor-props";
2391
+ import { isExperimentActive as isExperimentActive2 } from "@elementor/editor-v1-adapters";
2392
+ import { controlActionsMenu } from "@elementor/menus";
2393
+
2394
+ // src/components/global-styles-import-listener.tsx
2395
+ import { useEffect as useEffect4 } from "react";
2396
+ import { GLOBAL_STYLES_IMPORTED_EVENT } from "@elementor/editor-canvas";
2397
+ function GlobalStylesImportListener() {
2398
+ useEffect4(() => {
2399
+ const handleGlobalStylesImported = (event) => {
2400
+ const importedVars = event.detail?.global_variables;
2401
+ if (!importedVars) {
2402
+ return;
2403
+ }
2404
+ if (importedVars.data && typeof importedVars.data === "object") {
2405
+ styleVariablesRepository.update(importedVars.data);
2406
+ }
2407
+ service.load();
2408
+ };
2409
+ window.addEventListener(GLOBAL_STYLES_IMPORTED_EVENT, handleGlobalStylesImported);
2410
+ return () => {
2411
+ window.removeEventListener(GLOBAL_STYLES_IMPORTED_EVENT, handleGlobalStylesImported);
2412
+ };
2413
+ }, []);
2414
+ return null;
2415
+ }
2416
+
2325
2417
  // src/components/open-panel-from-event.tsx
2418
+ import { useEffect as useEffect5, useRef as useRef7, useState as useState7 } from "react";
2419
+ import {
2420
+ __privateListenTo as listenTo,
2421
+ __privateOpenRoute as openRoute,
2422
+ routeOpenEvent
2423
+ } from "@elementor/editor-v1-adapters";
2326
2424
  var EVENT_NAME = "elementor/open-variables-manager";
2327
2425
  var DEFAULT_PANEL_ROUTE = "panel/elements/categories";
2328
2426
  function OpenPanelFromEvent() {
@@ -2392,7 +2490,7 @@ import { useId, useRef as useRef9 } from "react";
2392
2490
  import * as React24 from "react";
2393
2491
  import { useBoundProp as useBoundProp6 } from "@elementor/editor-controls";
2394
2492
  import { ColorFilterIcon as ColorFilterIcon3 } from "@elementor/icons";
2395
- import { bindPopover, bindTrigger as bindTrigger3, Box as Box5, Popover, usePopupState as usePopupState3 } from "@elementor/ui";
2493
+ import { bindPopover, bindTrigger as bindTrigger3, Box as Box6, Popover, usePopupState as usePopupState3 } from "@elementor/ui";
2396
2494
 
2397
2495
  // src/utils/unlink-variable.ts
2398
2496
  function transformValueBeforeUnlink(variable, propTypeKey) {
@@ -2418,11 +2516,11 @@ import { isExperimentActive } from "@elementor/editor-v1-adapters";
2418
2516
  // src/context/variable-selection-popover.context.tsx
2419
2517
  import * as React15 from "react";
2420
2518
  import { createContext as createContext2, useContext as useContext2, useState as useState8 } from "react";
2421
- import { Box as Box2 } from "@elementor/ui";
2519
+ import { Box as Box3 } from "@elementor/ui";
2422
2520
  var PopoverContentRefContext = createContext2(null);
2423
2521
  var PopoverContentRefContextProvider = ({ children }) => {
2424
2522
  const [anchorRef, setAnchorRef] = useState8(null);
2425
- return /* @__PURE__ */ React15.createElement(PopoverContentRefContext.Provider, { value: anchorRef }, /* @__PURE__ */ React15.createElement(Box2, { ref: setAnchorRef }, children));
2523
+ return /* @__PURE__ */ React15.createElement(PopoverContentRefContext.Provider, { value: anchorRef }, /* @__PURE__ */ React15.createElement(Box3, { ref: setAnchorRef }, children));
2426
2524
  };
2427
2525
  var usePopoverContentRef = () => {
2428
2526
  return useContext2(PopoverContentRefContext);
@@ -2876,14 +2974,14 @@ import { __ as __15, sprintf as sprintf3 } from "@wordpress/i18n";
2876
2974
  import * as React20 from "react";
2877
2975
  import { EllipsisWithTooltip as EllipsisWithTooltip2 } from "@elementor/editor-ui";
2878
2976
  import { EditIcon } from "@elementor/icons";
2879
- import { Box as Box3, IconButton as IconButton6, ListItemIcon, Tooltip as Tooltip2, Typography as Typography9 } from "@elementor/ui";
2977
+ import { Box as Box4, IconButton as IconButton6, ListItemIcon, Tooltip as Tooltip2, Typography as Typography9 } from "@elementor/ui";
2880
2978
  import { __ as __14 } from "@wordpress/i18n";
2881
2979
  var SIZE4 = "tiny";
2882
2980
  var EDIT_LABEL = __14("Edit variable", "elementor");
2883
2981
  var MenuItemContent = ({ item, disabled = false }) => {
2884
2982
  const onEdit = item.onEdit;
2885
2983
  return /* @__PURE__ */ React20.createElement(React20.Fragment, null, /* @__PURE__ */ React20.createElement(ListItemIcon, { sx: { color: disabled ? "text.disabled" : "inherit" } }, item.icon), /* @__PURE__ */ React20.createElement(
2886
- Box3,
2984
+ Box4,
2887
2985
  {
2888
2986
  sx: {
2889
2987
  flex: 1,
@@ -3158,9 +3256,15 @@ var VIEW_EDIT = "edit";
3158
3256
  var VariableSelectionPopover = ({ closePopover, propTypeKey, selectedVariable }) => {
3159
3257
  const [currentView, setCurrentView] = useState13(VIEW_LIST);
3160
3258
  const [editId, setEditId] = useState13("");
3161
- const { open } = usePanelActions();
3259
+ const { open: openStandaloneVariablesPanel } = usePanelActions();
3162
3260
  const onSettingsAvailable = isExperimentActive("e_variables_manager") ? () => {
3163
- open();
3261
+ if (isExperimentActive("e_editor_design_system_panel")) {
3262
+ window.dispatchEvent(
3263
+ new CustomEvent("elementor/toggle-design-system", { detail: { tab: "variables" } })
3264
+ );
3265
+ } else {
3266
+ openStandaloneVariablesPanel();
3267
+ }
3164
3268
  } : void 0;
3165
3269
  return /* @__PURE__ */ React22.createElement(VariableTypeProvider, { propTypeKey }, /* @__PURE__ */ React22.createElement(PopoverContentRefContextProvider, null, RenderView({
3166
3270
  propTypeKey,
@@ -3175,7 +3279,7 @@ var VariableSelectionPopover = ({ closePopover, propTypeKey, selectedVariable })
3175
3279
  };
3176
3280
  function RenderView(props) {
3177
3281
  const userPermissions = usePermissions();
3178
- const userQuotaPremissions = useQuotaPermissions(props.propTypeKey);
3282
+ const userQuotaPermissions = useQuotaPermissions(props.propTypeKey);
3179
3283
  const handlers = {
3180
3284
  onClose: () => {
3181
3285
  props.closePopover();
@@ -3216,7 +3320,7 @@ function RenderView(props) {
3216
3320
  onAdd: handlers.onAdd,
3217
3321
  onEdit: handlers.onEdit,
3218
3322
  onSettings: handlers.onSettings,
3219
- disabled: !userQuotaPremissions.canAdd()
3323
+ disabled: !userQuotaPermissions.canAdd()
3220
3324
  }
3221
3325
  );
3222
3326
  }
@@ -3240,7 +3344,7 @@ function RenderView(props) {
3240
3344
  // src/components/ui/tags/assigned-tag.tsx
3241
3345
  import * as React23 from "react";
3242
3346
  import { DetachIcon } from "@elementor/icons";
3243
- import { Box as Box4, IconButton as IconButton8, Stack as Stack7, Tooltip as Tooltip4, Typography as Typography10, UnstableTag as Tag } from "@elementor/ui";
3347
+ import { Box as Box5, IconButton as IconButton8, Stack as Stack7, Tooltip as Tooltip4, Typography as Typography10, UnstableTag as Tag } from "@elementor/ui";
3244
3348
  import { __ as __16 } from "@wordpress/i18n";
3245
3349
  var SIZE6 = "tiny";
3246
3350
  var UNLINK_LABEL = __16("Unlink variable", "elementor");
@@ -3257,7 +3361,7 @@ var AssignedTag = ({ startIcon, label, onUnlink, ...props }) => {
3257
3361
  fullWidth: true,
3258
3362
  showActionsOnHover: true,
3259
3363
  startIcon: /* @__PURE__ */ React23.createElement(Stack7, { gap: 0.5, direction: "row", alignItems: "center" }, startIcon),
3260
- label: /* @__PURE__ */ React23.createElement(Box4, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React23.createElement(Typography10, { sx: { lineHeight: 1.34 }, variant: "caption", noWrap: true }, label)),
3364
+ label: /* @__PURE__ */ React23.createElement(Box5, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React23.createElement(Typography10, { sx: { lineHeight: 1.34 }, variant: "caption", noWrap: true }, label)),
3261
3365
  actions,
3262
3366
  ...props
3263
3367
  }
@@ -3276,7 +3380,7 @@ var AssignedVariable = ({ variable, propTypeKey }) => {
3276
3380
  });
3277
3381
  const unlinkVariable = createUnlinkHandler(variable, propTypeKey, setValue);
3278
3382
  const StartIcon = startIcon || (() => null);
3279
- return /* @__PURE__ */ React24.createElement(Box5, { ref: anchorRef }, /* @__PURE__ */ React24.createElement(
3383
+ return /* @__PURE__ */ React24.createElement(Box6, { ref: anchorRef }, /* @__PURE__ */ React24.createElement(
3280
3384
  AssignedTag,
3281
3385
  {
3282
3386
  label: variable.label,
@@ -3311,7 +3415,7 @@ var AssignedVariable = ({ variable, propTypeKey }) => {
3311
3415
  import * as React28 from "react";
3312
3416
  import { useId as useId2, useRef as useRef10, useState as useState15 } from "react";
3313
3417
  import { useBoundProp as useBoundProp8 } from "@elementor/editor-controls";
3314
- import { Backdrop, bindPopover as bindPopover2, Box as Box7, Infotip as Infotip2, Popover as Popover2, usePopupState as usePopupState4 } from "@elementor/ui";
3418
+ import { Backdrop, bindPopover as bindPopover2, Box as Box8, Infotip as Infotip2, Popover as Popover2, usePopupState as usePopupState4 } from "@elementor/ui";
3315
3419
  import { __ as __19 } from "@wordpress/i18n";
3316
3420
 
3317
3421
  // src/components/variable-restore.tsx
@@ -3458,7 +3562,7 @@ var DeletedVariableAlert = ({ onClose, onUnlink, onRestore, label }) => {
3458
3562
  // src/components/ui/tags/warning-variable-tag.tsx
3459
3563
  import * as React27 from "react";
3460
3564
  import { AlertTriangleFilledIcon as AlertTriangleFilledIcon4 } from "@elementor/icons";
3461
- import { Box as Box6, Chip, Tooltip as Tooltip5, Typography as Typography13 } from "@elementor/ui";
3565
+ import { Box as Box7, Chip, Tooltip as Tooltip5, Typography as Typography13 } from "@elementor/ui";
3462
3566
  var WarningVariableTag = React27.forwardRef(
3463
3567
  ({ label, suffix, onClick, icon, ...props }, ref) => {
3464
3568
  const displayText = suffix ? `${label} (${suffix})` : label;
@@ -3472,7 +3576,7 @@ var WarningVariableTag = React27.forwardRef(
3472
3576
  variant: "standard",
3473
3577
  onClick,
3474
3578
  icon: /* @__PURE__ */ React27.createElement(AlertTriangleFilledIcon4, null),
3475
- label: /* @__PURE__ */ React27.createElement(Tooltip5, { title: displayText, placement: "top" }, /* @__PURE__ */ React27.createElement(Box6, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React27.createElement(Typography13, { variant: "caption", noWrap: true, sx: { lineHeight: 1.34 } }, displayText))),
3579
+ label: /* @__PURE__ */ React27.createElement(Tooltip5, { title: displayText, placement: "top" }, /* @__PURE__ */ React27.createElement(Box7, { sx: { display: "inline-grid", minWidth: 0 } }, /* @__PURE__ */ React27.createElement(Typography13, { variant: "caption", noWrap: true, sx: { lineHeight: 1.34 } }, displayText))),
3476
3580
  sx: {
3477
3581
  height: (theme) => theme.spacing(3.5),
3478
3582
  borderRadius: (theme) => theme.spacing(1),
@@ -3522,7 +3626,7 @@ var DeletedVariable = ({ variable, propTypeKey }) => {
3522
3626
  const handleRestoreWithOverrides = () => {
3523
3627
  popupState.close();
3524
3628
  };
3525
- return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(Box7, { ref: deletedChipAnchorRef }, showInfotip && /* @__PURE__ */ React28.createElement(Backdrop, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React28.createElement(
3629
+ return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(Box8, { ref: deletedChipAnchorRef }, showInfotip && /* @__PURE__ */ React28.createElement(Backdrop, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React28.createElement(
3526
3630
  Infotip2,
3527
3631
  {
3528
3632
  color: "warning",
@@ -3584,7 +3688,7 @@ var DeletedVariable = ({ variable, propTypeKey }) => {
3584
3688
  import * as React30 from "react";
3585
3689
  import { useId as useId3, useRef as useRef11, useState as useState16 } from "react";
3586
3690
  import { useBoundProp as useBoundProp9 } from "@elementor/editor-controls";
3587
- import { Backdrop as Backdrop2, bindPopover as bindPopover3, Box as Box8, Infotip as Infotip3, Popover as Popover3, usePopupState as usePopupState5 } from "@elementor/ui";
3691
+ import { Backdrop as Backdrop2, bindPopover as bindPopover3, Box as Box9, Infotip as Infotip3, Popover as Popover3, usePopupState as usePopupState5 } from "@elementor/ui";
3588
3692
  import { __ as __21 } from "@wordpress/i18n";
3589
3693
 
3590
3694
  // src/components/ui/mismatch-variable-alert.tsx
@@ -3639,7 +3743,7 @@ var MismatchVariable = ({ variable }) => {
3639
3743
  setValue(null);
3640
3744
  };
3641
3745
  const showClearButton = !!value;
3642
- return /* @__PURE__ */ React30.createElement(Box8, { ref: anchorRef }, infotipVisible && /* @__PURE__ */ React30.createElement(Backdrop2, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React30.createElement(
3746
+ return /* @__PURE__ */ React30.createElement(Box9, { ref: anchorRef }, infotipVisible && /* @__PURE__ */ React30.createElement(Backdrop2, { open: true, onClick: closeInfotip, invisible: true }), /* @__PURE__ */ React30.createElement(
3643
3747
  Infotip3,
3644
3748
  {
3645
3749
  color: "warning",
@@ -3821,33 +3925,42 @@ var trackOpenVariablePopover = (path, variableType) => {
3821
3925
  import { z as z3 } from "@elementor/schema";
3822
3926
 
3823
3927
  // src/mcp/variables-resource.ts
3928
+ import { __privateListenTo as listenTo3, commandEndEvent } from "@elementor/editor-v1-adapters";
3824
3929
  var GLOBAL_VARIABLES_URI = "elementor://global-variables";
3930
+ var buildGlobalVariablesPayload = async () => {
3931
+ const merged = {};
3932
+ Object.entries(service.variables()).forEach(([id2, variable]) => {
3933
+ if (!variable.deleted) {
3934
+ merged[id2] = { ...variable, version: "v4" };
3935
+ }
3936
+ });
3937
+ return merged;
3938
+ };
3825
3939
  var initVariablesResource = (variablesMcpEntry, canvasMcpEntry) => {
3826
3940
  [canvasMcpEntry, variablesMcpEntry].forEach((entry) => {
3827
3941
  const { resource, sendResourceUpdated } = entry;
3942
+ const notifyGlobalVariablesUpdated = () => {
3943
+ sendResourceUpdated({
3944
+ uri: GLOBAL_VARIABLES_URI
3945
+ });
3946
+ };
3828
3947
  resource(
3829
3948
  "global-variables",
3830
3949
  GLOBAL_VARIABLES_URI,
3831
3950
  {
3832
- description: "List of Global variables. Defined as a key-value store (ID as key, global-variable object as value)"
3951
+ description: "Global variables available (v4)"
3833
3952
  },
3834
3953
  async () => {
3835
- const variables = {};
3836
- Object.entries(service.variables()).forEach(([id2, variable]) => {
3837
- if (!variable.deleted) {
3838
- variables[id2] = variable;
3839
- }
3840
- });
3954
+ const variables = await buildGlobalVariablesPayload();
3841
3955
  return {
3842
- contents: [{ uri: GLOBAL_VARIABLES_URI, text: JSON.stringify(variables) }]
3956
+ contents: [
3957
+ { uri: GLOBAL_VARIABLES_URI, mimeType: "application/json", text: JSON.stringify(variables) }
3958
+ ]
3843
3959
  };
3844
3960
  }
3845
3961
  );
3846
- window.addEventListener("variables:updated", () => {
3847
- sendResourceUpdated({
3848
- uri: GLOBAL_VARIABLES_URI
3849
- });
3850
- });
3962
+ window.addEventListener("variables:updated", notifyGlobalVariablesUpdated);
3963
+ listenTo3(commandEndEvent("document/save/update"), notifyGlobalVariablesUpdated);
3851
3964
  });
3852
3965
  };
3853
3966
 
@@ -3906,12 +4019,20 @@ function getServiceActions(svc) {
3906
4019
  if (!type || !label || !value) {
3907
4020
  throw new Error("Create requires type, label, and value");
3908
4021
  }
4022
+ const labelError = validateLabel(label);
4023
+ if (labelError) {
4024
+ throw new Error(labelError);
4025
+ }
3909
4026
  return svc.create({ type, label, value });
3910
4027
  },
3911
4028
  update({ id: id2, label, value }) {
3912
4029
  if (!id2 || !label || !value) {
3913
4030
  throw new Error("Update requires id, label, and value");
3914
4031
  }
4032
+ const labelError = validateLabel(label);
4033
+ if (labelError) {
4034
+ throw new Error(labelError);
4035
+ }
3915
4036
  return svc.update(id2, { label, value });
3916
4037
  },
3917
4038
  delete({ id: id2 }) {
@@ -3992,7 +4113,7 @@ var ColorField = ({ value, onChange, onValidationChange }) => {
3992
4113
 
3993
4114
  // src/components/fields/font-field.tsx
3994
4115
  import * as React36 from "react";
3995
- import { useId as useId4, useMemo as useMemo3, useRef as useRef13, useState as useState19 } from "react";
4116
+ import { useId as useId4, useMemo as useMemo4, useRef as useRef13, useState as useState19 } from "react";
3996
4117
  import { enqueueFont as enqueueFont2, ItemSelector, useFontFamilies } from "@elementor/editor-controls";
3997
4118
  import { useSectionWidth } from "@elementor/editor-ui";
3998
4119
  import { ChevronDownIcon, TextIcon } from "@elementor/icons";
@@ -4005,7 +4126,7 @@ var FontField = ({ value, onChange, onValidationChange }) => {
4005
4126
  const fontPopoverState = usePopupState6({ variant: "popover" });
4006
4127
  const fontFamilies = useFontFamilies();
4007
4128
  const sectionWidth = useSectionWidth();
4008
- const mapFontSubs = useMemo3(() => {
4129
+ const mapFontSubs = useMemo4(() => {
4009
4130
  return fontFamilies.map(({ label, fonts }) => ({
4010
4131
  label,
4011
4132
  items: fonts
@@ -4144,7 +4265,7 @@ import * as React38 from "react";
4144
4265
  import { useEffect as useEffect9, useState as useState20 } from "react";
4145
4266
  import {
4146
4267
  __privateUseListenTo as useListenTo,
4147
- commandEndEvent,
4268
+ commandEndEvent as commandEndEvent2,
4148
4269
  getCanvasIframeDocument
4149
4270
  } from "@elementor/editor-v1-adapters";
4150
4271
  import { Portal } from "@elementor/ui";
@@ -4161,7 +4282,7 @@ function StyleVariablesRenderer() {
4161
4282
  return /* @__PURE__ */ React38.createElement(Portal, { container }, /* @__PURE__ */ React38.createElement("style", { "data-e-style-id": "e-variables", key: wrappedCss }, wrappedCss));
4162
4283
  }
4163
4284
  function usePortalContainer() {
4164
- return useListenTo(commandEndEvent("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
4285
+ return useListenTo(commandEndEvent2("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
4165
4286
  }
4166
4287
  function useStyleVariables() {
4167
4288
  const [variables, setVariables] = useState20({});
@@ -4189,6 +4310,7 @@ import {
4189
4310
  backgroundColorOverlayPropTypeUtil,
4190
4311
  cssFilterFunctionPropUtil as cssFilterFunctionPropUtil2,
4191
4312
  dropShadowFilterPropTypeUtil as dropShadowFilterPropTypeUtil2,
4313
+ moveTransformPropTypeUtil as moveTransformPropTypeUtil2,
4192
4314
  selectionSizePropTypeUtil as selectionSizePropTypeUtil2,
4193
4315
  shadowPropTypeUtil as shadowPropTypeUtil2
4194
4316
  } from "@elementor/editor-props";
@@ -4198,10 +4320,11 @@ import * as React39 from "react";
4198
4320
  import {
4199
4321
  cssFilterFunctionPropUtil,
4200
4322
  dropShadowFilterPropTypeUtil,
4323
+ moveTransformPropTypeUtil,
4201
4324
  selectionSizePropTypeUtil,
4202
4325
  shadowPropTypeUtil
4203
4326
  } from "@elementor/editor-props";
4204
- import { Box as Box9 } from "@elementor/ui";
4327
+ import { Box as Box10 } from "@elementor/ui";
4205
4328
  import { __ as __27 } from "@wordpress/i18n";
4206
4329
 
4207
4330
  // src/utils/size-value.ts
@@ -4244,7 +4367,7 @@ var BackgroundRepeaterColorIndicator = ({ value }) => {
4244
4367
  };
4245
4368
  var BackgroundRepeaterLabel = ({ value }) => {
4246
4369
  const colorVariable = useColorVariable(value);
4247
- return /* @__PURE__ */ React39.createElement(Box9, { component: "span" }, colorVariable?.label);
4370
+ return /* @__PURE__ */ React39.createElement(Box10, { component: "span" }, colorVariable?.label);
4248
4371
  };
4249
4372
  var BoxShadowRepeaterColorIndicator = ({ value }) => {
4250
4373
  const colorVariable = useColorVariable(value);
@@ -4264,7 +4387,7 @@ var FilterSingleSizeRepeaterLabel = ({ value }) => {
4264
4387
  const args = cssFilterFunction?.args;
4265
4388
  const func = cssFilterFunction?.func?.value ?? "";
4266
4389
  const rendered = sizeValue(args?.value?.size);
4267
- return /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Box9, { component: "span", style: { textTransform: "capitalize" } }, `${func}: `), /* @__PURE__ */ React39.createElement(Box9, { component: "span" }, rendered));
4390
+ return /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Box10, { component: "span", style: { textTransform: "capitalize" } }, `${func}: `), /* @__PURE__ */ React39.createElement(Box10, { component: "span" }, rendered));
4268
4391
  };
4269
4392
  var FilterDropShadowRepeaterLabel = ({ value }) => {
4270
4393
  const { args } = cssFilterFunctionPropUtil.extract(value) || {};
@@ -4276,7 +4399,7 @@ var FilterDropShadowRepeaterLabel = ({ value }) => {
4276
4399
  labels.push(rendered);
4277
4400
  }
4278
4401
  }
4279
- return /* @__PURE__ */ React39.createElement(Box9, { component: "span" }, __27("Drop shadow:", "elementor"), " ", labels.join(" "));
4402
+ return /* @__PURE__ */ React39.createElement(Box10, { component: "span" }, __27("Drop shadow:", "elementor"), " ", labels.join(" "));
4280
4403
  };
4281
4404
  var BoxShadowRepeaterLabel = ({ value }) => {
4282
4405
  const { position, hOffset, vOffset, blur, spread } = shadowPropTypeUtil.extract(value) || {};
@@ -4288,7 +4411,21 @@ var BoxShadowRepeaterLabel = ({ value }) => {
4288
4411
  }
4289
4412
  }
4290
4413
  const positionLabel = position?.value || "outset";
4291
- return /* @__PURE__ */ React39.createElement(Box9, { component: "span", style: { textTransform: "capitalize" } }, positionLabel, ": ", labels.join(" "));
4414
+ return /* @__PURE__ */ React39.createElement(Box10, { component: "span", style: { textTransform: "capitalize" } }, positionLabel, ": ", labels.join(" "));
4415
+ };
4416
+ var TransformRepeaterLabel = ({ value }) => {
4417
+ const labels = [];
4418
+ if (moveTransformPropTypeUtil.isValid(value)) {
4419
+ labels.push(__27("Move:", "elementor"));
4420
+ const { x, y, z: z6 } = moveTransformPropTypeUtil.extract(value) || {};
4421
+ for (const val of [x, y, z6]) {
4422
+ const rendered = sizeValue(val);
4423
+ if (rendered) {
4424
+ labels.push(rendered);
4425
+ }
4426
+ }
4427
+ }
4428
+ return /* @__PURE__ */ React39.createElement(Box10, { component: "span" }, labels.join(" "));
4292
4429
  };
4293
4430
  var TransitionsSizeVariableLabel = ({ value: prop }) => {
4294
4431
  let label = "";
@@ -4301,7 +4438,7 @@ var TransitionsSizeVariableLabel = ({ value: prop }) => {
4301
4438
  }
4302
4439
  label += variable?.value;
4303
4440
  }
4304
- return /* @__PURE__ */ React39.createElement(Box9, { component: "span" }, label);
4441
+ return /* @__PURE__ */ React39.createElement(Box10, { component: "span" }, label);
4305
4442
  };
4306
4443
 
4307
4444
  // src/repeater-injections.ts
@@ -4309,6 +4446,7 @@ function registerRepeaterInjections() {
4309
4446
  backgroundOverlayRepeaterInjections();
4310
4447
  boxShadowRepeaterInjections();
4311
4448
  transitionsRepeaterInjections();
4449
+ transformRepeaterInjections();
4312
4450
  filterRepeaterInjections();
4313
4451
  }
4314
4452
  function backgroundOverlayRepeaterInjections() {
@@ -4345,6 +4483,19 @@ function boxShadowRepeaterInjections() {
4345
4483
  }
4346
4484
  });
4347
4485
  }
4486
+ function transformRepeaterInjections() {
4487
+ injectIntoRepeaterItemLabel({
4488
+ id: "transform-size-variables-label",
4489
+ component: TransformRepeaterLabel,
4490
+ condition: ({ value }) => {
4491
+ if (moveTransformPropTypeUtil2.isValid(value)) {
4492
+ const { x: xAxis, y: yAxis, z: zAxis } = moveTransformPropTypeUtil2.extract(value) || {};
4493
+ return hasAssignedSizeVariable(xAxis) || hasAssignedSizeVariable(yAxis) || hasAssignedSizeVariable(zAxis);
4494
+ }
4495
+ return false;
4496
+ }
4497
+ });
4498
+ }
4348
4499
  function transitionsRepeaterInjections() {
4349
4500
  injectIntoRepeaterItemLabel({
4350
4501
  id: "transition-size-variables-label",
@@ -4442,15 +4593,17 @@ function init() {
4442
4593
  id: "variables-import-listener",
4443
4594
  component: GlobalStylesImportListener
4444
4595
  });
4445
- injectIntoLogic({
4446
- id: "variables-open-panel-from-url",
4447
- component: OpenPanelFromUrl
4448
- });
4449
- injectIntoLogic({
4450
- id: "variables-open-panel-from-event",
4451
- component: OpenPanelFromEvent
4452
- });
4453
- registerPanel(panel);
4596
+ if (!isExperimentActive2("e_editor_design_system_panel")) {
4597
+ injectIntoLogic({
4598
+ id: "variables-open-panel-from-url",
4599
+ component: OpenPanelFromUrl
4600
+ });
4601
+ injectIntoLogic({
4602
+ id: "variables-open-panel-from-event",
4603
+ component: OpenPanelFromEvent
4604
+ });
4605
+ registerPanel(panel);
4606
+ }
4454
4607
  }
4455
4608
  function hasVariableAssigned(value) {
4456
4609
  if (isTransformable2(value)) {
@@ -4480,6 +4633,7 @@ var Utils = {
4480
4633
  export {
4481
4634
  GLOBAL_VARIABLES_URI,
4482
4635
  Utils,
4636
+ VariablesManagerPanelEmbedded,
4483
4637
  getMenuActionsForVariable,
4484
4638
  hasVariable,
4485
4639
  init,