@elementor/editor-controls 0.21.0 → 0.24.0

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
@@ -456,11 +456,11 @@ var SelectionEndAdornment = ({
456
456
  Button2,
457
457
  {
458
458
  size: "small",
459
- color: "inherit",
460
- sx: { font: "inherit", minWidth: "initial" },
459
+ color: "secondary",
460
+ sx: { font: "inherit", minWidth: "initial", textTransform: "uppercase" },
461
461
  ...bindTrigger(popupState)
462
462
  },
463
- value.toUpperCase()
463
+ value
464
464
  ), /* @__PURE__ */ React13.createElement(Menu, { MenuListProps: { dense: true }, ...bindMenu(popupState) }, options.map((option, index) => /* @__PURE__ */ React13.createElement(MenuListItem2, { key: option, onClick: () => handleMenuItemClick(index) }, option.toUpperCase()))));
465
465
  };
466
466
 
@@ -705,21 +705,10 @@ var SortableItem = ({ id, children }) => {
705
705
  triggerProps,
706
706
  itemStyle,
707
707
  triggerStyle,
708
- isDragOverlay,
709
708
  showDropIndication,
710
709
  dropIndicationStyle
711
710
  }) => {
712
- return /* @__PURE__ */ React22.createElement(
713
- StyledListItem,
714
- {
715
- ...itemProps,
716
- style: itemStyle,
717
- sx: { backgroundColor: isDragOverlay ? "background.paper" : void 0 }
718
- },
719
- /* @__PURE__ */ React22.createElement(SortableTrigger, { ...triggerProps, style: triggerStyle }),
720
- children,
721
- showDropIndication && /* @__PURE__ */ React22.createElement(StyledDivider, { style: dropIndicationStyle })
722
- );
711
+ return /* @__PURE__ */ React22.createElement(StyledListItem, { ...itemProps, style: itemStyle }, /* @__PURE__ */ React22.createElement(SortableTrigger, { ...triggerProps, style: triggerStyle }), children, showDropIndication && /* @__PURE__ */ React22.createElement(StyledDivider, { style: dropIndicationStyle }));
723
712
  }
724
713
  }
725
714
  );
@@ -742,6 +731,11 @@ var StyledListItem = styled2(ListItem)`
742
731
  transform: translate( -75%, -50% );
743
732
  }
744
733
 
734
+ &[aria-describedby=''] > .MuiTag-root {
735
+ background-color: ${({ theme }) => theme.palette.background.paper};
736
+ box-shadow: ${({ theme }) => theme.shadows[3]};
737
+ }
738
+
745
739
  &:hover {
746
740
  & .class-item-sortable-trigger {
747
741
  visibility: visible;
@@ -768,6 +762,7 @@ var StyledDivider = styled2(Divider)`
768
762
 
769
763
  // src/components/repeater.tsx
770
764
  var SIZE = "tiny";
765
+ var EMPTY_OPEN_ITEM = -1;
771
766
  var Repeater = ({
772
767
  label,
773
768
  itemSettings,
@@ -776,7 +771,7 @@ var Repeater = ({
776
771
  values: repeaterValues = [],
777
772
  setValues: setRepeaterValues
778
773
  }) => {
779
- const [openItem, setOpenItem] = useState2(-1);
774
+ const [openItem, setOpenItem] = useState2(EMPTY_OPEN_ITEM);
780
775
  const [items, setItems] = useSyncExternalState({
781
776
  external: repeaterValues,
782
777
  // @ts-expect-error - as long as persistWhen => true, value will never be null
@@ -857,14 +852,14 @@ var Repeater = ({
857
852
  return /* @__PURE__ */ React23.createElement(SortableItem, { id: key, key: `sortable-${key}` }, /* @__PURE__ */ React23.createElement(
858
853
  RepeaterItem,
859
854
  {
860
- bind: String(index),
861
855
  disabled: value?.disabled,
862
856
  label: /* @__PURE__ */ React23.createElement(itemSettings.Label, { value }),
863
857
  startIcon: /* @__PURE__ */ React23.createElement(itemSettings.Icon, { value }),
864
858
  removeItem: () => removeRepeaterItem(index),
865
859
  duplicateItem: () => duplicateRepeaterItem(index),
866
860
  toggleDisableItem: () => toggleDisableRepeaterItem(index),
867
- openOnMount: openOnAdd && openItem === key
861
+ openOnMount: openOnAdd && openItem === key,
862
+ onOpen: () => setOpenItem(EMPTY_OPEN_ITEM)
868
863
  },
869
864
  (props) => /* @__PURE__ */ React23.createElement(itemSettings.Content, { ...props, value, bind: String(index) })
870
865
  ));
@@ -878,10 +873,11 @@ var RepeaterItem = ({
878
873
  removeItem,
879
874
  duplicateItem,
880
875
  toggleDisableItem,
881
- openOnMount
876
+ openOnMount,
877
+ onOpen
882
878
  }) => {
883
879
  const [anchorEl, setAnchorEl] = useState2(null);
884
- const { popoverState, popoverProps, ref, setRef } = usePopover(openOnMount);
880
+ const { popoverState, popoverProps, ref, setRef } = usePopover(openOnMount, onOpen);
885
881
  const duplicateLabel = __4("Duplicate", "elementor");
886
882
  const toggleLabel = disabled ? __4("Show", "elementor") : __4("Hide", "elementor");
887
883
  const removeLabel = __4("Remove", "elementor");
@@ -896,8 +892,7 @@ var RepeaterItem = ({
896
892
  "aria-label": __4("Open item", "elementor"),
897
893
  ...bindTrigger2(popoverState),
898
894
  startIcon,
899
- actions: /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Tooltip, { title: duplicateLabel, placement: "top" }, /* @__PURE__ */ React23.createElement(IconButton, { size: SIZE, onClick: duplicateItem, "aria-label": duplicateLabel }, /* @__PURE__ */ React23.createElement(CopyIcon, { fontSize: SIZE }))), /* @__PURE__ */ React23.createElement(Tooltip, { title: toggleLabel, placement: "top" }, /* @__PURE__ */ React23.createElement(IconButton, { size: SIZE, onClick: toggleDisableItem, "aria-label": toggleLabel }, disabled ? /* @__PURE__ */ React23.createElement(EyeOffIcon, { fontSize: SIZE }) : /* @__PURE__ */ React23.createElement(EyeIcon, { fontSize: SIZE }))), /* @__PURE__ */ React23.createElement(Tooltip, { title: removeLabel, placement: "top" }, /* @__PURE__ */ React23.createElement(IconButton, { size: SIZE, onClick: removeItem, "aria-label": removeLabel }, /* @__PURE__ */ React23.createElement(XIcon, { fontSize: SIZE })))),
900
- sx: { backgroundColor: "background.paper" }
895
+ actions: /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Tooltip, { title: duplicateLabel, placement: "top" }, /* @__PURE__ */ React23.createElement(IconButton, { size: SIZE, onClick: duplicateItem, "aria-label": duplicateLabel }, /* @__PURE__ */ React23.createElement(CopyIcon, { fontSize: SIZE }))), /* @__PURE__ */ React23.createElement(Tooltip, { title: toggleLabel, placement: "top" }, /* @__PURE__ */ React23.createElement(IconButton, { size: SIZE, onClick: toggleDisableItem, "aria-label": toggleLabel }, disabled ? /* @__PURE__ */ React23.createElement(EyeOffIcon, { fontSize: SIZE }) : /* @__PURE__ */ React23.createElement(EyeIcon, { fontSize: SIZE }))), /* @__PURE__ */ React23.createElement(Tooltip, { title: removeLabel, placement: "top" }, /* @__PURE__ */ React23.createElement(IconButton, { size: SIZE, onClick: removeItem, "aria-label": removeLabel }, /* @__PURE__ */ React23.createElement(XIcon, { fontSize: SIZE }))))
901
896
  }
902
897
  ), /* @__PURE__ */ React23.createElement(
903
898
  Popover,
@@ -916,13 +911,14 @@ var RepeaterItem = ({
916
911
  /* @__PURE__ */ React23.createElement(Box, null, children({ anchorEl }))
917
912
  ));
918
913
  };
919
- var usePopover = (openOnMount) => {
914
+ var usePopover = (openOnMount, onOpen) => {
920
915
  const [ref, setRef] = useState2(null);
921
916
  const popoverState = usePopupState2({ variant: "popover" });
922
917
  const popoverProps = bindPopover(popoverState);
923
918
  useEffect2(() => {
924
919
  if (openOnMount && ref) {
925
920
  popoverState.open(ref);
921
+ onOpen?.();
926
922
  }
927
923
  }, [ref]);
928
924
  return {
@@ -1608,7 +1604,9 @@ var StyledMenuList = styled4(MenuList)(({ theme }) => ({
1608
1604
  position: "absolute",
1609
1605
  top: 0,
1610
1606
  left: 0,
1611
- width: "100%"
1607
+ width: "100%",
1608
+ display: "flex",
1609
+ alignItems: "center"
1612
1610
  },
1613
1611
  '& > [role="option"]': {
1614
1612
  ...theme.typography.caption,
@@ -1654,7 +1652,7 @@ var UrlControl = createControl(({ placeholder }) => {
1654
1652
  // src/controls/link-control.tsx
1655
1653
  import * as React34 from "react";
1656
1654
  import { useMemo, useState as useState4 } from "react";
1657
- import { getAncestorWithAnchorTag, getDescendantWithAnchorTag } from "@elementor/editor-elements";
1655
+ import { getLinkInLinkRestriction, selectElement } from "@elementor/editor-elements";
1658
1656
  import {
1659
1657
  booleanPropTypeUtil,
1660
1658
  linkPropTypeUtil,
@@ -1662,10 +1660,11 @@ import {
1662
1660
  stringPropTypeUtil as stringPropTypeUtil7,
1663
1661
  urlPropTypeUtil as urlPropTypeUtil2
1664
1662
  } from "@elementor/editor-props";
1663
+ import { InfoTipCard } from "@elementor/editor-ui";
1665
1664
  import { httpService as httpService2 } from "@elementor/http";
1666
- import { MinusIcon, PlusIcon as PlusIcon2 } from "@elementor/icons";
1665
+ import { AlertTriangleIcon, MinusIcon, PlusIcon as PlusIcon2 } from "@elementor/icons";
1667
1666
  import { useSessionStorage } from "@elementor/session";
1668
- import { Collapse, Divider as Divider3, Grid as Grid7, IconButton as IconButton4, Stack as Stack10, Switch } from "@elementor/ui";
1667
+ import { Box as Box4, Collapse, Divider as Divider3, Grid as Grid7, IconButton as IconButton4, Infotip, Stack as Stack10, Switch } from "@elementor/ui";
1669
1668
  import { debounce as debounce2 } from "@elementor/utils";
1670
1669
  import { __ as __9 } from "@wordpress/i18n";
1671
1670
 
@@ -1783,10 +1782,14 @@ function _factoryFilter(newValue, options, minInputLength) {
1783
1782
 
1784
1783
  // src/controls/link-control.tsx
1785
1784
  var SIZE3 = "tiny";
1785
+ var learnMoreButton = {
1786
+ label: __9("Learn More", "elementor"),
1787
+ href: "https://go.elementor.com/element-link-inside-link-infotip"
1788
+ };
1786
1789
  var LinkControl = createControl((props) => {
1787
1790
  const { value, path, setValue, ...propContext } = useBoundProp(linkPropTypeUtil);
1788
1791
  const [linkSessionValue, setLinkSessionValue] = useSessionStorage(path.join("/"));
1789
- const [isEnabled, setIsEnabled] = useState4(!!value);
1792
+ const [isActive, setIsActive] = useState4(!!value);
1790
1793
  const {
1791
1794
  allowCustomValues,
1792
1795
  queryOptions: { endpoint = "", requestParams = {} },
@@ -1794,17 +1797,19 @@ var LinkControl = createControl((props) => {
1794
1797
  minInputLength = 2,
1795
1798
  context: { elementId }
1796
1799
  } = props || {};
1800
+ const [linkInLinkRestriction, setLinkInLinkRestriction] = useState4(getLinkInLinkRestriction(elementId));
1797
1801
  const [options, setOptions] = useState4(
1798
1802
  generateFirstLoadedOption(value)
1799
1803
  );
1804
+ const shouldDisableAddingLink = !isActive && linkInLinkRestriction.shouldRestrict;
1800
1805
  const onEnabledChange = () => {
1801
- const shouldRestrict = getAncestorWithAnchorTag(elementId) || getDescendantWithAnchorTag(elementId);
1802
- if (shouldRestrict && !isEnabled) {
1806
+ setLinkInLinkRestriction(getLinkInLinkRestriction(elementId));
1807
+ if (linkInLinkRestriction.shouldRestrict && !isActive) {
1803
1808
  return;
1804
1809
  }
1805
- setIsEnabled((prevState) => !prevState);
1806
- setValue(isEnabled ? null : linkSessionValue?.value ?? null);
1807
- setLinkSessionValue({ value, meta: { isEnabled: !isEnabled } });
1810
+ setIsActive((prevState) => !prevState);
1811
+ setValue(isActive ? null : linkSessionValue?.value ?? null);
1812
+ setLinkSessionValue({ value, meta: { isEnabled: !isActive } });
1808
1813
  };
1809
1814
  const onOptionChange = (newValue) => {
1810
1815
  const valueToSave = newValue ? {
@@ -1854,15 +1859,16 @@ var LinkControl = createControl((props) => {
1854
1859
  }
1855
1860
  },
1856
1861
  /* @__PURE__ */ React34.createElement(ControlFormLabel, null, __9("Link", "elementor")),
1857
- /* @__PURE__ */ React34.createElement(
1862
+ /* @__PURE__ */ React34.createElement(ConditionalInfoTip, { isVisible: !isActive, linkInLinkRestriction }, /* @__PURE__ */ React34.createElement(
1858
1863
  ToggleIconControl,
1859
1864
  {
1860
- enabled: isEnabled,
1865
+ disabled: shouldDisableAddingLink,
1866
+ active: isActive,
1861
1867
  onIconClick: onEnabledChange,
1862
1868
  label: __9("Toggle link", "elementor")
1863
1869
  }
1864
- )
1865
- ), /* @__PURE__ */ React34.createElement(Collapse, { in: isEnabled, timeout: "auto", unmountOnExit: true }, /* @__PURE__ */ React34.createElement(Stack10, { gap: 1.5 }, /* @__PURE__ */ React34.createElement(PropKeyProvider, { bind: "destination" }, /* @__PURE__ */ React34.createElement(ControlActions, null, /* @__PURE__ */ React34.createElement(
1870
+ ))
1871
+ ), /* @__PURE__ */ React34.createElement(Collapse, { in: isActive, timeout: "auto", unmountOnExit: true }, /* @__PURE__ */ React34.createElement(Stack10, { gap: 1.5 }, /* @__PURE__ */ React34.createElement(PropKeyProvider, { bind: "destination" }, /* @__PURE__ */ React34.createElement(ControlActions, null, /* @__PURE__ */ React34.createElement(
1866
1872
  Autocomplete,
1867
1873
  {
1868
1874
  options,
@@ -1873,17 +1879,22 @@ var LinkControl = createControl((props) => {
1873
1879
  onTextChange,
1874
1880
  minInputLength
1875
1881
  }
1876
- ))), /* @__PURE__ */ React34.createElement(PropKeyProvider, { bind: "isTargetBlank" }, /* @__PURE__ */ React34.createElement(SwitchControl, null))))));
1882
+ ))), /* @__PURE__ */ React34.createElement(PropKeyProvider, { bind: "isTargetBlank" }, /* @__PURE__ */ React34.createElement(SwitchControl, { disabled: !value }))))));
1877
1883
  });
1878
- var ToggleIconControl = ({ enabled, onIconClick, label }) => {
1879
- return /* @__PURE__ */ React34.createElement(IconButton4, { size: SIZE3, onClick: onIconClick, "aria-label": label }, enabled ? /* @__PURE__ */ React34.createElement(MinusIcon, { fontSize: SIZE3 }) : /* @__PURE__ */ React34.createElement(PlusIcon2, { fontSize: SIZE3 }));
1884
+ var ToggleIconControl = ({ disabled, active, onIconClick, label }) => {
1885
+ return /* @__PURE__ */ React34.createElement(IconButton4, { size: SIZE3, onClick: onIconClick, "aria-label": label, disabled }, active ? /* @__PURE__ */ React34.createElement(MinusIcon, { fontSize: SIZE3 }) : /* @__PURE__ */ React34.createElement(PlusIcon2, { fontSize: SIZE3 }));
1880
1886
  };
1881
- var SwitchControl = () => {
1887
+ var SwitchControl = ({ disabled }) => {
1882
1888
  const { value = false, setValue } = useBoundProp(booleanPropTypeUtil);
1883
1889
  const onClick = () => {
1884
1890
  setValue(!value);
1885
1891
  };
1886
- return /* @__PURE__ */ React34.createElement(Grid7, { container: true, alignItems: "center", flexWrap: "nowrap", justifyContent: "space-between" }, /* @__PURE__ */ React34.createElement(Grid7, { item: true }, /* @__PURE__ */ React34.createElement(ControlFormLabel, null, __9("Open in a new tab", "elementor"))), /* @__PURE__ */ React34.createElement(Grid7, { item: true }, /* @__PURE__ */ React34.createElement(Switch, { checked: value, onClick })));
1892
+ const inputProps = disabled ? {
1893
+ style: {
1894
+ opacity: 0
1895
+ }
1896
+ } : {};
1897
+ return /* @__PURE__ */ React34.createElement(Grid7, { container: true, alignItems: "center", flexWrap: "nowrap", justifyContent: "space-between" }, /* @__PURE__ */ React34.createElement(Grid7, { item: true }, /* @__PURE__ */ React34.createElement(ControlFormLabel, null, __9("Open in a new tab", "elementor"))), /* @__PURE__ */ React34.createElement(Grid7, { item: true }, /* @__PURE__ */ React34.createElement(Switch, { checked: value, onClick, disabled, inputProps })));
1887
1898
  };
1888
1899
  async function fetchOptions(ajaxUrl, params) {
1889
1900
  if (!params || !ajaxUrl) {
@@ -1913,6 +1924,37 @@ function generateFirstLoadedOption(unionValue) {
1913
1924
  }
1914
1925
  ] : [];
1915
1926
  }
1927
+ var ConditionalInfoTip = ({ linkInLinkRestriction, isVisible, children }) => {
1928
+ const { shouldRestrict, reason, elementId } = linkInLinkRestriction;
1929
+ const handleTakeMeClick = () => {
1930
+ if (elementId) {
1931
+ selectElement(elementId);
1932
+ }
1933
+ };
1934
+ return shouldRestrict && isVisible ? /* @__PURE__ */ React34.createElement(
1935
+ Infotip,
1936
+ {
1937
+ placement: "right",
1938
+ content: /* @__PURE__ */ React34.createElement(
1939
+ InfoTipCard,
1940
+ {
1941
+ content: INFOTIP_CONTENT[reason],
1942
+ svgIcon: /* @__PURE__ */ React34.createElement(AlertTriangleIcon, null),
1943
+ learnMoreButton,
1944
+ ctaButton: {
1945
+ label: __9("Take me there", "elementor"),
1946
+ onClick: handleTakeMeClick
1947
+ }
1948
+ }
1949
+ )
1950
+ },
1951
+ /* @__PURE__ */ React34.createElement(Box4, null, children)
1952
+ ) : /* @__PURE__ */ React34.createElement(React34.Fragment, null, children);
1953
+ };
1954
+ var INFOTIP_CONTENT = {
1955
+ descendant: /* @__PURE__ */ React34.createElement(React34.Fragment, null, __9("To add a link to this container,", "elementor"), /* @__PURE__ */ React34.createElement("br", null), __9("first remove the link from the elements inside of it.", "elementor")),
1956
+ ancestor: /* @__PURE__ */ React34.createElement(React34.Fragment, null, __9("To add a link to this element,", "elementor"), /* @__PURE__ */ React34.createElement("br", null), __9("first remove the link from its parent container.", "elementor"))
1957
+ };
1916
1958
 
1917
1959
  // src/controls/gap-control.tsx
1918
1960
  import * as React35 from "react";
@@ -2154,7 +2196,7 @@ import {
2154
2196
  backgroundOverlayPropTypeUtil,
2155
2197
  colorPropTypeUtil as colorPropTypeUtil3
2156
2198
  } from "@elementor/editor-props";
2157
- import { Box as Box4, CardMedia as CardMedia3, Grid as Grid13, styled as styled6, Tab, TabPanel, Tabs, UnstableColorIndicator as UnstableColorIndicator2 } from "@elementor/ui";
2199
+ import { Box as Box5, CardMedia as CardMedia3, Grid as Grid13, styled as styled6, Tab, TabPanel, Tabs, UnstableColorIndicator as UnstableColorIndicator2 } from "@elementor/ui";
2158
2200
  import { useWpMediaAttachment as useWpMediaAttachment3 } from "@elementor/wp-media";
2159
2201
  import { __ as __17 } from "@wordpress/i18n";
2160
2202
 
@@ -2534,7 +2576,7 @@ var Content2 = () => {
2534
2576
  color: initialBackgroundColorOverlay.value,
2535
2577
  gradient: initialBackgroundGradientOverlay.value
2536
2578
  });
2537
- return /* @__PURE__ */ React43.createElement(Box4, { sx: { width: "100%" } }, /* @__PURE__ */ React43.createElement(Box4, { sx: { borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React43.createElement(
2579
+ return /* @__PURE__ */ React43.createElement(Box5, { sx: { width: "100%" } }, /* @__PURE__ */ React43.createElement(Box5, { sx: { borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React43.createElement(
2538
2580
  Tabs,
2539
2581
  {
2540
2582
  size: "small",
@@ -2636,7 +2678,7 @@ var useImage = (image) => {
2636
2678
  const imageSrc = image?.value.image.value?.src.value;
2637
2679
  const { data: attachment } = useWpMediaAttachment3(imageSrc.id?.value || null);
2638
2680
  if (imageSrc.id) {
2639
- const imageFileTypeExtension = attachment?.subtype ? `.${attachment.subtype}` : "";
2681
+ const imageFileTypeExtension = getFileExtensionFromFilename(attachment?.filename);
2640
2682
  imageTitle = `${attachment?.title}${imageFileTypeExtension}` || null;
2641
2683
  imageUrl = attachment?.url || null;
2642
2684
  } else if (imageSrc.url) {
@@ -2645,6 +2687,13 @@ var useImage = (image) => {
2645
2687
  }
2646
2688
  return { imageTitle, imageUrl };
2647
2689
  };
2690
+ var getFileExtensionFromFilename = (filename) => {
2691
+ if (!filename) {
2692
+ return "";
2693
+ }
2694
+ const extension = filename.substring(filename.lastIndexOf(".") + 1);
2695
+ return `.${extension}`;
2696
+ };
2648
2697
  var getGradientValue = (value) => {
2649
2698
  const gradient = value.value;
2650
2699
  const stops = gradient.stops.value?.map(({ value: { color, offset } }) => `${color.value} ${offset.value ?? 0}%`)?.join(",");