@elementor/editor-controls 1.0.0 → 1.1.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
@@ -722,9 +722,10 @@ var useSyncExternalState = ({
722
722
  var DEFAULT_UNIT = "px";
723
723
  var DEFAULT_SIZE = NaN;
724
724
  var SizeControl = createControl((props) => {
725
+ const defaultUnit = props.defaultUnit ?? DEFAULT_UNIT;
725
726
  const { units: units2 = [...defaultUnits], placeholder, startIcon, anchorRef } = props;
726
727
  const { value: sizeValue, setValue: setSizeValue, disabled, restoreValue } = useBoundProp(sizePropTypeUtil);
727
- const [internalState, setInternalState] = useState3(createStateFromSizeProp(sizeValue));
728
+ const [internalState, setInternalState] = useState3(createStateFromSizeProp(sizeValue, defaultUnit));
728
729
  const activeBreakpoint = useActiveBreakpoint();
729
730
  const extendedOptions = useSizeExtendedOptions(props.extendedOptions || [], props.disableCustom ?? false);
730
731
  const popupState = usePopupState2({ variant: "popover" });
@@ -741,7 +742,7 @@ var SizeControl = createControl((props) => {
741
742
  return !!newState?.numeric || newState?.numeric === 0;
742
743
  },
743
744
  fallback: (newState) => ({
744
- unit: newState?.unit ?? DEFAULT_UNIT,
745
+ unit: newState?.unit ?? props.defaultUnit ?? DEFAULT_UNIT,
745
746
  numeric: newState?.numeric ?? DEFAULT_SIZE,
746
747
  custom: newState?.custom ?? ""
747
748
  })
@@ -776,7 +777,7 @@ var SizeControl = createControl((props) => {
776
777
  }
777
778
  };
778
779
  useEffect2(() => {
779
- const newState = createStateFromSizeProp(sizeValue);
780
+ const newState = createStateFromSizeProp(sizeValue, defaultUnit);
780
781
  const currentUnit = isUnitExtendedOption(state.unit) ? "custom" : "numeric";
781
782
  const mergedStates = { ...state, [currentUnit]: newState[currentUnit] };
782
783
  if (mergedStates.unit !== "auto" && areStatesEqual(state, mergedStates)) {
@@ -789,7 +790,7 @@ var SizeControl = createControl((props) => {
789
790
  setState(newState);
790
791
  }, [sizeValue]);
791
792
  useEffect2(() => {
792
- const newState = createStateFromSizeProp(sizeValue);
793
+ const newState = createStateFromSizeProp(sizeValue, defaultUnit);
793
794
  if (activeBreakpoint && !areStatesEqual(newState, state)) {
794
795
  setState(newState);
795
796
  }
@@ -827,8 +828,8 @@ function formatSize(size, unit) {
827
828
  }
828
829
  return size || size === 0 ? Number(size) : NaN;
829
830
  }
830
- function createStateFromSizeProp(sizeValue) {
831
- const unit = sizeValue?.unit ?? DEFAULT_UNIT;
831
+ function createStateFromSizeProp(sizeValue, defaultUnit) {
832
+ const unit = sizeValue?.unit ?? defaultUnit;
832
833
  const size = sizeValue?.size ?? "";
833
834
  return {
834
835
  numeric: !isUnitExtendedOption(unit) && !isNaN(Number(size)) && (size || size === 0) ? Number(size) : DEFAULT_SIZE,
@@ -1076,7 +1077,9 @@ var Repeater = ({
1076
1077
  openOnAdd = false,
1077
1078
  addToBottom = false,
1078
1079
  values: repeaterValues = [],
1079
- setValues: setRepeaterValues
1080
+ setValues: setRepeaterValues,
1081
+ showDuplicate = true,
1082
+ showToggle = true
1080
1083
  }) => {
1081
1084
  const [openItem, setOpenItem] = useState4(EMPTY_OPEN_ITEM);
1082
1085
  const [items, setItems] = useSyncExternalState({
@@ -1180,7 +1183,9 @@ var Repeater = ({
1180
1183
  duplicateItem: () => duplicateRepeaterItem(index),
1181
1184
  toggleDisableItem: () => toggleDisableRepeaterItem(index),
1182
1185
  openOnMount: openOnAdd && openItem === key,
1183
- onOpen: () => setOpenItem(EMPTY_OPEN_ITEM)
1186
+ onOpen: () => setOpenItem(EMPTY_OPEN_ITEM),
1187
+ showDuplicate,
1188
+ showToggle
1184
1189
  },
1185
1190
  (props) => /* @__PURE__ */ React25.createElement(itemSettings.Content, { ...props, value, bind: String(index) })
1186
1191
  ));
@@ -1196,6 +1201,8 @@ var RepeaterItem = ({
1196
1201
  toggleDisableItem,
1197
1202
  openOnMount,
1198
1203
  onOpen,
1204
+ showDuplicate,
1205
+ showToggle,
1199
1206
  disabled
1200
1207
  }) => {
1201
1208
  const [anchorEl, setAnchorEl] = useState4(null);
@@ -1215,7 +1222,7 @@ var RepeaterItem = ({
1215
1222
  "aria-label": __4("Open item", "elementor"),
1216
1223
  ...bindTrigger2(popoverState),
1217
1224
  startIcon,
1218
- actions: /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(Tooltip, { title: duplicateLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(IconButton, { size: SIZE, onClick: duplicateItem, "aria-label": duplicateLabel }, /* @__PURE__ */ React25.createElement(CopyIcon, { fontSize: SIZE }))), /* @__PURE__ */ React25.createElement(Tooltip, { title: toggleLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(IconButton, { size: SIZE, onClick: toggleDisableItem, "aria-label": toggleLabel }, propDisabled ? /* @__PURE__ */ React25.createElement(EyeOffIcon, { fontSize: SIZE }) : /* @__PURE__ */ React25.createElement(EyeIcon, { fontSize: SIZE }))), /* @__PURE__ */ React25.createElement(Tooltip, { title: removeLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(IconButton, { size: SIZE, onClick: removeItem, "aria-label": removeLabel }, /* @__PURE__ */ React25.createElement(XIcon, { fontSize: SIZE }))))
1225
+ actions: /* @__PURE__ */ React25.createElement(React25.Fragment, null, showDuplicate && /* @__PURE__ */ React25.createElement(Tooltip, { title: duplicateLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(IconButton, { size: SIZE, onClick: duplicateItem, "aria-label": duplicateLabel }, /* @__PURE__ */ React25.createElement(CopyIcon, { fontSize: SIZE }))), showToggle && /* @__PURE__ */ React25.createElement(Tooltip, { title: toggleLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(IconButton, { size: SIZE, onClick: toggleDisableItem, "aria-label": toggleLabel }, propDisabled ? /* @__PURE__ */ React25.createElement(EyeOffIcon, { fontSize: SIZE }) : /* @__PURE__ */ React25.createElement(EyeIcon, { fontSize: SIZE }))), /* @__PURE__ */ React25.createElement(Tooltip, { title: removeLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(IconButton, { size: SIZE, onClick: removeItem, "aria-label": removeLabel }, /* @__PURE__ */ React25.createElement(XIcon, { fontSize: SIZE }))))
1219
1226
  }
1220
1227
  ), /* @__PURE__ */ React25.createElement(
1221
1228
  Popover2,
@@ -1422,14 +1429,14 @@ var ControlToggleButtonGroup = ({
1422
1429
  width: `100%`
1423
1430
  }
1424
1431
  },
1425
- fixedItems.map(({ label, value: buttonValue, renderContent: Content3, showTooltip }) => /* @__PURE__ */ React28.createElement(
1432
+ fixedItems.map(({ label, value: buttonValue, renderContent: Content4, showTooltip }) => /* @__PURE__ */ React28.createElement(
1426
1433
  ConditionalTooltip,
1427
1434
  {
1428
1435
  key: buttonValue,
1429
1436
  label,
1430
1437
  showTooltip: showTooltip || false
1431
1438
  },
1432
- /* @__PURE__ */ React28.createElement(ToggleButton, { value: buttonValue, "aria-label": label, size, fullWidth }, /* @__PURE__ */ React28.createElement(Content3, { size }))
1439
+ /* @__PURE__ */ React28.createElement(ToggleButton, { value: buttonValue, "aria-label": label, size, fullWidth }, /* @__PURE__ */ React28.createElement(Content4, { size }))
1433
1440
  )),
1434
1441
  menuItems.length && exclusive && /* @__PURE__ */ React28.createElement(
1435
1442
  SplitButtonGroup,
@@ -1880,24 +1887,12 @@ import { ChevronDownIcon as ChevronDownIcon2 } from "@elementor/icons";
1880
1887
  import { bindPopover as bindPopover4, bindTrigger as bindTrigger3, Popover as Popover4, UnstableTag as UnstableTag2, usePopupState as usePopupState5 } from "@elementor/ui";
1881
1888
 
1882
1889
  // src/components/font-family-selector.tsx
1883
- import { useEffect as useEffect5, useRef as useRef7, useState as useState6 } from "react";
1884
1890
  import * as React34 from "react";
1885
- import { PopoverHeader } from "@elementor/editor-ui";
1886
- import { SearchIcon, TextIcon } from "@elementor/icons";
1887
- import {
1888
- Box as Box3,
1889
- Divider as Divider2,
1890
- InputAdornment as InputAdornment3,
1891
- Link,
1892
- MenuList,
1893
- MenuSubheader,
1894
- Stack as Stack9,
1895
- styled as styled4,
1896
- TextField as TextField6,
1897
- Typography as Typography3
1898
- } from "@elementor/ui";
1891
+ import { useEffect as useEffect5, useState as useState6 } from "react";
1892
+ import { PopoverHeader, PopoverMenuList, PopoverScrollableContent, PopoverSearch } from "@elementor/editor-ui";
1893
+ import { TextIcon } from "@elementor/icons";
1894
+ import { Box as Box3, Divider as Divider2, Link, Stack as Stack9, Typography as Typography3 } from "@elementor/ui";
1899
1895
  import { debounce } from "@elementor/utils";
1900
- import { useVirtualizer } from "@tanstack/react-virtual";
1901
1896
  import { __ as __8 } from "@wordpress/i18n";
1902
1897
 
1903
1898
  // src/controls/font-family-control/enqueue-font.tsx
@@ -1932,8 +1927,8 @@ var FontFamilySelector = ({
1932
1927
  }) => {
1933
1928
  const [searchValue, setSearchValue] = useState6("");
1934
1929
  const filteredFontFamilies = useFilteredFontFamilies(fontFamilies, searchValue);
1935
- const handleSearch = (event) => {
1936
- setSearchValue(event.target.value);
1930
+ const handleSearch = (value) => {
1931
+ setSearchValue(value);
1937
1932
  };
1938
1933
  const handleClose = () => {
1939
1934
  setSearchValue("");
@@ -1946,20 +1941,14 @@ var FontFamilySelector = ({
1946
1941
  onClose: handleClose,
1947
1942
  icon: /* @__PURE__ */ React34.createElement(TextIcon, { fontSize: SIZE2 })
1948
1943
  }
1949
- ), /* @__PURE__ */ React34.createElement(Box3, { px: 1.5, pb: 1 }, /* @__PURE__ */ React34.createElement(
1950
- TextField6,
1944
+ ), /* @__PURE__ */ React34.createElement(
1945
+ PopoverSearch,
1951
1946
  {
1952
- autoFocus: true,
1953
- fullWidth: true,
1954
- size: SIZE2,
1955
1947
  value: searchValue,
1956
- placeholder: __8("Search", "elementor"),
1957
- onChange: handleSearch,
1958
- InputProps: {
1959
- startAdornment: /* @__PURE__ */ React34.createElement(InputAdornment3, { position: "start" }, /* @__PURE__ */ React34.createElement(SearchIcon, { fontSize: SIZE2 }))
1960
- }
1948
+ onSearch: handleSearch,
1949
+ placeholder: __8("Search", "elementor")
1961
1950
  }
1962
- )), /* @__PURE__ */ React34.createElement(Divider2, null), filteredFontFamilies.length > 0 ? /* @__PURE__ */ React34.createElement(
1951
+ ), /* @__PURE__ */ React34.createElement(Divider2, null), filteredFontFamilies.length > 0 ? /* @__PURE__ */ React34.createElement(
1963
1952
  FontList,
1964
1953
  {
1965
1954
  fontListItems: filteredFontFamilies,
@@ -1967,7 +1956,7 @@ var FontFamilySelector = ({
1967
1956
  handleClose,
1968
1957
  fontFamily
1969
1958
  }
1970
- ) : /* @__PURE__ */ React34.createElement(Box3, { sx: { overflowY: "auto", height: 260, width: 220 } }, /* @__PURE__ */ React34.createElement(Stack9, { alignItems: "center", p: 2.5, gap: 1.5, overflow: "hidden" }, /* @__PURE__ */ React34.createElement(TextIcon, { fontSize: "large" }), /* @__PURE__ */ React34.createElement(Box3, { sx: { maxWidth: 160, overflow: "hidden" } }, /* @__PURE__ */ React34.createElement(Typography3, { align: "center", variant: "subtitle2", color: "text.secondary" }, __8("Sorry, nothing matched", "elementor")), /* @__PURE__ */ React34.createElement(
1959
+ ) : /* @__PURE__ */ React34.createElement(PopoverScrollableContent, null, /* @__PURE__ */ React34.createElement(Stack9, { alignItems: "center", p: 2.5, gap: 1.5, overflow: "hidden" }, /* @__PURE__ */ React34.createElement(TextIcon, { fontSize: "large" }), /* @__PURE__ */ React34.createElement(Box3, { sx: { maxWidth: 160, overflow: "hidden" } }, /* @__PURE__ */ React34.createElement(Typography3, { align: "center", variant: "subtitle2", color: "text.secondary" }, __8("Sorry, nothing matched", "elementor")), /* @__PURE__ */ React34.createElement(
1971
1960
  Typography3,
1972
1961
  {
1973
1962
  variant: "subtitle2",
@@ -1992,10 +1981,7 @@ var FontFamilySelector = ({
1992
1981
  __8("Clear & try again", "elementor")
1993
1982
  )))));
1994
1983
  };
1995
- var LIST_ITEM_HEIGHT = 36;
1996
- var LIST_ITEMS_BUFFER = 6;
1997
1984
  var FontList = ({ fontListItems, setFontFamily, handleClose, fontFamily }) => {
1998
- const containerRef = useRef7(null);
1999
1985
  const selectedItem = fontListItems.find((item) => item.value === fontFamily);
2000
1986
  const debouncedVirtualizeChange = useDebounce(({ getVirtualIndexes }) => {
2001
1987
  getVirtualIndexes().forEach((index) => {
@@ -2005,120 +1991,19 @@ var FontList = ({ fontListItems, setFontFamily, handleClose, fontFamily }) => {
2005
1991
  }
2006
1992
  });
2007
1993
  }, 100);
2008
- const virtualizer = useVirtualizer({
2009
- count: fontListItems.length,
2010
- getScrollElement: () => containerRef.current,
2011
- estimateSize: () => LIST_ITEM_HEIGHT,
2012
- overscan: LIST_ITEMS_BUFFER,
2013
- onChange: debouncedVirtualizeChange
2014
- });
2015
- useEffect5(
2016
- () => {
2017
- virtualizer.scrollToIndex(fontListItems.findIndex((item) => item.value === fontFamily));
2018
- },
2019
- // eslint-disable-next-line react-compiler/react-compiler
2020
- // eslint-disable-next-line react-hooks/exhaustive-deps
2021
- [fontFamily]
2022
- );
2023
1994
  return /* @__PURE__ */ React34.createElement(
2024
- Box3,
1995
+ PopoverMenuList,
2025
1996
  {
2026
- ref: containerRef,
2027
- sx: {
2028
- overflowY: "auto",
2029
- height: 260,
2030
- width: 220
2031
- }
2032
- },
2033
- /* @__PURE__ */ React34.createElement(
2034
- StyledMenuList,
2035
- {
2036
- role: "listbox",
2037
- style: {
2038
- height: `${virtualizer.getTotalSize()}px`
2039
- },
2040
- "data-testid": "font-list"
2041
- },
2042
- virtualizer.getVirtualItems().map((virtualRow) => {
2043
- const item = fontListItems[virtualRow.index];
2044
- const isLast = virtualRow.index === fontListItems.length - 1;
2045
- const isFirst = virtualRow.index === 1;
2046
- const isSelected = selectedItem?.value === item.value;
2047
- const tabIndexFallback = !selectedItem ? 0 : -1;
2048
- if (item.type === "category") {
2049
- return /* @__PURE__ */ React34.createElement(
2050
- MenuSubheader,
2051
- {
2052
- key: virtualRow.key,
2053
- style: {
2054
- transform: `translateY(${virtualRow.start}px)`
2055
- }
2056
- },
2057
- item.value
2058
- );
2059
- }
2060
- return /* @__PURE__ */ React34.createElement(
2061
- "li",
2062
- {
2063
- key: virtualRow.key,
2064
- role: "option",
2065
- "aria-selected": isSelected,
2066
- onClick: () => {
2067
- setFontFamily(item.value);
2068
- handleClose();
2069
- },
2070
- onKeyDown: (event) => {
2071
- if (event.key === "Enter") {
2072
- setFontFamily(item.value);
2073
- handleClose();
2074
- }
2075
- if (event.key === "ArrowDown" && isLast) {
2076
- event.preventDefault();
2077
- event.stopPropagation();
2078
- }
2079
- if (event.key === "ArrowUp" && isFirst) {
2080
- event.preventDefault();
2081
- event.stopPropagation();
2082
- }
2083
- },
2084
- tabIndex: isSelected ? 0 : tabIndexFallback,
2085
- style: {
2086
- transform: `translateY(${virtualRow.start}px)`,
2087
- fontFamily: item.value
2088
- }
2089
- },
2090
- item.value
2091
- );
2092
- })
2093
- )
1997
+ items: fontListItems,
1998
+ selectedValue: selectedItem?.value,
1999
+ onChange: debouncedVirtualizeChange,
2000
+ onSelect: setFontFamily,
2001
+ onClose: handleClose,
2002
+ itemStyle: (item) => ({ fontFamily: item.value }),
2003
+ "data-testid": "font-list"
2004
+ }
2094
2005
  );
2095
2006
  };
2096
- var StyledMenuList = styled4(MenuList)(({ theme }) => ({
2097
- "& > li": {
2098
- height: LIST_ITEM_HEIGHT,
2099
- position: "absolute",
2100
- top: 0,
2101
- left: 0,
2102
- width: "100%",
2103
- display: "flex",
2104
- alignItems: "center"
2105
- },
2106
- '& > [role="option"]': {
2107
- ...theme.typography.caption,
2108
- lineHeight: "inherit",
2109
- padding: theme.spacing(0.75, 2, 0.75, 4),
2110
- "&:hover, &:focus": {
2111
- backgroundColor: theme.palette.action.hover
2112
- },
2113
- '&[aria-selected="true"]': {
2114
- backgroundColor: theme.palette.action.selected
2115
- },
2116
- cursor: "pointer",
2117
- textOverflow: "ellipsis"
2118
- },
2119
- width: "100%",
2120
- position: "relative"
2121
- }));
2122
2007
  var useDebounce = (fn, delay) => {
2123
2008
  const [debouncedFn] = useState6(() => debounce(fn, delay));
2124
2009
  useEffect5(() => () => debouncedFn.cancel(), [debouncedFn]);
@@ -2163,12 +2048,12 @@ var FontFamilyControl = createControl(({ fontFamilies }) => {
2163
2048
  // src/controls/url-control.tsx
2164
2049
  import * as React36 from "react";
2165
2050
  import { urlPropTypeUtil } from "@elementor/editor-props";
2166
- import { TextField as TextField7 } from "@elementor/ui";
2051
+ import { TextField as TextField6 } from "@elementor/ui";
2167
2052
  var UrlControl = createControl(({ placeholder }) => {
2168
2053
  const { value, setValue, disabled } = useBoundProp(urlPropTypeUtil);
2169
2054
  const handleChange = (event) => setValue(event.target.value);
2170
2055
  return /* @__PURE__ */ React36.createElement(ControlActions, null, /* @__PURE__ */ React36.createElement(
2171
- TextField7,
2056
+ TextField6,
2172
2057
  {
2173
2058
  size: "tiny",
2174
2059
  fullWidth: true,
@@ -2207,8 +2092,8 @@ import {
2207
2092
  Autocomplete as AutocompleteBase,
2208
2093
  Box as Box4,
2209
2094
  IconButton as IconButton2,
2210
- InputAdornment as InputAdornment4,
2211
- TextField as TextField8
2095
+ InputAdornment as InputAdornment3,
2096
+ TextField as TextField7
2212
2097
  } from "@elementor/ui";
2213
2098
  var Autocomplete = forwardRef4((props, ref) => {
2214
2099
  const {
@@ -2269,7 +2154,7 @@ var TextInput = ({
2269
2154
  handleChange(event.target.value);
2270
2155
  };
2271
2156
  return /* @__PURE__ */ React37.createElement(
2272
- TextField8,
2157
+ TextField7,
2273
2158
  {
2274
2159
  ...params,
2275
2160
  placeholder,
@@ -2290,7 +2175,7 @@ var ClearButton = ({
2290
2175
  allowClear,
2291
2176
  handleChange,
2292
2177
  params
2293
- }) => /* @__PURE__ */ React37.createElement(InputAdornment4, { position: "end" }, allowClear && /* @__PURE__ */ React37.createElement(IconButton2, { size: params.size, onClick: () => handleChange(null), sx: { cursor: "pointer" } }, /* @__PURE__ */ React37.createElement(XIcon2, { fontSize: params.size })));
2178
+ }) => /* @__PURE__ */ React37.createElement(InputAdornment3, { position: "end" }, allowClear && /* @__PURE__ */ React37.createElement(IconButton2, { size: params.size, onClick: () => handleChange(null), sx: { cursor: "pointer" } }, /* @__PURE__ */ React37.createElement(XIcon2, { fontSize: params.size })));
2294
2179
  function findMatchingOption(options, optionId = null) {
2295
2180
  const formattedOption = (optionId || "").toString();
2296
2181
  return options.find(({ id }) => formattedOption === id.toString());
@@ -2499,7 +2384,7 @@ var INFOTIP_CONTENT = {
2499
2384
 
2500
2385
  // src/controls/gap-control.tsx
2501
2386
  import * as React39 from "react";
2502
- import { useRef as useRef8 } from "react";
2387
+ import { useRef as useRef7 } from "react";
2503
2388
  import { layoutDirectionPropTypeUtil, sizePropTypeUtil as sizePropTypeUtil4 } from "@elementor/editor-props";
2504
2389
  import { DetachIcon as DetachIcon2, LinkIcon as LinkIcon2 } from "@elementor/icons";
2505
2390
  import { Grid as Grid8, Stack as Stack11, ToggleButton as ToggleButton4, Tooltip as Tooltip5 } from "@elementor/ui";
@@ -2511,7 +2396,7 @@ var GapControl = createControl(({ label }) => {
2511
2396
  propType,
2512
2397
  disabled: directionDisabled
2513
2398
  } = useBoundProp(layoutDirectionPropTypeUtil);
2514
- const stackRef = useRef8();
2399
+ const stackRef = useRef7();
2515
2400
  const { value: sizeValue, setValue: setSizeValue, disabled: sizeDisabled } = useBoundProp(sizePropTypeUtil4);
2516
2401
  const isLinked = !directionValue && !sizeValue ? true : !!sizeValue;
2517
2402
  const onLinkToggle = () => {
@@ -2561,7 +2446,7 @@ import { useState as useState8 } from "react";
2561
2446
  import { stringPropTypeUtil as stringPropTypeUtil7 } from "@elementor/editor-props";
2562
2447
  import { MenuListItem as MenuListItem3 } from "@elementor/editor-ui";
2563
2448
  import { ArrowsMoveHorizontalIcon, ArrowsMoveVerticalIcon } from "@elementor/icons";
2564
- import { Grid as Grid9, Select as Select2, Stack as Stack12, TextField as TextField9 } from "@elementor/ui";
2449
+ import { Grid as Grid9, Select as Select2, Stack as Stack12, TextField as TextField8 } from "@elementor/ui";
2565
2450
  import { __ as __11 } from "@wordpress/i18n";
2566
2451
  var RATIO_OPTIONS = [
2567
2452
  { label: __11("Auto", "elementor"), value: "auto" },
@@ -2623,7 +2508,7 @@ var AspectRatioControl = createControl(({ label }) => {
2623
2508
  ({ label: optionLabel, ...props }) => /* @__PURE__ */ React40.createElement(MenuListItem3, { key: props.value, ...props, value: props.value ?? "" }, optionLabel)
2624
2509
  )
2625
2510
  ))), isCustom && /* @__PURE__ */ React40.createElement(Grid9, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap" }, /* @__PURE__ */ React40.createElement(Grid9, { item: true, xs: 6 }, /* @__PURE__ */ React40.createElement(
2626
- TextField9,
2511
+ TextField8,
2627
2512
  {
2628
2513
  size: "tiny",
2629
2514
  type: "number",
@@ -2636,7 +2521,7 @@ var AspectRatioControl = createControl(({ label }) => {
2636
2521
  }
2637
2522
  }
2638
2523
  )), /* @__PURE__ */ React40.createElement(Grid9, { item: true, xs: 6 }, /* @__PURE__ */ React40.createElement(
2639
- TextField9,
2524
+ TextField8,
2640
2525
  {
2641
2526
  size: "tiny",
2642
2527
  type: "number",
@@ -2656,7 +2541,7 @@ import * as React42 from "react";
2656
2541
  import { useState as useState10 } from "react";
2657
2542
  import { imageSrcPropTypeUtil as imageSrcPropTypeUtil2 } from "@elementor/editor-props";
2658
2543
  import { UploadIcon as UploadIcon2 } from "@elementor/icons";
2659
- import { Button as Button4, Card as Card2, CardMedia as CardMedia2, CardOverlay as CardOverlay2, CircularProgress as CircularProgress3, Stack as Stack13, styled as styled5 } from "@elementor/ui";
2544
+ import { Button as Button4, Card as Card2, CardMedia as CardMedia2, CardOverlay as CardOverlay2, CircularProgress as CircularProgress3, Stack as Stack13, styled as styled4 } from "@elementor/ui";
2660
2545
  import { useWpMediaAttachment as useWpMediaAttachment2, useWpMediaFrame as useWpMediaFrame2 } from "@elementor/wp-media";
2661
2546
  import { __ as __13 } from "@wordpress/i18n";
2662
2547
 
@@ -2734,7 +2619,7 @@ var TILE_SIZE = 8;
2734
2619
  var TILE_WHITE = "transparent";
2735
2620
  var TILE_BLACK = "#c1c1c1";
2736
2621
  var TILES_GRADIENT_FORMULA = `linear-gradient(45deg, ${TILE_BLACK} 25%, ${TILE_WHITE} 0, ${TILE_WHITE} 75%, ${TILE_BLACK} 0, ${TILE_BLACK})`;
2737
- var StyledCard = styled5(Card2)`
2622
+ var StyledCard = styled4(Card2)`
2738
2623
  background-color: white;
2739
2624
  background-image: ${TILES_GRADIENT_FORMULA}, ${TILES_GRADIENT_FORMULA};
2740
2625
  background-size: ${TILE_SIZE}px ${TILE_SIZE}px;
@@ -2743,7 +2628,7 @@ var StyledCard = styled5(Card2)`
2743
2628
  ${TILE_SIZE / 2}px ${TILE_SIZE / 2}px;
2744
2629
  border: none;
2745
2630
  `;
2746
- var StyledCardMediaContainer = styled5(Stack13)`
2631
+ var StyledCardMediaContainer = styled4(Stack13)`
2747
2632
  position: relative;
2748
2633
  height: 140px;
2749
2634
  object-fit: contain;
@@ -2843,7 +2728,7 @@ import {
2843
2728
  backgroundOverlayPropTypeUtil,
2844
2729
  colorPropTypeUtil as colorPropTypeUtil3
2845
2730
  } from "@elementor/editor-props";
2846
- import { Box as Box6, CardMedia as CardMedia3, Grid as Grid14, styled as styled6, Tab, TabPanel, Tabs, UnstableColorIndicator as UnstableColorIndicator2 } from "@elementor/ui";
2731
+ import { Box as Box6, CardMedia as CardMedia3, Grid as Grid14, styled as styled5, Tab, TabPanel, Tabs, UnstableColorIndicator as UnstableColorIndicator2 } from "@elementor/ui";
2847
2732
  import { useWpMediaAttachment as useWpMediaAttachment3 } from "@elementor/wp-media";
2848
2733
  import { __ as __18 } from "@wordpress/i18n";
2849
2734
 
@@ -2948,7 +2833,7 @@ var BackgroundImageOverlayAttachment = () => {
2948
2833
 
2949
2834
  // src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-position.tsx
2950
2835
  import * as React45 from "react";
2951
- import { useRef as useRef9 } from "react";
2836
+ import { useRef as useRef8 } from "react";
2952
2837
  import { backgroundImagePositionOffsetPropTypeUtil, stringPropTypeUtil as stringPropTypeUtil9 } from "@elementor/editor-props";
2953
2838
  import { MenuListItem as MenuListItem4 } from "@elementor/editor-ui";
2954
2839
  import { LetterXIcon, LetterYIcon } from "@elementor/icons";
@@ -2970,7 +2855,7 @@ var BackgroundImageOverlayPosition = () => {
2970
2855
  const backgroundImageOffsetContext = useBoundProp(backgroundImagePositionOffsetPropTypeUtil);
2971
2856
  const stringPropContext = useBoundProp(stringPropTypeUtil9);
2972
2857
  const isCustom = !!backgroundImageOffsetContext.value;
2973
- const rowRef = useRef9();
2858
+ const rowRef = useRef8();
2974
2859
  const handlePositionChange = (event) => {
2975
2860
  const value = event.target.value || null;
2976
2861
  if (value === "custom") {
@@ -3041,7 +2926,7 @@ var BackgroundImageOverlayRepeat = () => {
3041
2926
 
3042
2927
  // src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-size.tsx
3043
2928
  import * as React47 from "react";
3044
- import { useRef as useRef10 } from "react";
2929
+ import { useRef as useRef9 } from "react";
3045
2930
  import { backgroundImageSizeScalePropTypeUtil, stringPropTypeUtil as stringPropTypeUtil10 } from "@elementor/editor-props";
3046
2931
  import {
3047
2932
  ArrowBarBothIcon,
@@ -3083,7 +2968,7 @@ var BackgroundImageOverlaySize = () => {
3083
2968
  const backgroundImageScaleContext = useBoundProp(backgroundImageSizeScalePropTypeUtil);
3084
2969
  const stringPropContext = useBoundProp(stringPropTypeUtil10);
3085
2970
  const isCustom = !!backgroundImageScaleContext.value;
3086
- const rowRef = useRef10();
2971
+ const rowRef = useRef9();
3087
2972
  const handleSizeChange = (size) => {
3088
2973
  if (size === "custom") {
3089
2974
  backgroundImageScaleContext.setValue({ width: null, height: null });
@@ -3118,7 +3003,7 @@ var BackgroundImageOverlaySize = () => {
3118
3003
  };
3119
3004
 
3120
3005
  // src/controls/background-control/background-overlay/use-background-tabs-history.ts
3121
- import { useRef as useRef11 } from "react";
3006
+ import { useRef as useRef10 } from "react";
3122
3007
  import {
3123
3008
  backgroundColorOverlayPropTypeUtil,
3124
3009
  backgroundGradientOverlayPropTypeUtil as backgroundGradientOverlayPropTypeUtil2,
@@ -3143,7 +3028,7 @@ var useBackgroundTabsHistory = ({
3143
3028
  return "image";
3144
3029
  };
3145
3030
  const { getTabsProps, getTabProps, getTabPanelProps } = useTabs(getCurrentOverlayType());
3146
- const valuesHistory = useRef11({
3031
+ const valuesHistory = useRef10({
3147
3032
  image: initialBackgroundImageOverlay,
3148
3033
  color: initialBackgroundColorOverlay2,
3149
3034
  gradient: initialBackgroundGradientOverlay2
@@ -3338,7 +3223,7 @@ var ImageOverlayContent = () => {
3338
3223
  }
3339
3224
  )))), /* @__PURE__ */ React48.createElement(PropKeyProvider, { bind: "position" }, /* @__PURE__ */ React48.createElement(BackgroundImageOverlayPosition, null)), /* @__PURE__ */ React48.createElement(PropKeyProvider, { bind: "repeat" }, /* @__PURE__ */ React48.createElement(BackgroundImageOverlayRepeat, null)), /* @__PURE__ */ React48.createElement(PropKeyProvider, { bind: "size" }, /* @__PURE__ */ React48.createElement(BackgroundImageOverlaySize, null)), /* @__PURE__ */ React48.createElement(PropKeyProvider, { bind: "attachment" }, /* @__PURE__ */ React48.createElement(BackgroundImageOverlayAttachment, null)));
3340
3225
  };
3341
- var StyledUnstableColorIndicator = styled6(UnstableColorIndicator2)(({ theme }) => ({
3226
+ var StyledUnstableColorIndicator = styled5(UnstableColorIndicator2)(({ theme }) => ({
3342
3227
  borderRadius: `${theme.shape.borderRadius / 2}px`
3343
3228
  }));
3344
3229
  var useImage = (image) => {
@@ -3390,6 +3275,188 @@ var SwitchControl2 = createControl(() => {
3390
3275
  };
3391
3276
  return /* @__PURE__ */ React50.createElement("div", { style: { display: "flex", justifyContent: "flex-end" } }, /* @__PURE__ */ React50.createElement(Switch2, { checked: !!value, onChange: handleChange, size: "small", disabled }));
3392
3277
  });
3278
+
3279
+ // src/controls/repeatable-control.tsx
3280
+ import * as React51 from "react";
3281
+ import { useMemo as useMemo4 } from "react";
3282
+ import { createArrayPropUtils } from "@elementor/editor-props";
3283
+ import { __ as __20 } from "@wordpress/i18n";
3284
+
3285
+ // src/hooks/use-repeatable-control-context.ts
3286
+ import { createContext as createContext6, useContext as useContext6 } from "react";
3287
+ var RepeatableControlContext = createContext6(void 0);
3288
+ var useRepeatableControlContext = () => {
3289
+ const context = useContext6(RepeatableControlContext);
3290
+ if (!context) {
3291
+ throw new Error("useRepeatableControlContext must be used within RepeatableControl");
3292
+ }
3293
+ return context;
3294
+ };
3295
+
3296
+ // src/controls/repeatable-control.tsx
3297
+ var RepeatableControl = createControl(
3298
+ ({ label, childControlConfig, showDuplicate, showToggle }) => {
3299
+ const { propTypeUtil: childPropTypeUtil } = childControlConfig;
3300
+ if (!childPropTypeUtil) {
3301
+ return null;
3302
+ }
3303
+ const childArrayPropTypeUtil = useMemo4(
3304
+ () => createArrayPropUtils(childPropTypeUtil.key, childPropTypeUtil.schema),
3305
+ [childPropTypeUtil.key, childPropTypeUtil.schema]
3306
+ );
3307
+ const { propType, value, setValue } = useBoundProp(childArrayPropTypeUtil);
3308
+ return /* @__PURE__ */ React51.createElement(PropProvider, { propType, value, setValue }, /* @__PURE__ */ React51.createElement(RepeatableControlContext.Provider, { value: childControlConfig }, /* @__PURE__ */ React51.createElement(
3309
+ Repeater,
3310
+ {
3311
+ openOnAdd: true,
3312
+ values: value ?? [],
3313
+ setValues: setValue,
3314
+ label,
3315
+ itemSettings: {
3316
+ Icon: ItemIcon3,
3317
+ Label: ItemLabel3,
3318
+ Content: ItemContent3,
3319
+ initialValues: childPropTypeUtil.create(null)
3320
+ },
3321
+ showDuplicate,
3322
+ showToggle
3323
+ }
3324
+ )));
3325
+ }
3326
+ );
3327
+ var ItemContent3 = ({ bind }) => {
3328
+ return /* @__PURE__ */ React51.createElement(PropKeyProvider, { bind }, /* @__PURE__ */ React51.createElement(Content3, null));
3329
+ };
3330
+ var ItemIcon3 = () => /* @__PURE__ */ React51.createElement(React51.Fragment, null);
3331
+ var Content3 = () => {
3332
+ const { component: ChildControl, props = {} } = useRepeatableControlContext();
3333
+ return /* @__PURE__ */ React51.createElement(PopoverContent, { p: 1.5 }, /* @__PURE__ */ React51.createElement(PopoverGridContainer, null, /* @__PURE__ */ React51.createElement(ChildControl, { ...props })));
3334
+ };
3335
+ var ItemLabel3 = () => {
3336
+ const { label = __20("Empty", "elementor") } = useRepeatableControlContext();
3337
+ return /* @__PURE__ */ React51.createElement("span", null, label);
3338
+ };
3339
+
3340
+ // src/controls/key-value-control.tsx
3341
+ import * as React52 from "react";
3342
+ import { useMemo as useMemo5, useState as useState11 } from "react";
3343
+ import { keyValuePropTypeUtil } from "@elementor/editor-props";
3344
+ import { FormHelperText, FormLabel as FormLabel3, Grid as Grid16, TextField as TextField9 } from "@elementor/ui";
3345
+ import { __ as __21 } from "@wordpress/i18n";
3346
+ var KeyValueControl = createControl((props = {}) => {
3347
+ const { value, setValue } = useBoundProp(keyValuePropTypeUtil);
3348
+ const [keyError, setKeyError] = useState11(null);
3349
+ const [valueError, setValueError] = useState11(null);
3350
+ const keyLabel = props.keyName || __21("Key", "elementor");
3351
+ const valueLabel = props.valueName || __21("Value", "elementor");
3352
+ const keyValue = value?.key?.value || "";
3353
+ const valueValue = value?.value?.value || "";
3354
+ const [keyRegex, valueRegex, errMsg] = useMemo5(
3355
+ () => [
3356
+ props.regexKey ? new RegExp(props.regexKey) : void 0,
3357
+ props.regexValue ? new RegExp(props.regexValue) : void 0,
3358
+ props.validationErrorMessage || __21("Invalid Format", "elementor")
3359
+ ],
3360
+ [props.regexKey, props.regexValue, props.validationErrorMessage]
3361
+ );
3362
+ const validate = (newValue, FieldType) => {
3363
+ if (FieldType === "key" && keyRegex) {
3364
+ const isValid = keyRegex.test(newValue);
3365
+ setKeyError(isValid ? null : errMsg);
3366
+ } else if (FieldType === "value" && valueRegex) {
3367
+ const isValid = valueRegex.test(newValue);
3368
+ setValueError(isValid ? null : errMsg);
3369
+ }
3370
+ };
3371
+ const handleChange = (event, fieldType) => {
3372
+ const newValue = event.target.value;
3373
+ validate(newValue, fieldType);
3374
+ setValue({
3375
+ ...value,
3376
+ [fieldType]: {
3377
+ value: newValue,
3378
+ $$type: "string"
3379
+ }
3380
+ });
3381
+ };
3382
+ const isKeyInvalid = keyError !== null;
3383
+ const isValueInvalid = valueError !== null;
3384
+ return /* @__PURE__ */ React52.createElement(ControlActions, null, /* @__PURE__ */ React52.createElement(Grid16, { container: true, gap: 1.5, p: 1.5, sx: props.sx }, /* @__PURE__ */ React52.createElement(Grid16, { item: true, xs: 12 }, /* @__PURE__ */ React52.createElement(FormLabel3, { size: "tiny" }, keyLabel), /* @__PURE__ */ React52.createElement(
3385
+ TextField9,
3386
+ {
3387
+ sx: { pt: 1 },
3388
+ size: "tiny",
3389
+ fullWidth: true,
3390
+ value: keyValue,
3391
+ onChange: (e) => handleChange(e, "key"),
3392
+ error: isKeyInvalid
3393
+ }
3394
+ ), isKeyInvalid && /* @__PURE__ */ React52.createElement(FormHelperText, { error: true }, keyError)), /* @__PURE__ */ React52.createElement(Grid16, { item: true, xs: 12 }, /* @__PURE__ */ React52.createElement(FormLabel3, { size: "tiny" }, valueLabel), /* @__PURE__ */ React52.createElement(
3395
+ TextField9,
3396
+ {
3397
+ sx: { pt: 1 },
3398
+ size: "tiny",
3399
+ fullWidth: true,
3400
+ value: valueValue,
3401
+ onChange: (e) => handleChange(e, "value"),
3402
+ disabled: isKeyInvalid,
3403
+ error: isValueInvalid
3404
+ }
3405
+ ), isValueInvalid && /* @__PURE__ */ React52.createElement(FormHelperText, { error: true }, valueError))));
3406
+ });
3407
+
3408
+ // src/controls/position-control.tsx
3409
+ import * as React53 from "react";
3410
+ import { useMemo as useMemo6 } from "react";
3411
+ import { positionPropTypeUtil, stringPropTypeUtil as stringPropTypeUtil11 } from "@elementor/editor-props";
3412
+ import { MenuListItem as MenuListItem5 } from "@elementor/editor-ui";
3413
+ import { isExperimentActive as isExperimentActive5 } from "@elementor/editor-v1-adapters";
3414
+ import { LetterXIcon as LetterXIcon2, LetterYIcon as LetterYIcon2 } from "@elementor/icons";
3415
+ import { Grid as Grid17, Select as Select4 } from "@elementor/ui";
3416
+ import { __ as __22 } from "@wordpress/i18n";
3417
+ var positionOptions = [
3418
+ { label: __22("Center center", "elementor"), value: "center center" },
3419
+ { label: __22("Center left", "elementor"), value: "center left" },
3420
+ { label: __22("Center right", "elementor"), value: "center right" },
3421
+ { label: __22("Top center", "elementor"), value: "top center" },
3422
+ { label: __22("Top left", "elementor"), value: "top left" },
3423
+ { label: __22("Top right", "elementor"), value: "top right" },
3424
+ { label: __22("Bottom center", "elementor"), value: "bottom center" },
3425
+ { label: __22("Bottom left", "elementor"), value: "bottom left" },
3426
+ { label: __22("Bottom right", "elementor"), value: "bottom right" }
3427
+ ];
3428
+ var PositionControl = () => {
3429
+ const positionContext = useBoundProp(positionPropTypeUtil);
3430
+ const stringPropContext = useBoundProp(stringPropTypeUtil11);
3431
+ const isVersion331Active = isExperimentActive5("e_v_3_31");
3432
+ const isCustom = !!positionContext.value && isVersion331Active;
3433
+ const availablePositionOptions = useMemo6(() => {
3434
+ const options = [...positionOptions];
3435
+ if (isVersion331Active) {
3436
+ options.push({ label: __22("Custom", "elementor"), value: "custom" });
3437
+ }
3438
+ return options;
3439
+ }, [isVersion331Active]);
3440
+ const handlePositionChange = (event) => {
3441
+ const value = event.target.value || null;
3442
+ if (value === "custom" && isVersion331Active) {
3443
+ positionContext.setValue({ x: null, y: null });
3444
+ } else {
3445
+ stringPropContext.setValue(value);
3446
+ }
3447
+ };
3448
+ return /* @__PURE__ */ React53.createElement(Grid17, { container: true, spacing: 1.5 }, /* @__PURE__ */ React53.createElement(Grid17, { item: true, xs: 12 }, /* @__PURE__ */ React53.createElement(Grid17, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap" }, /* @__PURE__ */ React53.createElement(Grid17, { item: true, xs: 6 }, /* @__PURE__ */ React53.createElement(ControlFormLabel, null, __22("Object position", "elementor"))), /* @__PURE__ */ React53.createElement(Grid17, { item: true, xs: 6, sx: { overflow: "hidden" } }, /* @__PURE__ */ React53.createElement(
3449
+ Select4,
3450
+ {
3451
+ size: "tiny",
3452
+ disabled: stringPropContext.disabled,
3453
+ value: (positionContext.value ? "custom" : stringPropContext.value) ?? "",
3454
+ onChange: handlePositionChange,
3455
+ fullWidth: true
3456
+ },
3457
+ availablePositionOptions.map(({ label, value }) => /* @__PURE__ */ React53.createElement(MenuListItem5, { key: value, value: value ?? "" }, label))
3458
+ )))), isCustom && /* @__PURE__ */ React53.createElement(PropProvider, { ...positionContext }, /* @__PURE__ */ React53.createElement(Grid17, { item: true, xs: 12 }, /* @__PURE__ */ React53.createElement(Grid17, { container: true, spacing: 1.5 }, /* @__PURE__ */ React53.createElement(Grid17, { item: true, xs: 6 }, /* @__PURE__ */ React53.createElement(PropKeyProvider, { bind: "x" }, /* @__PURE__ */ React53.createElement(SizeControl, { startIcon: /* @__PURE__ */ React53.createElement(LetterXIcon2, { fontSize: "tiny" }) }))), /* @__PURE__ */ React53.createElement(Grid17, { item: true, xs: 6 }, /* @__PURE__ */ React53.createElement(PropKeyProvider, { bind: "y" }, /* @__PURE__ */ React53.createElement(SizeControl, { startIcon: /* @__PURE__ */ React53.createElement(LetterYIcon2, { fontSize: "tiny" }) })))))));
3459
+ };
3393
3460
  export {
3394
3461
  AspectRatioControl,
3395
3462
  BackgroundControl,
@@ -3406,11 +3473,14 @@ export {
3406
3473
  FontFamilySelector,
3407
3474
  GapControl,
3408
3475
  ImageControl,
3476
+ KeyValueControl,
3409
3477
  LinkControl,
3410
3478
  LinkedDimensionsControl,
3411
3479
  NumberControl,
3480
+ PositionControl,
3412
3481
  PropKeyProvider,
3413
3482
  PropProvider,
3483
+ RepeatableControl,
3414
3484
  SelectControl,
3415
3485
  SizeControl,
3416
3486
  StrokeControl,