@elementor/editor-variables 3.33.0-103 → 3.33.0-105

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 CHANGED
@@ -116,9 +116,66 @@ var apiClient = {
116
116
  payload.value = value;
117
117
  }
118
118
  return (0, import_http_client.httpService)().post(BASE_PATH + "/restore", payload);
119
+ },
120
+ batch: (payload) => {
121
+ return (0, import_http_client.httpService)().post(BASE_PATH + "/batch", payload);
119
122
  }
120
123
  };
121
124
 
125
+ // src/batch-operations.ts
126
+ var isTempId = (id2) => {
127
+ return id2.startsWith("tmp-");
128
+ };
129
+ var buildOperationsArray = (originalVariables, currentVariables) => {
130
+ const operations = [];
131
+ Object.entries(currentVariables).forEach(([id2, variable]) => {
132
+ if (isTempId(id2)) {
133
+ operations.push({
134
+ type: "create",
135
+ variable: {
136
+ ...variable,
137
+ id: id2
138
+ }
139
+ });
140
+ } else if (originalVariables[id2]) {
141
+ const original = originalVariables[id2];
142
+ if (original.deleted && !variable.deleted) {
143
+ operations.push({
144
+ type: "restore",
145
+ id: id2,
146
+ ...original.label !== variable.label && { label: variable.label },
147
+ ...original.value !== variable.value && { value: variable.value }
148
+ });
149
+ } else if (!variable.deleted && (original.label !== variable.label || original.value !== variable.value)) {
150
+ operations.push({
151
+ type: "update",
152
+ id: id2,
153
+ variable: {
154
+ ...original.label !== variable.label && { label: variable.label },
155
+ ...original.value !== variable.value && { value: variable.value }
156
+ }
157
+ });
158
+ }
159
+ }
160
+ });
161
+ Object.entries(originalVariables).forEach(([id2, variable]) => {
162
+ if (isTempId(id2) || variable.deleted) {
163
+ return;
164
+ }
165
+ const currentVariable = currentVariables[id2];
166
+ if (!currentVariable || currentVariable.deleted) {
167
+ operations.push({
168
+ type: "delete",
169
+ id: id2
170
+ });
171
+ }
172
+ });
173
+ return operations.filter((op) => {
174
+ const id2 = op.id || op.variable?.id;
175
+ return id2 && !(isTempId(id2) && currentVariables[id2]?.deleted);
176
+ });
177
+ };
178
+
122
179
  // src/storage.ts
123
180
  var STORAGE_KEY = "elementor-global-variables";
124
181
  var STORAGE_WATERMARK_KEY = "elementor-global-variables-watermark";
@@ -259,6 +316,9 @@ var service = {
259
316
  variables: () => {
260
317
  return storage.load();
261
318
  },
319
+ getWatermark: () => {
320
+ return storage.state.watermark;
321
+ },
262
322
  init: () => {
263
323
  service.load();
264
324
  },
@@ -361,6 +421,40 @@ var service = {
361
421
  variable: restoredVariable
362
422
  };
363
423
  });
424
+ },
425
+ batchSave: (originalVariables, currentVariables) => {
426
+ const operations = buildOperationsArray(originalVariables, currentVariables);
427
+ const batchPayload = { operations, watermark: storage.state.watermark };
428
+ return apiClient.batch(batchPayload).then((response) => {
429
+ const { success, data: payload } = response.data;
430
+ if (!success) {
431
+ throw new Error("Unexpected response from server");
432
+ }
433
+ return payload;
434
+ }).then((data) => {
435
+ const { results, watermark } = data;
436
+ handleWatermark(OP_RW, watermark);
437
+ if (results) {
438
+ results.forEach((result) => {
439
+ if (result.variable) {
440
+ const { id: variableId, ...variableData } = result.variable;
441
+ if (result.type === "create") {
442
+ storage.add(variableId, variableData);
443
+ } else {
444
+ storage.update(variableId, variableData);
445
+ }
446
+ styleVariablesRepository.update({
447
+ [variableId]: variableData
448
+ });
449
+ }
450
+ });
451
+ }
452
+ return {
453
+ success: true,
454
+ watermark,
455
+ operations: operations.length
456
+ };
457
+ });
364
458
  }
365
459
  };
366
460
  var handleWatermark = (operation, newWatermark) => {
@@ -998,7 +1092,21 @@ function VariablesManagerPanel() {
998
1092
  const [isDirty, setIsDirty] = (0, import_react7.useState)(false);
999
1093
  const [variables, setVariables] = (0, import_react7.useState)(getVariables(false));
1000
1094
  const [deletedVariables, setDeletedVariables] = (0, import_react7.useState)([]);
1095
+ const [isSaving, setIsSaving] = (0, import_react7.useState)(false);
1001
1096
  usePreventUnload(isDirty);
1097
+ const handleSave = (0, import_react7.useCallback)(async () => {
1098
+ setIsSaving(true);
1099
+ const originalVariables = getVariables(false);
1100
+ const result = await service.batchSave(originalVariables, variables);
1101
+ if (result.success) {
1102
+ await service.load();
1103
+ const updatedVariables = service.variables();
1104
+ setVariables(updatedVariables);
1105
+ setIsDirty(false);
1106
+ setDeletedVariables([]);
1107
+ }
1108
+ setIsSaving(false);
1109
+ }, [variables]);
1002
1110
  const menuActions = [
1003
1111
  {
1004
1112
  name: (0, import_i18n5.__)("Delete", "elementor"),
@@ -1040,7 +1148,18 @@ function VariablesManagerPanel() {
1040
1148
  onChange: handleOnChange
1041
1149
  }
1042
1150
  )
1043
- ), /* @__PURE__ */ React8.createElement(import_editor_panels.PanelFooter, null, /* @__PURE__ */ React8.createElement(import_ui8.Button, { fullWidth: true, size: "small", color: "global", variant: "contained", disabled: !isDirty }, (0, import_i18n5.__)("Save changes", "elementor"))))));
1151
+ ), /* @__PURE__ */ React8.createElement(import_editor_panels.PanelFooter, null, /* @__PURE__ */ React8.createElement(
1152
+ import_ui8.Button,
1153
+ {
1154
+ fullWidth: true,
1155
+ size: "small",
1156
+ color: "global",
1157
+ variant: "contained",
1158
+ disabled: !isDirty || isSaving,
1159
+ onClick: handleSave
1160
+ },
1161
+ (0, import_i18n5.__)("Save changes", "elementor")
1162
+ )))));
1044
1163
  }
1045
1164
  var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React8.createElement(import_ui8.IconButton, { size: "small", color: "secondary", onClick: onClose, "aria-label": "Close", ...props }, /* @__PURE__ */ React8.createElement(import_icons3.XIcon, { fontSize: "small" }));
1046
1165
  var ErrorBoundaryFallback = () => /* @__PURE__ */ React8.createElement(import_ui8.Box, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React8.createElement(import_ui8.Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React8.createElement("strong", null, (0, import_i18n5.__)("Something went wrong", "elementor"))));