@elementor/editor-variables 4.1.0-838 → 4.1.0-beta2
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.js +177 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +199 -68
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -15
- package/src/components/global-styles-import-listener.tsx +3 -14
- package/src/components/variables-manager/hooks/use-variables-manager-state.ts +34 -4
- package/src/components/variables-manager/ui/variable-table-row.tsx +1 -1
- package/src/components/variables-manager/variables-manager-panel.tsx +0 -1
- package/src/init.ts +9 -1
- package/src/mcp/index.ts +0 -9
- package/src/mcp/manage-variable-tool.ts +76 -18
- package/src/mcp/variable-tool-prompt.ts +85 -0
- package/src/mcp/variables-resource.ts +2 -2
- package/src/storage.ts +3 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/components/variables-manager/variables-manager-panel.tsx
|
|
2
2
|
import * as React14 from "react";
|
|
3
|
-
import { useCallback as useCallback6, useEffect as
|
|
3
|
+
import { useCallback as useCallback6, useEffect as useEffect4, useMemo as useMemo3, useState as useState6 } from "react";
|
|
4
4
|
import { useSuppressedMessage } from "@elementor/editor-current-user";
|
|
5
5
|
import {
|
|
6
6
|
__createPanel as createPanel,
|
|
@@ -310,12 +310,13 @@ var buildOperationsArray = (originalVariables, currentVariables, deletedVariable
|
|
|
310
310
|
// src/storage.ts
|
|
311
311
|
var STORAGE_KEY = "elementor-global-variables";
|
|
312
312
|
var STORAGE_WATERMARK_KEY = "elementor-global-variables-watermark";
|
|
313
|
+
var STORAGE_UPDATED_EVENT = "variables:updated";
|
|
313
314
|
var OP_RW = "RW";
|
|
314
315
|
var OP_RO = "RO";
|
|
315
316
|
var Storage = class {
|
|
316
317
|
state;
|
|
317
318
|
notifyChange() {
|
|
318
|
-
window.dispatchEvent(new Event(
|
|
319
|
+
window.dispatchEvent(new Event(STORAGE_UPDATED_EVENT));
|
|
319
320
|
}
|
|
320
321
|
constructor() {
|
|
321
322
|
this.state = {
|
|
@@ -871,7 +872,7 @@ var useErrorNavigation = () => {
|
|
|
871
872
|
};
|
|
872
873
|
|
|
873
874
|
// src/components/variables-manager/hooks/use-variables-manager-state.ts
|
|
874
|
-
import { useCallback as useCallback3, useState as useState2 } from "react";
|
|
875
|
+
import { useCallback as useCallback3, useEffect, useState as useState2 } from "react";
|
|
875
876
|
|
|
876
877
|
// src/hooks/use-prop-variables.ts
|
|
877
878
|
import { useMemo } from "react";
|
|
@@ -1035,10 +1036,30 @@ var useVariablesManagerState = () => {
|
|
|
1035
1036
|
const [isDirty, setIsDirty] = useState2(false);
|
|
1036
1037
|
const [isSaving, setIsSaving] = useState2(false);
|
|
1037
1038
|
const [searchValue, setSearchValue] = useState2("");
|
|
1039
|
+
useEffect(() => {
|
|
1040
|
+
const handleStorageUpdated = () => {
|
|
1041
|
+
setVariables(getVariables(false));
|
|
1042
|
+
setDeletedVariables([]);
|
|
1043
|
+
setIsDirty(false);
|
|
1044
|
+
};
|
|
1045
|
+
window.addEventListener(STORAGE_UPDATED_EVENT, handleStorageUpdated);
|
|
1046
|
+
return () => {
|
|
1047
|
+
window.removeEventListener(STORAGE_UPDATED_EVENT, handleStorageUpdated);
|
|
1048
|
+
};
|
|
1049
|
+
}, []);
|
|
1038
1050
|
const handleOnChange = useCallback3(
|
|
1039
1051
|
(newVariables) => {
|
|
1040
|
-
|
|
1041
|
-
|
|
1052
|
+
const hasChanges = Object.entries(newVariables).some(([id2, newVar]) => {
|
|
1053
|
+
const existingVar = variables[id2];
|
|
1054
|
+
if (!existingVar) {
|
|
1055
|
+
return true;
|
|
1056
|
+
}
|
|
1057
|
+
return existingVar.label !== newVar.label || existingVar.value !== newVar.value || existingVar.order !== newVar.order || existingVar.type !== newVar.type || (existingVar.sync_to_v3 ?? false) !== (newVar.sync_to_v3 ?? false);
|
|
1058
|
+
});
|
|
1059
|
+
if (hasChanges) {
|
|
1060
|
+
setVariables({ ...variables, ...newVariables });
|
|
1061
|
+
setIsDirty(true);
|
|
1062
|
+
}
|
|
1042
1063
|
},
|
|
1043
1064
|
[variables]
|
|
1044
1065
|
);
|
|
@@ -1335,7 +1356,7 @@ var getDefaultName = (variables, baseName) => {
|
|
|
1335
1356
|
|
|
1336
1357
|
// src/components/variables-manager/variables-manager-table.tsx
|
|
1337
1358
|
import * as React13 from "react";
|
|
1338
|
-
import { useEffect as
|
|
1359
|
+
import { useEffect as useEffect3, useRef as useRef6 } from "react";
|
|
1339
1360
|
import {
|
|
1340
1361
|
Table,
|
|
1341
1362
|
TableBody,
|
|
@@ -1460,7 +1481,7 @@ var LabelField = ({
|
|
|
1460
1481
|
|
|
1461
1482
|
// src/components/variables-manager/variable-editable-cell.tsx
|
|
1462
1483
|
import * as React10 from "react";
|
|
1463
|
-
import { useCallback as useCallback5, useEffect, useRef as useRef4, useState as useState5 } from "react";
|
|
1484
|
+
import { useCallback as useCallback5, useEffect as useEffect2, useRef as useRef4, useState as useState5 } from "react";
|
|
1464
1485
|
import { ClickAwayListener, Stack as Stack4 } from "@elementor/ui";
|
|
1465
1486
|
var VariableEditableCell = React10.memo(
|
|
1466
1487
|
({
|
|
@@ -1488,10 +1509,10 @@ var VariableEditableCell = React10.memo(
|
|
|
1488
1509
|
}
|
|
1489
1510
|
setIsEditing(false);
|
|
1490
1511
|
}, [value, onChange, fieldType, labelFieldError, valueFieldError]);
|
|
1491
|
-
|
|
1512
|
+
useEffect2(() => {
|
|
1492
1513
|
onRowRef?.(rowRef?.current);
|
|
1493
1514
|
}, [onRowRef]);
|
|
1494
|
-
|
|
1515
|
+
useEffect2(() => {
|
|
1495
1516
|
if (autoEdit && !isEditing && !disabled) {
|
|
1496
1517
|
setIsEditing(true);
|
|
1497
1518
|
onAutoEditComplete?.();
|
|
@@ -1776,7 +1797,7 @@ var VariableRow = (props) => {
|
|
|
1776
1797
|
value,
|
|
1777
1798
|
onChange,
|
|
1778
1799
|
onPropTypeKeyChange: (type) => {
|
|
1779
|
-
if (!isDisabled) {
|
|
1800
|
+
if (!isDisabled && type !== row.type) {
|
|
1780
1801
|
handleOnChange({
|
|
1781
1802
|
...variables,
|
|
1782
1803
|
[row.id]: { ...variables[row.id], type }
|
|
@@ -1832,7 +1853,7 @@ var VariablesManagerTable = ({
|
|
|
1832
1853
|
}) => {
|
|
1833
1854
|
const tableContainerRef = useRef6(null);
|
|
1834
1855
|
const variableRowRefs = useRef6(/* @__PURE__ */ new Map());
|
|
1835
|
-
|
|
1856
|
+
useEffect3(() => {
|
|
1836
1857
|
if (autoEditVariableId && tableContainerRef.current) {
|
|
1837
1858
|
const rowElement = variableRowRefs.current.get(autoEditVariableId);
|
|
1838
1859
|
if (rowElement) {
|
|
@@ -2000,7 +2021,7 @@ function VariablesManagerPanelRoot({
|
|
|
2000
2021
|
}
|
|
2001
2022
|
void closePanel();
|
|
2002
2023
|
}, [isDirty, openSaveChangesDialog, closePanel]);
|
|
2003
|
-
|
|
2024
|
+
useEffect4(() => {
|
|
2004
2025
|
if (!embedded || !onExposeCloseAttempt) {
|
|
2005
2026
|
return;
|
|
2006
2027
|
}
|
|
@@ -2305,8 +2326,7 @@ function VariablesManagerPanelRoot({
|
|
|
2305
2326
|
display: "flex",
|
|
2306
2327
|
flexDirection: "column",
|
|
2307
2328
|
flex: 1,
|
|
2308
|
-
minHeight: 0
|
|
2309
|
-
overflow: "hidden"
|
|
2329
|
+
minHeight: 0
|
|
2310
2330
|
}
|
|
2311
2331
|
},
|
|
2312
2332
|
bodyInner
|
|
@@ -2351,7 +2371,7 @@ function VariablesManagerPanelRoot({
|
|
|
2351
2371
|
return embedded ? core : /* @__PURE__ */ React14.createElement(ThemeProvider, null, core);
|
|
2352
2372
|
}
|
|
2353
2373
|
var usePreventUnload = (isDirty) => {
|
|
2354
|
-
|
|
2374
|
+
useEffect4(() => {
|
|
2355
2375
|
const handleBeforeUnload = (event) => {
|
|
2356
2376
|
if (isDirty) {
|
|
2357
2377
|
event.preventDefault();
|
|
@@ -2392,18 +2412,11 @@ import { isExperimentActive as isExperimentActive2 } from "@elementor/editor-v1-
|
|
|
2392
2412
|
import { controlActionsMenu } from "@elementor/menus";
|
|
2393
2413
|
|
|
2394
2414
|
// src/components/global-styles-import-listener.tsx
|
|
2395
|
-
import { useEffect as
|
|
2415
|
+
import { useEffect as useEffect5 } from "react";
|
|
2396
2416
|
import { GLOBAL_STYLES_IMPORTED_EVENT } from "@elementor/editor-canvas";
|
|
2397
2417
|
function GlobalStylesImportListener() {
|
|
2398
|
-
|
|
2399
|
-
const handleGlobalStylesImported = (
|
|
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
|
-
}
|
|
2418
|
+
useEffect5(() => {
|
|
2419
|
+
const handleGlobalStylesImported = () => {
|
|
2407
2420
|
service.load();
|
|
2408
2421
|
};
|
|
2409
2422
|
window.addEventListener(GLOBAL_STYLES_IMPORTED_EVENT, handleGlobalStylesImported);
|
|
@@ -2415,7 +2428,7 @@ function GlobalStylesImportListener() {
|
|
|
2415
2428
|
}
|
|
2416
2429
|
|
|
2417
2430
|
// src/components/open-panel-from-event.tsx
|
|
2418
|
-
import { useEffect as
|
|
2431
|
+
import { useEffect as useEffect6, useRef as useRef7, useState as useState7 } from "react";
|
|
2419
2432
|
import {
|
|
2420
2433
|
__privateListenTo as listenTo,
|
|
2421
2434
|
__privateOpenRoute as openRoute,
|
|
@@ -2427,13 +2440,13 @@ function OpenPanelFromEvent() {
|
|
|
2427
2440
|
const { open } = usePanelActions();
|
|
2428
2441
|
const pendingRef = useRef7(false);
|
|
2429
2442
|
const [readyToOpen, setReadyToOpen] = useState7(false);
|
|
2430
|
-
|
|
2443
|
+
useEffect6(() => {
|
|
2431
2444
|
if (readyToOpen) {
|
|
2432
2445
|
setReadyToOpen(false);
|
|
2433
2446
|
open();
|
|
2434
2447
|
}
|
|
2435
2448
|
}, [readyToOpen, open]);
|
|
2436
|
-
|
|
2449
|
+
useEffect6(() => {
|
|
2437
2450
|
return listenTo(routeOpenEvent(DEFAULT_PANEL_ROUTE), () => {
|
|
2438
2451
|
if (pendingRef.current) {
|
|
2439
2452
|
pendingRef.current = false;
|
|
@@ -2441,7 +2454,7 @@ function OpenPanelFromEvent() {
|
|
|
2441
2454
|
}
|
|
2442
2455
|
});
|
|
2443
2456
|
}, []);
|
|
2444
|
-
|
|
2457
|
+
useEffect6(() => {
|
|
2445
2458
|
const handler = () => {
|
|
2446
2459
|
pendingRef.current = true;
|
|
2447
2460
|
openRoute(DEFAULT_PANEL_ROUTE);
|
|
@@ -2453,7 +2466,7 @@ function OpenPanelFromEvent() {
|
|
|
2453
2466
|
}
|
|
2454
2467
|
|
|
2455
2468
|
// src/components/open-panel-from-url.tsx
|
|
2456
|
-
import { useEffect as
|
|
2469
|
+
import { useEffect as useEffect7, useRef as useRef8 } from "react";
|
|
2457
2470
|
import { __privateListenTo as listenTo2, routeOpenEvent as routeOpenEvent2 } from "@elementor/editor-v1-adapters";
|
|
2458
2471
|
var ACTIVE_PANEL_PARAM = "active-panel";
|
|
2459
2472
|
var PANEL_ID = "variables-manager";
|
|
@@ -2461,7 +2474,7 @@ var DEFAULT_PANEL_ROUTE2 = "panel/elements";
|
|
|
2461
2474
|
function OpenPanelFromUrl() {
|
|
2462
2475
|
const { open } = usePanelActions();
|
|
2463
2476
|
const hasOpened = useRef8(false);
|
|
2464
|
-
|
|
2477
|
+
useEffect7(() => {
|
|
2465
2478
|
const urlParams = new URLSearchParams(window.location.search);
|
|
2466
2479
|
const activePanel = urlParams.get(ACTIVE_PANEL_PARAM);
|
|
2467
2480
|
if (activePanel !== PANEL_ID) {
|
|
@@ -2714,7 +2727,7 @@ var VariableCreation = ({ onGoBack, onClose }) => {
|
|
|
2714
2727
|
|
|
2715
2728
|
// src/components/variable-edit.tsx
|
|
2716
2729
|
import * as React19 from "react";
|
|
2717
|
-
import { useEffect as
|
|
2730
|
+
import { useEffect as useEffect8, useState as useState11 } from "react";
|
|
2718
2731
|
import { PopoverContent as PopoverContent2, useBoundProp as useBoundProp5 } from "@elementor/editor-controls";
|
|
2719
2732
|
import { useSuppressedMessage as useSuppressedMessage2 } from "@elementor/editor-current-user";
|
|
2720
2733
|
import { PopoverHeader as PopoverHeader2, SectionPopoverBody as SectionPopoverBody2 } from "@elementor/editor-ui";
|
|
@@ -2791,7 +2804,7 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
|
|
|
2791
2804
|
const userPermissions = usePermissions();
|
|
2792
2805
|
const [value, setValue] = useState11(() => variable.value);
|
|
2793
2806
|
const [label, setLabel] = useState11(() => variable.label);
|
|
2794
|
-
|
|
2807
|
+
useEffect8(() => {
|
|
2795
2808
|
styleVariablesRepository.update({
|
|
2796
2809
|
[editId]: {
|
|
2797
2810
|
...variable,
|
|
@@ -2956,7 +2969,7 @@ var VariableEdit = ({ onClose, onGoBack, onSubmit, editId }) => {
|
|
|
2956
2969
|
};
|
|
2957
2970
|
|
|
2958
2971
|
// src/components/variables-selection.tsx
|
|
2959
|
-
import { useEffect as
|
|
2972
|
+
import { useEffect as useEffect9, useState as useState12 } from "react";
|
|
2960
2973
|
import * as React21 from "react";
|
|
2961
2974
|
import { trackUpgradePromotionClick as trackUpgradePromotionClick2, trackViewPromotion as trackViewPromotion2 } from "@elementor/editor-controls";
|
|
2962
2975
|
import {
|
|
@@ -3146,7 +3159,7 @@ var VariablesSelection = ({ closePopover, onAdd, onEdit, onSettings, disabled =
|
|
|
3146
3159
|
const handleClearSearch = () => {
|
|
3147
3160
|
setSearchValue("");
|
|
3148
3161
|
};
|
|
3149
|
-
|
|
3162
|
+
useEffect9(() => {
|
|
3150
3163
|
if (disabled) {
|
|
3151
3164
|
trackViewPromotion2({
|
|
3152
3165
|
target_name: "variables_popover",
|
|
@@ -3923,6 +3936,84 @@ var trackOpenVariablePopover = (path, variableType) => {
|
|
|
3923
3936
|
|
|
3924
3937
|
// src/mcp/manage-variable-tool.ts
|
|
3925
3938
|
import { z as z3 } from "@elementor/schema";
|
|
3939
|
+
import { isProActive as isProActive2 } from "@elementor/utils";
|
|
3940
|
+
|
|
3941
|
+
// src/mcp/variable-tool-prompt.ts
|
|
3942
|
+
import { toolPrompts } from "@elementor/editor-mcp";
|
|
3943
|
+
import { isProActive } from "@elementor/utils";
|
|
3944
|
+
var MANAGE_VARIABLES_GUIDE_URI = "elementor://variables/tools/manage-global-variable-guide";
|
|
3945
|
+
var generateVariablesPrompt = () => {
|
|
3946
|
+
const prompt = toolPrompts("manage-global-variable");
|
|
3947
|
+
const proIsActive = isProActive();
|
|
3948
|
+
const sizeVariableSection = proIsActive ? `- **global-size-variable** \u2014 A simple CSS length with a unit (Elementor Pro). Use this for fixed spacing, font sizes, or layout values. Example: \`16px\`, \`1.5rem\`, \`2em\`, \`10vh\`
|
|
3949
|
+
- **global-custom-size-variable** \u2014 Any CSS size expression that goes beyond a simple number + unit (Elementor Pro). Use this when the value is a CSS function, a keyword, or a combination of units that \`global-size-variable\` cannot represent. Example: \`auto\`, \`clamp(1rem, 2vw, 2rem)\`, \`calc(100% - 32px)\`, \`min(50vw, 600px)\`, \`300ms\`, \`2ch\`. When in doubt: if the value contains a function call or a keyword, use \`global-custom-size-variable\`.` : `- ~~global-size-variable~~ \u2014 requires Elementor Pro (not available on this site)
|
|
3950
|
+
- ~~global-custom-size-variable~~ \u2014 requires Elementor Pro (not available on this site)`;
|
|
3951
|
+
prompt.description(`
|
|
3952
|
+
# Purpose
|
|
3953
|
+
Create, update, or delete V4 global CSS variables. These are distinct from legacy v3 globals and map 1:1 to \`--css-var: VALUE\`.
|
|
3954
|
+
|
|
3955
|
+
# Available Types
|
|
3956
|
+
- **global-color-variable** \u2014 CSS color value. Example: \`#FF0000\`, \`rgba(255,0,0,1)\`, \`hsl(0,100%,50%)\`
|
|
3957
|
+
- **global-font-variable** \u2014 Font family name ONLY \u2014 NOT a size or px value. Example: \`Roboto\`, \`Open Sans\`. NEVER pass px/rem here.
|
|
3958
|
+
${sizeVariableSection}
|
|
3959
|
+
|
|
3960
|
+
# Naming Rules
|
|
3961
|
+
- Labels must be **lowercase**, using only letters (a-z), numbers, digits (0-9), dashes (-), or underscores (_)
|
|
3962
|
+
- No spaces, no special characters
|
|
3963
|
+
- Example: "Headline Primary" \u2192 \`headline-primary\`
|
|
3964
|
+
- Labels must be unique \u2014 always check [elementor://global-variables] first
|
|
3965
|
+
|
|
3966
|
+
# Value Rules
|
|
3967
|
+
- Provide a **plain CSS value** only \u2014 do NOT pass JSON, legacy-globals object structures, or variable references
|
|
3968
|
+
- Values are inserted as-is: \`--css-var: <value>\`
|
|
3969
|
+
- NEVER store a px/rem value inside a \`global-font-variable\` \u2014 use \`global-size-variable\` (Pro) instead
|
|
3970
|
+
|
|
3971
|
+
# Operations
|
|
3972
|
+
- **create** \u2014 requires \`type\`, \`label\`, \`value\`. Label must be unique.
|
|
3973
|
+
- **update** \u2014 requires \`id\`, \`label\`, \`value\`. Get \`id\` from [elementor://global-variables]. When renaming: keep existing value. When changing value: keep exact existing label.
|
|
3974
|
+
- **delete** \u2014 requires \`id\`. DESTRUCTIVE \u2014 always confirm with user before executing.
|
|
3975
|
+
`);
|
|
3976
|
+
prompt.parameter("action", '"create", "update", or "delete".');
|
|
3977
|
+
prompt.parameter("type", "Variable type. Required for create. See Available Types above.");
|
|
3978
|
+
prompt.parameter("label", "Variable name (lowercase, dash-separated). Required for create/update.");
|
|
3979
|
+
prompt.parameter(
|
|
3980
|
+
"value",
|
|
3981
|
+
"Plain CSS value matching the variable type. Required for create/update. Do NOT pass JSON."
|
|
3982
|
+
);
|
|
3983
|
+
prompt.parameter("id", "Variable ID. Required for update/delete. Obtain from [elementor://global-variables].");
|
|
3984
|
+
prompt.example(`
|
|
3985
|
+
Create a brand color:
|
|
3986
|
+
{ "action": "create", "type": "global-color-variable", "label": "brand-primary", "value": "#1A73E8" }
|
|
3987
|
+
|
|
3988
|
+
Create a heading font:
|
|
3989
|
+
{ "action": "create", "type": "global-font-variable", "label": "font-heading", "value": "Playfair Display" }
|
|
3990
|
+
|
|
3991
|
+
Create a simple spacing size:
|
|
3992
|
+
{ "action": "create", "type": "global-size-variable", "label": "spacing-md", "value": "16px" }
|
|
3993
|
+
|
|
3994
|
+
Create a fluid/responsive size using a CSS function (use global-custom-size-variable, NOT global-size-variable):
|
|
3995
|
+
{ "action": "create", "type": "global-custom-size-variable", "label": "spacing-fluid", "value": "clamp(1rem, 2vw, 2rem)" }
|
|
3996
|
+
|
|
3997
|
+
Create a size that is a keyword:
|
|
3998
|
+
{ "action": "create", "type": "global-custom-size-variable", "label": "width-auto", "value": "auto" }
|
|
3999
|
+
|
|
4000
|
+
Create a size using calc():
|
|
4001
|
+
{ "action": "create", "type": "global-custom-size-variable", "label": "sidebar-width", "value": "calc(100% - 32px)" }
|
|
4002
|
+
|
|
4003
|
+
Update a variable's value (keep exact label):
|
|
4004
|
+
{ "action": "update", "id": "abc123", "label": "brand-primary", "value": "#0D47A1" }
|
|
4005
|
+
|
|
4006
|
+
Rename a variable (keep existing value):
|
|
4007
|
+
{ "action": "update", "id": "abc123", "label": "brand-secondary", "value": "#1A73E8" }
|
|
4008
|
+
|
|
4009
|
+
Delete a variable:
|
|
4010
|
+
{ "action": "delete", "id": "abc123" }
|
|
4011
|
+
`);
|
|
4012
|
+
prompt.instruction(
|
|
4013
|
+
"Always read [elementor://global-variables] before creating to check existing variables and avoid duplicate labels."
|
|
4014
|
+
);
|
|
4015
|
+
return prompt.prompt();
|
|
4016
|
+
};
|
|
3926
4017
|
|
|
3927
4018
|
// src/mcp/variables-resource.ts
|
|
3928
4019
|
import { __privateListenTo as listenTo3, commandEndEvent } from "@elementor/editor-v1-adapters";
|
|
@@ -3959,22 +4050,59 @@ var initVariablesResource = (variablesMcpEntry, canvasMcpEntry) => {
|
|
|
3959
4050
|
};
|
|
3960
4051
|
}
|
|
3961
4052
|
);
|
|
3962
|
-
window.addEventListener(
|
|
4053
|
+
window.addEventListener(STORAGE_UPDATED_EVENT, notifyGlobalVariablesUpdated);
|
|
3963
4054
|
listenTo3(commandEndEvent("document/save/update"), notifyGlobalVariablesUpdated);
|
|
3964
4055
|
});
|
|
3965
4056
|
};
|
|
3966
4057
|
|
|
3967
4058
|
// src/mcp/manage-variable-tool.ts
|
|
4059
|
+
var VARIABLE_TYPES = {
|
|
4060
|
+
COLOR: "global-color-variable",
|
|
4061
|
+
FONT: "global-font-variable",
|
|
4062
|
+
SIZE: "global-size-variable",
|
|
4063
|
+
CUSTOM_SIZE: "global-custom-size-variable"
|
|
4064
|
+
};
|
|
4065
|
+
var LENGTH_UNIT_PATTERN = /^(auto|\d+(\.\d+)?(px|rem|em|vh|vw|%|ch|s|ms))$/i;
|
|
4066
|
+
var COLOR_PATTERN = /^(#[0-9a-f]{3,8}|rgba?\(|hsl)/i;
|
|
4067
|
+
function validateValueForType(type, value) {
|
|
4068
|
+
if (type === VARIABLE_TYPES.FONT && LENGTH_UNIT_PATTERN.test(value.trim())) {
|
|
4069
|
+
return `Font variable value must be a font family name (e.g. "Roboto"), not a size value like "${value}". Use "global-size-variable" or "global-custom-size-variable" for spacing/size values.`;
|
|
4070
|
+
}
|
|
4071
|
+
if (type === VARIABLE_TYPES.COLOR && !COLOR_PATTERN.test(value.trim())) {
|
|
4072
|
+
return `Color variable value should be a CSS color (e.g. "#FF0000"), got "${value}".`;
|
|
4073
|
+
}
|
|
4074
|
+
if (type === VARIABLE_TYPES.SIZE && !LENGTH_UNIT_PATTERN.test(value.trim())) {
|
|
4075
|
+
return `Size variable value should include a CSS unit (e.g. "16px") or be "auto", got "${value}".`;
|
|
4076
|
+
}
|
|
4077
|
+
return null;
|
|
4078
|
+
}
|
|
3968
4079
|
var initManageVariableTool = (reg) => {
|
|
3969
|
-
const { addTool } = reg;
|
|
4080
|
+
const { addTool, resource } = reg;
|
|
4081
|
+
resource(
|
|
4082
|
+
"manage-global-variable-guide",
|
|
4083
|
+
MANAGE_VARIABLES_GUIDE_URI,
|
|
4084
|
+
{
|
|
4085
|
+
title: "Manage Global Variable Guide",
|
|
4086
|
+
description: "Detailed guide for using the manage-global-variable tool",
|
|
4087
|
+
mimeType: "text/plain"
|
|
4088
|
+
},
|
|
4089
|
+
async (uri) => ({
|
|
4090
|
+
contents: [{ uri: uri.href, mimeType: "text/plain", text: generateVariablesPrompt() }]
|
|
4091
|
+
})
|
|
4092
|
+
);
|
|
3970
4093
|
addTool({
|
|
3971
4094
|
name: "manage-global-variable",
|
|
4095
|
+
description: "Manage V4 global variables (color, font, size). Read the guide resource before use.",
|
|
3972
4096
|
schema: {
|
|
3973
4097
|
action: z3.enum(["create", "update", "delete"]).describe("Operation to perform"),
|
|
3974
|
-
id: z3.string().optional().describe("Variable id
|
|
3975
|
-
type: z3.string().optional().describe(
|
|
3976
|
-
|
|
3977
|
-
|
|
4098
|
+
id: z3.string().optional().describe("Variable id \u2014 required for update/delete. Get from the global-variables resource."),
|
|
4099
|
+
type: z3.string().optional().describe(
|
|
4100
|
+
'Variable type \u2014 required for create. One of: "global-color-variable", "global-font-variable", "global-size-variable", "global-custom-size-variable" (size types require Elementor Pro). NEVER store px/rem values in a font variable.'
|
|
4101
|
+
),
|
|
4102
|
+
label: z3.string().optional().describe("Variable label (lowercase, dash-separated) \u2014 required for create/update."),
|
|
4103
|
+
value: z3.string().optional().describe(
|
|
4104
|
+
'Plain CSS value \u2014 required for create/update. Color: hex/rgba/hsl. Font: family name only, never px/rem. Size: value with unit e.g. "16px", or "auto" (Pro). Do NOT pass JSON.'
|
|
4105
|
+
)
|
|
3978
4106
|
},
|
|
3979
4107
|
outputSchema: {
|
|
3980
4108
|
status: z3.enum(["ok"]).describe("Operation status"),
|
|
@@ -3985,32 +4113,22 @@ var initManageVariableTool = (reg) => {
|
|
|
3985
4113
|
speedPriority: 0.75
|
|
3986
4114
|
},
|
|
3987
4115
|
requiredResources: [
|
|
4116
|
+
{ uri: MANAGE_VARIABLES_GUIDE_URI, description: "Full guide for variable types, naming rules, and usage" },
|
|
3988
4117
|
{
|
|
3989
4118
|
uri: GLOBAL_VARIABLES_URI,
|
|
3990
|
-
description: "
|
|
4119
|
+
description: "Current global variables \u2014 check before creating to avoid duplicates"
|
|
3991
4120
|
}
|
|
3992
4121
|
],
|
|
3993
|
-
|
|
3994
|
-
CREATE: requires type, label, value. Ensure label is unique.
|
|
3995
|
-
UPDATE: requires id, label, value. When renaming: keep existing value. When updating value: keep exact label.
|
|
3996
|
-
DELETE: requires id. DESTRUCTIVE - confirm with user first.
|
|
3997
|
-
|
|
3998
|
-
# NAMING - IMPORTANT
|
|
3999
|
-
the variables names should ALWAYS be lowercased and dashed spaced. example: "Headline Primary" should be "headline-primary"
|
|
4000
|
-
`,
|
|
4122
|
+
isDestructive: true,
|
|
4001
4123
|
handler: async (params) => {
|
|
4002
4124
|
const operations = getServiceActions(service);
|
|
4003
4125
|
const op = operations[params.action];
|
|
4004
4126
|
if (op) {
|
|
4005
4127
|
await op(params);
|
|
4006
|
-
return {
|
|
4007
|
-
status: "ok"
|
|
4008
|
-
};
|
|
4128
|
+
return { status: "ok" };
|
|
4009
4129
|
}
|
|
4010
4130
|
throw new Error(`Unknown action ${params.action}`);
|
|
4011
|
-
}
|
|
4012
|
-
isDestructive: true
|
|
4013
|
-
// Because delete is destructive
|
|
4131
|
+
}
|
|
4014
4132
|
});
|
|
4015
4133
|
};
|
|
4016
4134
|
function getServiceActions(svc) {
|
|
@@ -4019,10 +4137,17 @@ function getServiceActions(svc) {
|
|
|
4019
4137
|
if (!type || !label || !value) {
|
|
4020
4138
|
throw new Error("Create requires type, label, and value");
|
|
4021
4139
|
}
|
|
4140
|
+
if ((type === VARIABLE_TYPES.SIZE || type === VARIABLE_TYPES.CUSTOM_SIZE) && !isProActive2()) {
|
|
4141
|
+
throw new Error("Creating size variables requires Elementor Pro.");
|
|
4142
|
+
}
|
|
4022
4143
|
const labelError = validateLabel(label);
|
|
4023
4144
|
if (labelError) {
|
|
4024
4145
|
throw new Error(labelError);
|
|
4025
4146
|
}
|
|
4147
|
+
const valueError = validateValueForType(type, value);
|
|
4148
|
+
if (valueError) {
|
|
4149
|
+
throw new Error(valueError);
|
|
4150
|
+
}
|
|
4026
4151
|
return svc.create({ type, label, value });
|
|
4027
4152
|
},
|
|
4028
4153
|
update({ id: id2, label, value }) {
|
|
@@ -4033,6 +4158,13 @@ function getServiceActions(svc) {
|
|
|
4033
4158
|
if (labelError) {
|
|
4034
4159
|
throw new Error(labelError);
|
|
4035
4160
|
}
|
|
4161
|
+
const existingVariable = svc.variables()[id2];
|
|
4162
|
+
if (existingVariable) {
|
|
4163
|
+
const valueError = validateValueForType(existingVariable.type, value);
|
|
4164
|
+
if (valueError) {
|
|
4165
|
+
throw new Error(valueError);
|
|
4166
|
+
}
|
|
4167
|
+
}
|
|
4036
4168
|
return svc.update(id2, { label, value });
|
|
4037
4169
|
},
|
|
4038
4170
|
delete({ id: id2 }) {
|
|
@@ -4046,15 +4178,6 @@ function getServiceActions(svc) {
|
|
|
4046
4178
|
|
|
4047
4179
|
// src/mcp/index.ts
|
|
4048
4180
|
function initMcp(reg, canvasMcpEntry) {
|
|
4049
|
-
const { setMCPDescription } = reg;
|
|
4050
|
-
setMCPDescription(
|
|
4051
|
-
`Everything related to V4 ( Atomic ) variables.
|
|
4052
|
-
# Global variables
|
|
4053
|
-
- Create/update/delete global variables
|
|
4054
|
-
- Get list of global variables
|
|
4055
|
-
- Get details of a global variable
|
|
4056
|
-
`
|
|
4057
|
-
);
|
|
4058
4181
|
initManageVariableTool(reg);
|
|
4059
4182
|
initVariablesResource(reg, canvasMcpEntry);
|
|
4060
4183
|
}
|
|
@@ -4262,7 +4385,7 @@ function registerVariableTypes() {
|
|
|
4262
4385
|
|
|
4263
4386
|
// src/renderers/style-variables-renderer.tsx
|
|
4264
4387
|
import * as React38 from "react";
|
|
4265
|
-
import { useEffect as
|
|
4388
|
+
import { useEffect as useEffect10, useState as useState20 } from "react";
|
|
4266
4389
|
import {
|
|
4267
4390
|
__privateUseListenTo as useListenTo,
|
|
4268
4391
|
commandEndEvent as commandEndEvent2,
|
|
@@ -4286,7 +4409,7 @@ function usePortalContainer() {
|
|
|
4286
4409
|
}
|
|
4287
4410
|
function useStyleVariables() {
|
|
4288
4411
|
const [variables, setVariables] = useState20({});
|
|
4289
|
-
|
|
4412
|
+
useEffect10(() => {
|
|
4290
4413
|
const unsubscribe = styleVariablesRepository.subscribe(setVariables);
|
|
4291
4414
|
return () => {
|
|
4292
4415
|
unsubscribe();
|
|
@@ -4583,7 +4706,15 @@ function init() {
|
|
|
4583
4706
|
useProps: usePropVariableAction
|
|
4584
4707
|
});
|
|
4585
4708
|
service.init().then(() => {
|
|
4586
|
-
|
|
4709
|
+
const variablesMcpRegistry = getMCPByDomain("variables", {
|
|
4710
|
+
instructions: `Everything related to V4 ( Atomic ) variables.
|
|
4711
|
+
# Global variables
|
|
4712
|
+
- Create/update/delete global variables
|
|
4713
|
+
- Get list of global variables
|
|
4714
|
+
- Get details of a global variable
|
|
4715
|
+
`
|
|
4716
|
+
});
|
|
4717
|
+
initMcp(variablesMcpRegistry, getMCPByDomain("canvas"));
|
|
4587
4718
|
});
|
|
4588
4719
|
injectIntoTop({
|
|
4589
4720
|
id: "canvas-style-variables-render",
|