@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.js CHANGED
@@ -45,11 +45,14 @@ __export(index_exports, {
45
45
  FontFamilySelector: () => FontFamilySelector,
46
46
  GapControl: () => GapControl,
47
47
  ImageControl: () => ImageControl,
48
+ KeyValueControl: () => KeyValueControl,
48
49
  LinkControl: () => LinkControl,
49
50
  LinkedDimensionsControl: () => LinkedDimensionsControl,
50
51
  NumberControl: () => NumberControl,
52
+ PositionControl: () => PositionControl,
51
53
  PropKeyProvider: () => PropKeyProvider,
52
54
  PropProvider: () => PropProvider,
55
+ RepeatableControl: () => RepeatableControl,
53
56
  SelectControl: () => SelectControl,
54
57
  SizeControl: () => SizeControl,
55
58
  StrokeControl: () => StrokeControl,
@@ -784,9 +787,10 @@ var useSyncExternalState = ({
784
787
  var DEFAULT_UNIT = "px";
785
788
  var DEFAULT_SIZE = NaN;
786
789
  var SizeControl = createControl((props) => {
790
+ const defaultUnit = props.defaultUnit ?? DEFAULT_UNIT;
787
791
  const { units: units2 = [...defaultUnits], placeholder, startIcon, anchorRef } = props;
788
792
  const { value: sizeValue, setValue: setSizeValue, disabled, restoreValue } = useBoundProp(import_editor_props6.sizePropTypeUtil);
789
- const [internalState, setInternalState] = (0, import_react10.useState)(createStateFromSizeProp(sizeValue));
793
+ const [internalState, setInternalState] = (0, import_react10.useState)(createStateFromSizeProp(sizeValue, defaultUnit));
790
794
  const activeBreakpoint = (0, import_editor_responsive.useActiveBreakpoint)();
791
795
  const extendedOptions = useSizeExtendedOptions(props.extendedOptions || [], props.disableCustom ?? false);
792
796
  const popupState = (0, import_ui12.usePopupState)({ variant: "popover" });
@@ -803,7 +807,7 @@ var SizeControl = createControl((props) => {
803
807
  return !!newState?.numeric || newState?.numeric === 0;
804
808
  },
805
809
  fallback: (newState) => ({
806
- unit: newState?.unit ?? DEFAULT_UNIT,
810
+ unit: newState?.unit ?? props.defaultUnit ?? DEFAULT_UNIT,
807
811
  numeric: newState?.numeric ?? DEFAULT_SIZE,
808
812
  custom: newState?.custom ?? ""
809
813
  })
@@ -838,7 +842,7 @@ var SizeControl = createControl((props) => {
838
842
  }
839
843
  };
840
844
  (0, import_react10.useEffect)(() => {
841
- const newState = createStateFromSizeProp(sizeValue);
845
+ const newState = createStateFromSizeProp(sizeValue, defaultUnit);
842
846
  const currentUnit = isUnitExtendedOption(state.unit) ? "custom" : "numeric";
843
847
  const mergedStates = { ...state, [currentUnit]: newState[currentUnit] };
844
848
  if (mergedStates.unit !== "auto" && areStatesEqual(state, mergedStates)) {
@@ -851,7 +855,7 @@ var SizeControl = createControl((props) => {
851
855
  setState(newState);
852
856
  }, [sizeValue]);
853
857
  (0, import_react10.useEffect)(() => {
854
- const newState = createStateFromSizeProp(sizeValue);
858
+ const newState = createStateFromSizeProp(sizeValue, defaultUnit);
855
859
  if (activeBreakpoint && !areStatesEqual(newState, state)) {
856
860
  setState(newState);
857
861
  }
@@ -889,8 +893,8 @@ function formatSize(size, unit) {
889
893
  }
890
894
  return size || size === 0 ? Number(size) : NaN;
891
895
  }
892
- function createStateFromSizeProp(sizeValue) {
893
- const unit = sizeValue?.unit ?? DEFAULT_UNIT;
896
+ function createStateFromSizeProp(sizeValue, defaultUnit) {
897
+ const unit = sizeValue?.unit ?? defaultUnit;
894
898
  const size = sizeValue?.size ?? "";
895
899
  return {
896
900
  numeric: !isUnitExtendedOption(unit) && !isNaN(Number(size)) && (size || size === 0) ? Number(size) : DEFAULT_SIZE,
@@ -1120,7 +1124,9 @@ var Repeater = ({
1120
1124
  openOnAdd = false,
1121
1125
  addToBottom = false,
1122
1126
  values: repeaterValues = [],
1123
- setValues: setRepeaterValues
1127
+ setValues: setRepeaterValues,
1128
+ showDuplicate = true,
1129
+ showToggle = true
1124
1130
  }) => {
1125
1131
  const [openItem, setOpenItem] = (0, import_react14.useState)(EMPTY_OPEN_ITEM);
1126
1132
  const [items, setItems] = useSyncExternalState({
@@ -1224,7 +1230,9 @@ var Repeater = ({
1224
1230
  duplicateItem: () => duplicateRepeaterItem(index),
1225
1231
  toggleDisableItem: () => toggleDisableRepeaterItem(index),
1226
1232
  openOnMount: openOnAdd && openItem === key,
1227
- onOpen: () => setOpenItem(EMPTY_OPEN_ITEM)
1233
+ onOpen: () => setOpenItem(EMPTY_OPEN_ITEM),
1234
+ showDuplicate,
1235
+ showToggle
1228
1236
  },
1229
1237
  (props) => /* @__PURE__ */ React25.createElement(itemSettings.Content, { ...props, value, bind: String(index) })
1230
1238
  ));
@@ -1240,6 +1248,8 @@ var RepeaterItem = ({
1240
1248
  toggleDisableItem,
1241
1249
  openOnMount,
1242
1250
  onOpen,
1251
+ showDuplicate,
1252
+ showToggle,
1243
1253
  disabled
1244
1254
  }) => {
1245
1255
  const [anchorEl, setAnchorEl] = (0, import_react14.useState)(null);
@@ -1259,7 +1269,7 @@ var RepeaterItem = ({
1259
1269
  "aria-label": (0, import_i18n4.__)("Open item", "elementor"),
1260
1270
  ...(0, import_ui19.bindTrigger)(popoverState),
1261
1271
  startIcon,
1262
- actions: /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(import_ui19.Tooltip, { title: duplicateLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(import_ui19.IconButton, { size: SIZE, onClick: duplicateItem, "aria-label": duplicateLabel }, /* @__PURE__ */ React25.createElement(import_icons4.CopyIcon, { fontSize: SIZE }))), /* @__PURE__ */ React25.createElement(import_ui19.Tooltip, { title: toggleLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(import_ui19.IconButton, { size: SIZE, onClick: toggleDisableItem, "aria-label": toggleLabel }, propDisabled ? /* @__PURE__ */ React25.createElement(import_icons4.EyeOffIcon, { fontSize: SIZE }) : /* @__PURE__ */ React25.createElement(import_icons4.EyeIcon, { fontSize: SIZE }))), /* @__PURE__ */ React25.createElement(import_ui19.Tooltip, { title: removeLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(import_ui19.IconButton, { size: SIZE, onClick: removeItem, "aria-label": removeLabel }, /* @__PURE__ */ React25.createElement(import_icons4.XIcon, { fontSize: SIZE }))))
1272
+ actions: /* @__PURE__ */ React25.createElement(React25.Fragment, null, showDuplicate && /* @__PURE__ */ React25.createElement(import_ui19.Tooltip, { title: duplicateLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(import_ui19.IconButton, { size: SIZE, onClick: duplicateItem, "aria-label": duplicateLabel }, /* @__PURE__ */ React25.createElement(import_icons4.CopyIcon, { fontSize: SIZE }))), showToggle && /* @__PURE__ */ React25.createElement(import_ui19.Tooltip, { title: toggleLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(import_ui19.IconButton, { size: SIZE, onClick: toggleDisableItem, "aria-label": toggleLabel }, propDisabled ? /* @__PURE__ */ React25.createElement(import_icons4.EyeOffIcon, { fontSize: SIZE }) : /* @__PURE__ */ React25.createElement(import_icons4.EyeIcon, { fontSize: SIZE }))), /* @__PURE__ */ React25.createElement(import_ui19.Tooltip, { title: removeLabel, placement: "top" }, /* @__PURE__ */ React25.createElement(import_ui19.IconButton, { size: SIZE, onClick: removeItem, "aria-label": removeLabel }, /* @__PURE__ */ React25.createElement(import_icons4.XIcon, { fontSize: SIZE }))))
1263
1273
  }
1264
1274
  ), /* @__PURE__ */ React25.createElement(
1265
1275
  import_ui19.Popover,
@@ -1457,14 +1467,14 @@ var ControlToggleButtonGroup = ({
1457
1467
  width: `100%`
1458
1468
  }
1459
1469
  },
1460
- fixedItems.map(({ label, value: buttonValue, renderContent: Content3, showTooltip }) => /* @__PURE__ */ React28.createElement(
1470
+ fixedItems.map(({ label, value: buttonValue, renderContent: Content4, showTooltip }) => /* @__PURE__ */ React28.createElement(
1461
1471
  ConditionalTooltip,
1462
1472
  {
1463
1473
  key: buttonValue,
1464
1474
  label,
1465
1475
  showTooltip: showTooltip || false
1466
1476
  },
1467
- /* @__PURE__ */ React28.createElement(import_ui22.ToggleButton, { value: buttonValue, "aria-label": label, size, fullWidth }, /* @__PURE__ */ React28.createElement(Content3, { size }))
1477
+ /* @__PURE__ */ React28.createElement(import_ui22.ToggleButton, { value: buttonValue, "aria-label": label, size, fullWidth }, /* @__PURE__ */ React28.createElement(Content4, { size }))
1468
1478
  )),
1469
1479
  menuItems.length && exclusive && /* @__PURE__ */ React28.createElement(
1470
1480
  SplitButtonGroup,
@@ -1915,13 +1925,12 @@ var import_icons8 = require("@elementor/icons");
1915
1925
  var import_ui28 = require("@elementor/ui");
1916
1926
 
1917
1927
  // src/components/font-family-selector.tsx
1918
- var import_react19 = require("react");
1919
1928
  var React34 = __toESM(require("react"));
1929
+ var import_react19 = require("react");
1920
1930
  var import_editor_ui3 = require("@elementor/editor-ui");
1921
1931
  var import_icons7 = require("@elementor/icons");
1922
1932
  var import_ui27 = require("@elementor/ui");
1923
1933
  var import_utils2 = require("@elementor/utils");
1924
- var import_react_virtual = require("@tanstack/react-virtual");
1925
1934
  var import_i18n8 = require("@wordpress/i18n");
1926
1935
 
1927
1936
  // src/controls/font-family-control/enqueue-font.tsx
@@ -1956,8 +1965,8 @@ var FontFamilySelector = ({
1956
1965
  }) => {
1957
1966
  const [searchValue, setSearchValue] = (0, import_react19.useState)("");
1958
1967
  const filteredFontFamilies = useFilteredFontFamilies(fontFamilies, searchValue);
1959
- const handleSearch = (event) => {
1960
- setSearchValue(event.target.value);
1968
+ const handleSearch = (value) => {
1969
+ setSearchValue(value);
1961
1970
  };
1962
1971
  const handleClose = () => {
1963
1972
  setSearchValue("");
@@ -1970,20 +1979,14 @@ var FontFamilySelector = ({
1970
1979
  onClose: handleClose,
1971
1980
  icon: /* @__PURE__ */ React34.createElement(import_icons7.TextIcon, { fontSize: SIZE2 })
1972
1981
  }
1973
- ), /* @__PURE__ */ React34.createElement(import_ui27.Box, { px: 1.5, pb: 1 }, /* @__PURE__ */ React34.createElement(
1974
- import_ui27.TextField,
1982
+ ), /* @__PURE__ */ React34.createElement(
1983
+ import_editor_ui3.PopoverSearch,
1975
1984
  {
1976
- autoFocus: true,
1977
- fullWidth: true,
1978
- size: SIZE2,
1979
1985
  value: searchValue,
1980
- placeholder: (0, import_i18n8.__)("Search", "elementor"),
1981
- onChange: handleSearch,
1982
- InputProps: {
1983
- startAdornment: /* @__PURE__ */ React34.createElement(import_ui27.InputAdornment, { position: "start" }, /* @__PURE__ */ React34.createElement(import_icons7.SearchIcon, { fontSize: SIZE2 }))
1984
- }
1986
+ onSearch: handleSearch,
1987
+ placeholder: (0, import_i18n8.__)("Search", "elementor")
1985
1988
  }
1986
- )), /* @__PURE__ */ React34.createElement(import_ui27.Divider, null), filteredFontFamilies.length > 0 ? /* @__PURE__ */ React34.createElement(
1989
+ ), /* @__PURE__ */ React34.createElement(import_ui27.Divider, null), filteredFontFamilies.length > 0 ? /* @__PURE__ */ React34.createElement(
1987
1990
  FontList,
1988
1991
  {
1989
1992
  fontListItems: filteredFontFamilies,
@@ -1991,7 +1994,7 @@ var FontFamilySelector = ({
1991
1994
  handleClose,
1992
1995
  fontFamily
1993
1996
  }
1994
- ) : /* @__PURE__ */ React34.createElement(import_ui27.Box, { sx: { overflowY: "auto", height: 260, width: 220 } }, /* @__PURE__ */ React34.createElement(import_ui27.Stack, { alignItems: "center", p: 2.5, gap: 1.5, overflow: "hidden" }, /* @__PURE__ */ React34.createElement(import_icons7.TextIcon, { fontSize: "large" }), /* @__PURE__ */ React34.createElement(import_ui27.Box, { sx: { maxWidth: 160, overflow: "hidden" } }, /* @__PURE__ */ React34.createElement(import_ui27.Typography, { align: "center", variant: "subtitle2", color: "text.secondary" }, (0, import_i18n8.__)("Sorry, nothing matched", "elementor")), /* @__PURE__ */ React34.createElement(
1997
+ ) : /* @__PURE__ */ React34.createElement(import_editor_ui3.PopoverScrollableContent, null, /* @__PURE__ */ React34.createElement(import_ui27.Stack, { alignItems: "center", p: 2.5, gap: 1.5, overflow: "hidden" }, /* @__PURE__ */ React34.createElement(import_icons7.TextIcon, { fontSize: "large" }), /* @__PURE__ */ React34.createElement(import_ui27.Box, { sx: { maxWidth: 160, overflow: "hidden" } }, /* @__PURE__ */ React34.createElement(import_ui27.Typography, { align: "center", variant: "subtitle2", color: "text.secondary" }, (0, import_i18n8.__)("Sorry, nothing matched", "elementor")), /* @__PURE__ */ React34.createElement(
1995
1998
  import_ui27.Typography,
1996
1999
  {
1997
2000
  variant: "subtitle2",
@@ -2016,10 +2019,7 @@ var FontFamilySelector = ({
2016
2019
  (0, import_i18n8.__)("Clear & try again", "elementor")
2017
2020
  )))));
2018
2021
  };
2019
- var LIST_ITEM_HEIGHT = 36;
2020
- var LIST_ITEMS_BUFFER = 6;
2021
2022
  var FontList = ({ fontListItems, setFontFamily, handleClose, fontFamily }) => {
2022
- const containerRef = (0, import_react19.useRef)(null);
2023
2023
  const selectedItem = fontListItems.find((item) => item.value === fontFamily);
2024
2024
  const debouncedVirtualizeChange = useDebounce(({ getVirtualIndexes }) => {
2025
2025
  getVirtualIndexes().forEach((index) => {
@@ -2029,120 +2029,19 @@ var FontList = ({ fontListItems, setFontFamily, handleClose, fontFamily }) => {
2029
2029
  }
2030
2030
  });
2031
2031
  }, 100);
2032
- const virtualizer = (0, import_react_virtual.useVirtualizer)({
2033
- count: fontListItems.length,
2034
- getScrollElement: () => containerRef.current,
2035
- estimateSize: () => LIST_ITEM_HEIGHT,
2036
- overscan: LIST_ITEMS_BUFFER,
2037
- onChange: debouncedVirtualizeChange
2038
- });
2039
- (0, import_react19.useEffect)(
2040
- () => {
2041
- virtualizer.scrollToIndex(fontListItems.findIndex((item) => item.value === fontFamily));
2042
- },
2043
- // eslint-disable-next-line react-compiler/react-compiler
2044
- // eslint-disable-next-line react-hooks/exhaustive-deps
2045
- [fontFamily]
2046
- );
2047
2032
  return /* @__PURE__ */ React34.createElement(
2048
- import_ui27.Box,
2033
+ import_editor_ui3.PopoverMenuList,
2049
2034
  {
2050
- ref: containerRef,
2051
- sx: {
2052
- overflowY: "auto",
2053
- height: 260,
2054
- width: 220
2055
- }
2056
- },
2057
- /* @__PURE__ */ React34.createElement(
2058
- StyledMenuList,
2059
- {
2060
- role: "listbox",
2061
- style: {
2062
- height: `${virtualizer.getTotalSize()}px`
2063
- },
2064
- "data-testid": "font-list"
2065
- },
2066
- virtualizer.getVirtualItems().map((virtualRow) => {
2067
- const item = fontListItems[virtualRow.index];
2068
- const isLast = virtualRow.index === fontListItems.length - 1;
2069
- const isFirst = virtualRow.index === 1;
2070
- const isSelected = selectedItem?.value === item.value;
2071
- const tabIndexFallback = !selectedItem ? 0 : -1;
2072
- if (item.type === "category") {
2073
- return /* @__PURE__ */ React34.createElement(
2074
- import_ui27.MenuSubheader,
2075
- {
2076
- key: virtualRow.key,
2077
- style: {
2078
- transform: `translateY(${virtualRow.start}px)`
2079
- }
2080
- },
2081
- item.value
2082
- );
2083
- }
2084
- return /* @__PURE__ */ React34.createElement(
2085
- "li",
2086
- {
2087
- key: virtualRow.key,
2088
- role: "option",
2089
- "aria-selected": isSelected,
2090
- onClick: () => {
2091
- setFontFamily(item.value);
2092
- handleClose();
2093
- },
2094
- onKeyDown: (event) => {
2095
- if (event.key === "Enter") {
2096
- setFontFamily(item.value);
2097
- handleClose();
2098
- }
2099
- if (event.key === "ArrowDown" && isLast) {
2100
- event.preventDefault();
2101
- event.stopPropagation();
2102
- }
2103
- if (event.key === "ArrowUp" && isFirst) {
2104
- event.preventDefault();
2105
- event.stopPropagation();
2106
- }
2107
- },
2108
- tabIndex: isSelected ? 0 : tabIndexFallback,
2109
- style: {
2110
- transform: `translateY(${virtualRow.start}px)`,
2111
- fontFamily: item.value
2112
- }
2113
- },
2114
- item.value
2115
- );
2116
- })
2117
- )
2035
+ items: fontListItems,
2036
+ selectedValue: selectedItem?.value,
2037
+ onChange: debouncedVirtualizeChange,
2038
+ onSelect: setFontFamily,
2039
+ onClose: handleClose,
2040
+ itemStyle: (item) => ({ fontFamily: item.value }),
2041
+ "data-testid": "font-list"
2042
+ }
2118
2043
  );
2119
2044
  };
2120
- var StyledMenuList = (0, import_ui27.styled)(import_ui27.MenuList)(({ theme }) => ({
2121
- "& > li": {
2122
- height: LIST_ITEM_HEIGHT,
2123
- position: "absolute",
2124
- top: 0,
2125
- left: 0,
2126
- width: "100%",
2127
- display: "flex",
2128
- alignItems: "center"
2129
- },
2130
- '& > [role="option"]': {
2131
- ...theme.typography.caption,
2132
- lineHeight: "inherit",
2133
- padding: theme.spacing(0.75, 2, 0.75, 4),
2134
- "&:hover, &:focus": {
2135
- backgroundColor: theme.palette.action.hover
2136
- },
2137
- '&[aria-selected="true"]': {
2138
- backgroundColor: theme.palette.action.selected
2139
- },
2140
- cursor: "pointer",
2141
- textOverflow: "ellipsis"
2142
- },
2143
- width: "100%",
2144
- position: "relative"
2145
- }));
2146
2045
  var useDebounce = (fn, delay) => {
2147
2046
  const [debouncedFn] = (0, import_react19.useState)(() => (0, import_utils2.debounce)(fn, delay));
2148
2047
  (0, import_react19.useEffect)(() => () => debouncedFn.cancel(), [debouncedFn]);
@@ -3369,6 +3268,188 @@ var SwitchControl2 = createControl(() => {
3369
3268
  };
3370
3269
  return /* @__PURE__ */ React50.createElement("div", { style: { display: "flex", justifyContent: "flex-end" } }, /* @__PURE__ */ React50.createElement(import_ui44.Switch, { checked: !!value, onChange: handleChange, size: "small", disabled }));
3371
3270
  });
3271
+
3272
+ // src/controls/repeatable-control.tsx
3273
+ var React51 = __toESM(require("react"));
3274
+ var import_react30 = require("react");
3275
+ var import_editor_props27 = require("@elementor/editor-props");
3276
+ var import_i18n20 = require("@wordpress/i18n");
3277
+
3278
+ // src/hooks/use-repeatable-control-context.ts
3279
+ var import_react29 = require("react");
3280
+ var RepeatableControlContext = (0, import_react29.createContext)(void 0);
3281
+ var useRepeatableControlContext = () => {
3282
+ const context = (0, import_react29.useContext)(RepeatableControlContext);
3283
+ if (!context) {
3284
+ throw new Error("useRepeatableControlContext must be used within RepeatableControl");
3285
+ }
3286
+ return context;
3287
+ };
3288
+
3289
+ // src/controls/repeatable-control.tsx
3290
+ var RepeatableControl = createControl(
3291
+ ({ label, childControlConfig, showDuplicate, showToggle }) => {
3292
+ const { propTypeUtil: childPropTypeUtil } = childControlConfig;
3293
+ if (!childPropTypeUtil) {
3294
+ return null;
3295
+ }
3296
+ const childArrayPropTypeUtil = (0, import_react30.useMemo)(
3297
+ () => (0, import_editor_props27.createArrayPropUtils)(childPropTypeUtil.key, childPropTypeUtil.schema),
3298
+ [childPropTypeUtil.key, childPropTypeUtil.schema]
3299
+ );
3300
+ const { propType, value, setValue } = useBoundProp(childArrayPropTypeUtil);
3301
+ return /* @__PURE__ */ React51.createElement(PropProvider, { propType, value, setValue }, /* @__PURE__ */ React51.createElement(RepeatableControlContext.Provider, { value: childControlConfig }, /* @__PURE__ */ React51.createElement(
3302
+ Repeater,
3303
+ {
3304
+ openOnAdd: true,
3305
+ values: value ?? [],
3306
+ setValues: setValue,
3307
+ label,
3308
+ itemSettings: {
3309
+ Icon: ItemIcon3,
3310
+ Label: ItemLabel3,
3311
+ Content: ItemContent3,
3312
+ initialValues: childPropTypeUtil.create(null)
3313
+ },
3314
+ showDuplicate,
3315
+ showToggle
3316
+ }
3317
+ )));
3318
+ }
3319
+ );
3320
+ var ItemContent3 = ({ bind }) => {
3321
+ return /* @__PURE__ */ React51.createElement(PropKeyProvider, { bind }, /* @__PURE__ */ React51.createElement(Content3, null));
3322
+ };
3323
+ var ItemIcon3 = () => /* @__PURE__ */ React51.createElement(React51.Fragment, null);
3324
+ var Content3 = () => {
3325
+ const { component: ChildControl, props = {} } = useRepeatableControlContext();
3326
+ return /* @__PURE__ */ React51.createElement(PopoverContent, { p: 1.5 }, /* @__PURE__ */ React51.createElement(PopoverGridContainer, null, /* @__PURE__ */ React51.createElement(ChildControl, { ...props })));
3327
+ };
3328
+ var ItemLabel3 = () => {
3329
+ const { label = (0, import_i18n20.__)("Empty", "elementor") } = useRepeatableControlContext();
3330
+ return /* @__PURE__ */ React51.createElement("span", null, label);
3331
+ };
3332
+
3333
+ // src/controls/key-value-control.tsx
3334
+ var React52 = __toESM(require("react"));
3335
+ var import_react31 = require("react");
3336
+ var import_editor_props28 = require("@elementor/editor-props");
3337
+ var import_ui45 = require("@elementor/ui");
3338
+ var import_i18n21 = require("@wordpress/i18n");
3339
+ var KeyValueControl = createControl((props = {}) => {
3340
+ const { value, setValue } = useBoundProp(import_editor_props28.keyValuePropTypeUtil);
3341
+ const [keyError, setKeyError] = (0, import_react31.useState)(null);
3342
+ const [valueError, setValueError] = (0, import_react31.useState)(null);
3343
+ const keyLabel = props.keyName || (0, import_i18n21.__)("Key", "elementor");
3344
+ const valueLabel = props.valueName || (0, import_i18n21.__)("Value", "elementor");
3345
+ const keyValue = value?.key?.value || "";
3346
+ const valueValue = value?.value?.value || "";
3347
+ const [keyRegex, valueRegex, errMsg] = (0, import_react31.useMemo)(
3348
+ () => [
3349
+ props.regexKey ? new RegExp(props.regexKey) : void 0,
3350
+ props.regexValue ? new RegExp(props.regexValue) : void 0,
3351
+ props.validationErrorMessage || (0, import_i18n21.__)("Invalid Format", "elementor")
3352
+ ],
3353
+ [props.regexKey, props.regexValue, props.validationErrorMessage]
3354
+ );
3355
+ const validate = (newValue, FieldType) => {
3356
+ if (FieldType === "key" && keyRegex) {
3357
+ const isValid = keyRegex.test(newValue);
3358
+ setKeyError(isValid ? null : errMsg);
3359
+ } else if (FieldType === "value" && valueRegex) {
3360
+ const isValid = valueRegex.test(newValue);
3361
+ setValueError(isValid ? null : errMsg);
3362
+ }
3363
+ };
3364
+ const handleChange = (event, fieldType) => {
3365
+ const newValue = event.target.value;
3366
+ validate(newValue, fieldType);
3367
+ setValue({
3368
+ ...value,
3369
+ [fieldType]: {
3370
+ value: newValue,
3371
+ $$type: "string"
3372
+ }
3373
+ });
3374
+ };
3375
+ const isKeyInvalid = keyError !== null;
3376
+ const isValueInvalid = valueError !== null;
3377
+ return /* @__PURE__ */ React52.createElement(ControlActions, null, /* @__PURE__ */ React52.createElement(import_ui45.Grid, { container: true, gap: 1.5, p: 1.5, sx: props.sx }, /* @__PURE__ */ React52.createElement(import_ui45.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React52.createElement(import_ui45.FormLabel, { size: "tiny" }, keyLabel), /* @__PURE__ */ React52.createElement(
3378
+ import_ui45.TextField,
3379
+ {
3380
+ sx: { pt: 1 },
3381
+ size: "tiny",
3382
+ fullWidth: true,
3383
+ value: keyValue,
3384
+ onChange: (e) => handleChange(e, "key"),
3385
+ error: isKeyInvalid
3386
+ }
3387
+ ), isKeyInvalid && /* @__PURE__ */ React52.createElement(import_ui45.FormHelperText, { error: true }, keyError)), /* @__PURE__ */ React52.createElement(import_ui45.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React52.createElement(import_ui45.FormLabel, { size: "tiny" }, valueLabel), /* @__PURE__ */ React52.createElement(
3388
+ import_ui45.TextField,
3389
+ {
3390
+ sx: { pt: 1 },
3391
+ size: "tiny",
3392
+ fullWidth: true,
3393
+ value: valueValue,
3394
+ onChange: (e) => handleChange(e, "value"),
3395
+ disabled: isKeyInvalid,
3396
+ error: isValueInvalid
3397
+ }
3398
+ ), isValueInvalid && /* @__PURE__ */ React52.createElement(import_ui45.FormHelperText, { error: true }, valueError))));
3399
+ });
3400
+
3401
+ // src/controls/position-control.tsx
3402
+ var React53 = __toESM(require("react"));
3403
+ var import_react32 = require("react");
3404
+ var import_editor_props29 = require("@elementor/editor-props");
3405
+ var import_editor_ui7 = require("@elementor/editor-ui");
3406
+ var import_editor_v1_adapters5 = require("@elementor/editor-v1-adapters");
3407
+ var import_icons18 = require("@elementor/icons");
3408
+ var import_ui46 = require("@elementor/ui");
3409
+ var import_i18n22 = require("@wordpress/i18n");
3410
+ var positionOptions = [
3411
+ { label: (0, import_i18n22.__)("Center center", "elementor"), value: "center center" },
3412
+ { label: (0, import_i18n22.__)("Center left", "elementor"), value: "center left" },
3413
+ { label: (0, import_i18n22.__)("Center right", "elementor"), value: "center right" },
3414
+ { label: (0, import_i18n22.__)("Top center", "elementor"), value: "top center" },
3415
+ { label: (0, import_i18n22.__)("Top left", "elementor"), value: "top left" },
3416
+ { label: (0, import_i18n22.__)("Top right", "elementor"), value: "top right" },
3417
+ { label: (0, import_i18n22.__)("Bottom center", "elementor"), value: "bottom center" },
3418
+ { label: (0, import_i18n22.__)("Bottom left", "elementor"), value: "bottom left" },
3419
+ { label: (0, import_i18n22.__)("Bottom right", "elementor"), value: "bottom right" }
3420
+ ];
3421
+ var PositionControl = () => {
3422
+ const positionContext = useBoundProp(import_editor_props29.positionPropTypeUtil);
3423
+ const stringPropContext = useBoundProp(import_editor_props29.stringPropTypeUtil);
3424
+ const isVersion331Active = (0, import_editor_v1_adapters5.isExperimentActive)("e_v_3_31");
3425
+ const isCustom = !!positionContext.value && isVersion331Active;
3426
+ const availablePositionOptions = (0, import_react32.useMemo)(() => {
3427
+ const options = [...positionOptions];
3428
+ if (isVersion331Active) {
3429
+ options.push({ label: (0, import_i18n22.__)("Custom", "elementor"), value: "custom" });
3430
+ }
3431
+ return options;
3432
+ }, [isVersion331Active]);
3433
+ const handlePositionChange = (event) => {
3434
+ const value = event.target.value || null;
3435
+ if (value === "custom" && isVersion331Active) {
3436
+ positionContext.setValue({ x: null, y: null });
3437
+ } else {
3438
+ stringPropContext.setValue(value);
3439
+ }
3440
+ };
3441
+ return /* @__PURE__ */ React53.createElement(import_ui46.Grid, { container: true, spacing: 1.5 }, /* @__PURE__ */ React53.createElement(import_ui46.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React53.createElement(import_ui46.Grid, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap" }, /* @__PURE__ */ React53.createElement(import_ui46.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React53.createElement(ControlFormLabel, null, (0, import_i18n22.__)("Object position", "elementor"))), /* @__PURE__ */ React53.createElement(import_ui46.Grid, { item: true, xs: 6, sx: { overflow: "hidden" } }, /* @__PURE__ */ React53.createElement(
3442
+ import_ui46.Select,
3443
+ {
3444
+ size: "tiny",
3445
+ disabled: stringPropContext.disabled,
3446
+ value: (positionContext.value ? "custom" : stringPropContext.value) ?? "",
3447
+ onChange: handlePositionChange,
3448
+ fullWidth: true
3449
+ },
3450
+ availablePositionOptions.map(({ label, value }) => /* @__PURE__ */ React53.createElement(import_editor_ui7.MenuListItem, { key: value, value: value ?? "" }, label))
3451
+ )))), isCustom && /* @__PURE__ */ React53.createElement(PropProvider, { ...positionContext }, /* @__PURE__ */ React53.createElement(import_ui46.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React53.createElement(import_ui46.Grid, { container: true, spacing: 1.5 }, /* @__PURE__ */ React53.createElement(import_ui46.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React53.createElement(PropKeyProvider, { bind: "x" }, /* @__PURE__ */ React53.createElement(SizeControl, { startIcon: /* @__PURE__ */ React53.createElement(import_icons18.LetterXIcon, { fontSize: "tiny" }) }))), /* @__PURE__ */ React53.createElement(import_ui46.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React53.createElement(PropKeyProvider, { bind: "y" }, /* @__PURE__ */ React53.createElement(SizeControl, { startIcon: /* @__PURE__ */ React53.createElement(import_icons18.LetterYIcon, { fontSize: "tiny" }) })))))));
3452
+ };
3372
3453
  // Annotate the CommonJS export names for ESM import in node:
3373
3454
  0 && (module.exports = {
3374
3455
  AspectRatioControl,
@@ -3386,11 +3467,14 @@ var SwitchControl2 = createControl(() => {
3386
3467
  FontFamilySelector,
3387
3468
  GapControl,
3388
3469
  ImageControl,
3470
+ KeyValueControl,
3389
3471
  LinkControl,
3390
3472
  LinkedDimensionsControl,
3391
3473
  NumberControl,
3474
+ PositionControl,
3392
3475
  PropKeyProvider,
3393
3476
  PropProvider,
3477
+ RepeatableControl,
3394
3478
  SelectControl,
3395
3479
  SizeControl,
3396
3480
  StrokeControl,