@elementor/editor-controls 3.32.0-95 → 3.33.0-101

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.d.mts CHANGED
@@ -179,6 +179,7 @@ declare const FontFamilyControl: ControlComponent<({ fontFamilies, sectionWidth
179
179
  type SelectableItem = {
180
180
  type: 'item' | 'category';
181
181
  value: string;
182
+ disabled?: boolean;
182
183
  };
183
184
 
184
185
  type Category = {
@@ -197,8 +198,9 @@ type ItemSelectorProps = {
197
198
  icon: React$1.ElementType<{
198
199
  fontSize: string;
199
200
  }>;
201
+ disabledItems?: string[];
200
202
  };
201
- declare const ItemSelector: ({ itemsList, selectedItem, onItemChange, onClose, sectionWidth, title, itemStyle, onDebounce, icon, }: ItemSelectorProps) => React$1.JSX.Element;
203
+ declare const ItemSelector: ({ itemsList, selectedItem, onItemChange, onClose, sectionWidth, title, itemStyle, onDebounce, icon, disabledItems, }: ItemSelectorProps) => React$1.JSX.Element;
202
204
 
203
205
  declare const UrlControl: ControlComponent<({ placeholder }: {
204
206
  placeholder?: string;
@@ -317,7 +319,7 @@ declare const ControlFormLabel: (props: FormLabelProps) => React$1.JSX.Element;
317
319
 
318
320
  type CssEditorProps = {
319
321
  value: string;
320
- onChange: (value: string) => void;
322
+ onChange: (value: string, isValid: boolean) => void;
321
323
  };
322
324
  declare const CssEditor: ({ value, onChange }: CssEditorProps) => React$1.JSX.Element;
323
325
 
package/dist/index.d.ts CHANGED
@@ -179,6 +179,7 @@ declare const FontFamilyControl: ControlComponent<({ fontFamilies, sectionWidth
179
179
  type SelectableItem = {
180
180
  type: 'item' | 'category';
181
181
  value: string;
182
+ disabled?: boolean;
182
183
  };
183
184
 
184
185
  type Category = {
@@ -197,8 +198,9 @@ type ItemSelectorProps = {
197
198
  icon: React$1.ElementType<{
198
199
  fontSize: string;
199
200
  }>;
201
+ disabledItems?: string[];
200
202
  };
201
- declare const ItemSelector: ({ itemsList, selectedItem, onItemChange, onClose, sectionWidth, title, itemStyle, onDebounce, icon, }: ItemSelectorProps) => React$1.JSX.Element;
203
+ declare const ItemSelector: ({ itemsList, selectedItem, onItemChange, onClose, sectionWidth, title, itemStyle, onDebounce, icon, disabledItems, }: ItemSelectorProps) => React$1.JSX.Element;
202
204
 
203
205
  declare const UrlControl: ControlComponent<({ placeholder }: {
204
206
  placeholder?: string;
@@ -317,7 +319,7 @@ declare const ControlFormLabel: (props: FormLabelProps) => React$1.JSX.Element;
317
319
 
318
320
  type CssEditorProps = {
319
321
  value: string;
320
- onChange: (value: string) => void;
322
+ onChange: (value: string, isValid: boolean) => void;
321
323
  };
322
324
  declare const CssEditor: ({ value, onChange }: CssEditorProps) => React$1.JSX.Element;
323
325
 
package/dist/index.js CHANGED
@@ -1264,6 +1264,42 @@ var import_i18n5 = require("@wordpress/i18n");
1264
1264
  var React24 = __toESM(require("react"));
1265
1265
  var import_react16 = require("react");
1266
1266
  var import_ui19 = require("@elementor/ui");
1267
+
1268
+ // src/services/event-bus.ts
1269
+ var EventBus = class {
1270
+ listeners = /* @__PURE__ */ new Map();
1271
+ subscribe(eventName, callback) {
1272
+ if (!this.listeners.has(eventName)) {
1273
+ this.listeners.set(eventName, /* @__PURE__ */ new Set());
1274
+ }
1275
+ const eventListeners = this.listeners.get(eventName);
1276
+ if (eventListeners) {
1277
+ eventListeners.add(callback);
1278
+ }
1279
+ }
1280
+ unsubscribe(eventName, callback) {
1281
+ const eventListeners = this.listeners.get(eventName);
1282
+ if (!eventListeners) {
1283
+ return;
1284
+ }
1285
+ eventListeners.delete(callback);
1286
+ if (eventListeners.size === 0) {
1287
+ this.listeners.delete(eventName);
1288
+ }
1289
+ }
1290
+ emit(eventName, data) {
1291
+ const eventListeners = this.listeners.get(eventName);
1292
+ if (eventListeners) {
1293
+ eventListeners.forEach((callback) => callback(data));
1294
+ }
1295
+ }
1296
+ clearAll() {
1297
+ this.listeners.clear();
1298
+ }
1299
+ };
1300
+ var eventBus = new EventBus();
1301
+
1302
+ // src/components/unstable-repeater/context/repeater-context.tsx
1267
1303
  var RepeaterContext = (0, import_react16.createContext)(null);
1268
1304
  var EMPTY_OPEN_ITEM = -1;
1269
1305
  var useRepeaterContext = () => {
@@ -1312,9 +1348,16 @@ var RepeaterContextProvider = ({
1312
1348
  setItems(newItems);
1313
1349
  setOpenItemIndex(newIndex);
1314
1350
  popoverState.open(rowRef ?? ev);
1351
+ eventBus.emit(`${propTypeUtil.key}-item-added`, {
1352
+ itemValue: initial.value
1353
+ });
1315
1354
  };
1316
1355
  const removeItem = (index) => {
1356
+ const itemToRemove = items2[index];
1317
1357
  setItems(items2.filter((_, pos) => pos !== index));
1358
+ eventBus.emit(`${propTypeUtil.key}-item-removed`, {
1359
+ itemValue: itemToRemove?.value
1360
+ });
1318
1361
  };
1319
1362
  const updateItem = (updatedItem, index) => {
1320
1363
  const newItems = [...items2.slice(0, index), updatedItem, ...items2.slice(index + 1)];
@@ -2713,7 +2756,7 @@ var import_utils3 = require("@elementor/utils");
2713
2756
  var import_i18n19 = require("@wordpress/i18n");
2714
2757
 
2715
2758
  // src/hooks/use-filtered-items-list.ts
2716
- var useFilteredItemsList = (itemsList, searchValue) => {
2759
+ var useFilteredItemsList = (itemsList, searchValue, disabledItems) => {
2717
2760
  return itemsList.reduce((acc, category) => {
2718
2761
  const filteredItems = category.items.filter(
2719
2762
  (item) => item.toLowerCase().includes(searchValue.toLowerCase())
@@ -2721,7 +2764,7 @@ var useFilteredItemsList = (itemsList, searchValue) => {
2721
2764
  if (filteredItems.length) {
2722
2765
  acc.push({ type: "category", value: category.label });
2723
2766
  filteredItems.forEach((item) => {
2724
- acc.push({ type: "item", value: item });
2767
+ acc.push({ type: "item", value: item, disabled: disabledItems?.includes(item) ?? false });
2725
2768
  });
2726
2769
  }
2727
2770
  return acc;
@@ -2739,10 +2782,11 @@ var ItemSelector = ({
2739
2782
  itemStyle = () => ({}),
2740
2783
  onDebounce = () => {
2741
2784
  },
2742
- icon
2785
+ icon,
2786
+ disabledItems
2743
2787
  }) => {
2744
2788
  const [searchValue, setSearchValue] = (0, import_react25.useState)("");
2745
- const filteredItemsList = useFilteredItemsList(itemsList, searchValue);
2789
+ const filteredItemsList = useFilteredItemsList(itemsList, searchValue, disabledItems);
2746
2790
  const IconComponent = icon;
2747
2791
  const handleSearch = (value) => {
2748
2792
  setSearchValue(value);
@@ -5062,6 +5106,29 @@ var transitionsItemsList = transitionProperties.map((category) => ({
5062
5106
  items: category.properties.map((property) => property.label)
5063
5107
  }));
5064
5108
 
5109
+ // src/controls/transition-control/trainsition-events.ts
5110
+ var import_editor_elements3 = require("@elementor/editor-elements");
5111
+ var import_utils5 = require("@elementor/utils");
5112
+ var transitionRepeaterMixpanelEvent = {
5113
+ eventName: "click_added_transition",
5114
+ location: "V4 Style Tab",
5115
+ secondaryLocation: "Transition control",
5116
+ trigger: "click"
5117
+ };
5118
+ function subscribeToTransitionEvent() {
5119
+ eventBus.subscribe("transition-item-added", (data) => {
5120
+ const payload = data;
5121
+ const value = payload?.itemValue?.selection?.value?.value?.value;
5122
+ const selectedElements = (0, import_editor_elements3.getSelectedElements)();
5123
+ const widgetType = selectedElements[0]?.type ?? null;
5124
+ (0, import_utils5.sendMixpanelEvent)({
5125
+ transition_type: value ?? "unknown",
5126
+ ...transitionRepeaterMixpanelEvent,
5127
+ widget_type: widgetType
5128
+ });
5129
+ });
5130
+ }
5131
+
5065
5132
  // src/controls/transition-control/transition-selector.tsx
5066
5133
  var React89 = __toESM(require("react"));
5067
5134
  var import_react45 = require("react");
@@ -5089,7 +5156,10 @@ var findByValue = (value) => {
5089
5156
  }
5090
5157
  }
5091
5158
  };
5092
- var TransitionSelector = ({ recentlyUsedList = [] }) => {
5159
+ var TransitionSelector = ({
5160
+ recentlyUsedList = [],
5161
+ disabledItems = []
5162
+ }) => {
5093
5163
  const { value, setValue } = useBoundProp(import_editor_props46.keyValuePropTypeUtil);
5094
5164
  const {
5095
5165
  key: { value: transitionLabel }
@@ -5164,7 +5234,8 @@ var TransitionSelector = ({ recentlyUsedList = [] }) => {
5164
5234
  onClose: popoverState.close,
5165
5235
  sectionWidth: 268,
5166
5236
  title: (0, import_i18n46.__)("Transition Property", "elementor"),
5167
- icon: import_icons30.VariationsIcon
5237
+ icon: import_icons30.VariationsIcon,
5238
+ disabledItems
5168
5239
  }
5169
5240
  )
5170
5241
  ));
@@ -5176,14 +5247,15 @@ var DURATION_CONFIG = {
5176
5247
  units: ["s", "ms"],
5177
5248
  defaultUnit: "ms"
5178
5249
  };
5179
- var getSelectionSizeProps = (recentlyUsedList) => {
5250
+ var getSelectionSizeProps = (recentlyUsedList, disabledItems) => {
5180
5251
  return {
5181
5252
  selectionLabel: (0, import_i18n47.__)("Type", "elementor"),
5182
5253
  sizeLabel: (0, import_i18n47.__)("Duration", "elementor"),
5183
5254
  selectionConfig: {
5184
5255
  component: TransitionSelector,
5185
5256
  props: {
5186
- recentlyUsedList
5257
+ recentlyUsedList,
5258
+ disabledItems
5187
5259
  }
5188
5260
  },
5189
5261
  sizeConfigMap: {
@@ -5199,11 +5271,11 @@ var getSelectionSizeProps = (recentlyUsedList) => {
5199
5271
  }
5200
5272
  };
5201
5273
  };
5202
- function getChildControlConfig(recentlyUsedList) {
5274
+ function getChildControlConfig(recentlyUsedList, disabledItems) {
5203
5275
  return {
5204
5276
  propTypeUtil: import_editor_props47.selectionSizePropTypeUtil,
5205
5277
  component: SelectionSizeControl,
5206
- props: getSelectionSizeProps(recentlyUsedList)
5278
+ props: getSelectionSizeProps(recentlyUsedList, disabledItems)
5207
5279
  };
5208
5280
  }
5209
5281
  var disableAddItemTooltipContent = /* @__PURE__ */ React90.createElement(
@@ -5219,6 +5291,13 @@ var disableAddItemTooltipContent = /* @__PURE__ */ React90.createElement(
5219
5291
  /* @__PURE__ */ React90.createElement(import_ui78.AlertTitle, null, (0, import_i18n47.__)("Transitions", "elementor")),
5220
5292
  /* @__PURE__ */ React90.createElement(import_ui78.Box, { component: "span" }, /* @__PURE__ */ React90.createElement(import_ui78.Typography, { variant: "body2" }, (0, import_i18n47.__)("Switch to 'Normal' state to add a transition.", "elementor")))
5221
5293
  );
5294
+ subscribeToTransitionEvent();
5295
+ var getTransitionLabel = (item) => {
5296
+ return item.value.selection.value?.key?.value ?? "";
5297
+ };
5298
+ var getDisabledItems = (value) => {
5299
+ return value?.map(getTransitionLabel) ?? [];
5300
+ };
5222
5301
  var TransitionRepeaterControl = createControl(
5223
5302
  ({
5224
5303
  recentlyUsedListGetter,
@@ -5226,6 +5305,12 @@ var TransitionRepeaterControl = createControl(
5226
5305
  }) => {
5227
5306
  const currentStyleIsNormal = currentStyleState === null;
5228
5307
  const [recentlyUsedList, setRecentlyUsedList] = (0, import_react46.useState)([]);
5308
+ const childArrayPropTypeUtil = (0, import_react46.useMemo)(
5309
+ () => (0, import_editor_props47.createArrayPropUtils)(import_editor_props47.selectionSizePropTypeUtil.key, import_editor_props47.selectionSizePropTypeUtil.schema, "transition"),
5310
+ []
5311
+ );
5312
+ const { value } = useBoundProp(childArrayPropTypeUtil);
5313
+ const disabledItems = (0, import_react46.useMemo)(() => getDisabledItems(value), [value]);
5229
5314
  (0, import_react46.useEffect)(() => {
5230
5315
  recentlyUsedListGetter().then(setRecentlyUsedList);
5231
5316
  }, [recentlyUsedListGetter]);
@@ -5239,7 +5324,7 @@ var TransitionRepeaterControl = createControl(
5239
5324
  showDuplicate: false,
5240
5325
  showToggle: true,
5241
5326
  initialValues: initialTransitionValue,
5242
- childControlConfig: getChildControlConfig(recentlyUsedList),
5327
+ childControlConfig: getChildControlConfig(recentlyUsedList, disabledItems),
5243
5328
  propKey: "transition",
5244
5329
  addItemTooltipProps: {
5245
5330
  disabled: !currentStyleIsNormal,
@@ -5266,8 +5351,15 @@ var EditorWrapper = (0, import_ui79.styled)(import_ui79.Box)`
5266
5351
  position: relative;
5267
5352
  height: 200px;
5268
5353
 
5269
- .monaco-editor .colorpicker-widget {
5270
- z-index: 99999999 !important;
5354
+ .monaco-editor .suggest-widget {
5355
+ width: 220px !important;
5356
+ max-width: 220px !important;
5357
+ }
5358
+
5359
+ .visual-content-dimmed {
5360
+ opacity: 0.6;
5361
+ color: #aaa !important;
5362
+ pointer-events: none;
5271
5363
  }
5272
5364
  `;
5273
5365
  var ResizeHandle = (0, import_ui79.styled)(import_ui79.Button)`
@@ -5358,6 +5450,16 @@ function validate(editor, monaco) {
5358
5450
  const allMarkers = monaco.editor.getModelMarkers({ resource: model.uri });
5359
5451
  return allMarkers.filter((marker) => marker.severity === monaco.MarkerSeverity.Error).length === 0;
5360
5452
  }
5453
+ function clearMarkersFromVisualContent(editor, monaco) {
5454
+ const model = editor.getModel();
5455
+ if (!model) {
5456
+ return;
5457
+ }
5458
+ const allMarkers = monaco.editor.getModelMarkers({ resource: model.uri });
5459
+ const filteredMarkers = allMarkers.filter((marker) => marker.startLineNumber !== 1);
5460
+ const nonCustomMarkers = filteredMarkers.filter((m) => m.source !== "custom-css-rules");
5461
+ monaco.editor.setModelMarkers(model, "css", nonCustomMarkers);
5462
+ }
5361
5463
 
5362
5464
  // src/components/css-code-editor/resize-handle.tsx
5363
5465
  var React91 = __toESM(require("react"));
@@ -5404,6 +5506,60 @@ var ResizeHandleComponent = ({ onResize, containerRef, onHeightChange }) => {
5404
5506
  );
5405
5507
  };
5406
5508
 
5509
+ // src/components/css-code-editor/visual-content-change-protection.ts
5510
+ var preventChangeOnVisualContent = (editor) => {
5511
+ const model = editor.getModel();
5512
+ if (!model) {
5513
+ return;
5514
+ }
5515
+ const decorationsCollection = editor.createDecorationsCollection();
5516
+ const applyVisualContentStyling = () => {
5517
+ const totalLines = model.getLineCount();
5518
+ const decorations = [];
5519
+ decorations.push({
5520
+ range: {
5521
+ startLineNumber: 1,
5522
+ startColumn: 1,
5523
+ endLineNumber: 1,
5524
+ endColumn: model.getLineContent(1).length + 1
5525
+ },
5526
+ options: {
5527
+ inlineClassName: "visual-content-dimmed",
5528
+ isWholeLine: false
5529
+ }
5530
+ });
5531
+ if (totalLines > 1) {
5532
+ decorations.push({
5533
+ range: {
5534
+ startLineNumber: totalLines,
5535
+ startColumn: 1,
5536
+ endLineNumber: totalLines,
5537
+ endColumn: model.getLineContent(totalLines).length + 1
5538
+ },
5539
+ options: {
5540
+ inlineClassName: "visual-content-dimmed",
5541
+ isWholeLine: false
5542
+ }
5543
+ });
5544
+ }
5545
+ decorationsCollection.set(decorations);
5546
+ };
5547
+ applyVisualContentStyling();
5548
+ model.onDidChangeContent(() => {
5549
+ applyVisualContentStyling();
5550
+ });
5551
+ const originalPushEditOperations = model.pushEditOperations;
5552
+ model.pushEditOperations = function(beforeCursorState, editOperations, cursorStateComputer) {
5553
+ const totalLines = model.getLineCount();
5554
+ const filteredOperations = editOperations.filter((operation) => {
5555
+ const range = operation.range;
5556
+ const affectsProtectedLine = range.startLineNumber === 1 || range.endLineNumber === 1 || range.startLineNumber === totalLines || range.endLineNumber === totalLines;
5557
+ return !affectsProtectedLine;
5558
+ });
5559
+ return originalPushEditOperations.call(this, beforeCursorState, filteredOperations, cursorStateComputer);
5560
+ };
5561
+ };
5562
+
5407
5563
  // src/components/css-code-editor/css-editor.tsx
5408
5564
  var setVisualContent = (value) => {
5409
5565
  const trimmed = value.trim();
@@ -5417,63 +5573,16 @@ var getActual = (value) => {
5417
5573
  }
5418
5574
  return lines.slice(1, -1).map((line) => line.replace(/^ {2}/, "")).join("\n");
5419
5575
  };
5420
- var preventChangeOnVisualContent = (editor, monaco) => {
5421
- const model = editor.getModel();
5422
- if (!model) {
5423
- return;
5424
- }
5425
- editor.onKeyDown((e) => {
5426
- const position = editor.getPosition();
5427
- if (!position) {
5428
- return;
5429
- }
5430
- const totalLines = model.getLineCount();
5431
- const isInProtectedRange = position.lineNumber === 1 || position.lineNumber === totalLines;
5432
- if (isInProtectedRange) {
5433
- const allowedKeys = [
5434
- monaco.KeyCode.UpArrow,
5435
- monaco.KeyCode.DownArrow,
5436
- monaco.KeyCode.LeftArrow,
5437
- monaco.KeyCode.RightArrow,
5438
- monaco.KeyCode.Home,
5439
- monaco.KeyCode.End,
5440
- monaco.KeyCode.PageUp,
5441
- monaco.KeyCode.PageDown,
5442
- monaco.KeyCode.Tab,
5443
- monaco.KeyCode.Escape
5444
- ];
5445
- if (!allowedKeys.includes(e.keyCode)) {
5446
- e.preventDefault();
5447
- e.stopPropagation();
5448
- }
5449
- }
5450
- });
5451
- };
5452
- var createEditorDidMountHandler = (editorRef, monacoRef, debounceTimer, onChange) => {
5576
+ var createEditorDidMountHandler = (editorRef, monacoRef) => {
5453
5577
  return (editor, monaco) => {
5454
5578
  editorRef.current = editor;
5455
5579
  monacoRef.current = monaco;
5456
- preventChangeOnVisualContent(editor, monaco);
5580
+ preventChangeOnVisualContent(editor);
5457
5581
  setCustomSyntaxRules(editor, monaco);
5458
- editor.onDidChangeModelContent(() => {
5459
- const code = editor.getModel()?.getValue() ?? "";
5460
- const userContent = getActual(code);
5461
- setCustomSyntaxRules(editor, monaco);
5462
- const currentTimer = debounceTimer.current;
5463
- if (currentTimer) {
5464
- clearTimeout(currentTimer);
5465
- }
5466
- const newTimer = setTimeout(() => {
5467
- if (!editorRef.current || !monacoRef.current) {
5468
- return;
5469
- }
5470
- const hasNoErrors = validate(editorRef.current, monacoRef.current);
5471
- if (hasNoErrors) {
5472
- onChange(userContent);
5473
- }
5474
- }, 500);
5475
- debounceTimer.current = newTimer;
5582
+ monaco.editor.onDidChangeMarkers(() => {
5583
+ setTimeout(() => clearMarkersFromVisualContent(editor, monaco), 0);
5476
5584
  });
5585
+ editor.setPosition({ lineNumber: 2, column: (editor.getModel()?.getLineContent(2).length ?? 0) + 1 });
5477
5586
  };
5478
5587
  };
5479
5588
  var CssEditor = ({ value, onChange }) => {
@@ -5491,7 +5600,27 @@ var CssEditor = ({ value, onChange }) => {
5491
5600
  containerRef.current.style.height = `${height}px`;
5492
5601
  }
5493
5602
  }, []);
5494
- const handleEditorDidMount = createEditorDidMountHandler(editorRef, monacoRef, debounceTimer, onChange);
5603
+ const handleEditorChange = () => {
5604
+ if (!editorRef.current || !monacoRef.current) {
5605
+ return;
5606
+ }
5607
+ const code = editorRef.current?.getModel()?.getValue() ?? "";
5608
+ const userContent = getActual(code);
5609
+ setCustomSyntaxRules(editorRef?.current, monacoRef.current);
5610
+ const currentTimer = debounceTimer.current;
5611
+ if (currentTimer) {
5612
+ clearTimeout(currentTimer);
5613
+ }
5614
+ const newTimer = setTimeout(() => {
5615
+ if (!editorRef.current || !monacoRef.current) {
5616
+ return;
5617
+ }
5618
+ const hasNoErrors = validate(editorRef.current, monacoRef.current);
5619
+ onChange(userContent, hasNoErrors);
5620
+ }, 500);
5621
+ debounceTimer.current = newTimer;
5622
+ };
5623
+ const handleEditorDidMount = createEditorDidMountHandler(editorRef, monacoRef);
5495
5624
  React92.useEffect(() => {
5496
5625
  const timerRef = debounceTimer;
5497
5626
  return () => {
@@ -5508,18 +5637,24 @@ var CssEditor = ({ value, onChange }) => {
5508
5637
  height: "100%",
5509
5638
  language: "css",
5510
5639
  theme: theme.palette.mode === "dark" ? "vs-dark" : "vs",
5511
- defaultValue: setVisualContent(value),
5640
+ value: setVisualContent(value),
5512
5641
  onMount: handleEditorDidMount,
5642
+ onChange: handleEditorChange,
5513
5643
  options: {
5514
- lineNumbers: "off",
5515
- folding: false,
5516
- showFoldingControls: "never",
5644
+ lineNumbers: "on",
5645
+ folding: true,
5517
5646
  minimap: { enabled: false },
5518
5647
  fontFamily: "Roboto, Arial, Helvetica, Verdana, sans-serif",
5519
5648
  fontSize: 12,
5520
5649
  renderLineHighlight: "none",
5521
5650
  hideCursorInOverviewRuler: true,
5522
- fixedOverflowWidgets: true
5651
+ fixedOverflowWidgets: true,
5652
+ suggestFontSize: 10,
5653
+ suggestLineHeight: 14,
5654
+ stickyScroll: {
5655
+ enabled: false
5656
+ },
5657
+ lineDecorationsWidth: 2
5523
5658
  }
5524
5659
  }
5525
5660
  ), /* @__PURE__ */ React92.createElement(