@elementor/editor-controls 4.2.0-beta1 → 4.2.3

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
@@ -452,7 +452,7 @@ var ImageMediaControl = createControl(({ mediaTypes = ["image"] }) => {
452
452
  import * as React12 from "react";
453
453
  import { stringPropTypeUtil as stringPropTypeUtil2 } from "@elementor/editor-props";
454
454
  import { MenuListItem } from "@elementor/editor-ui";
455
- import { Select, Typography } from "@elementor/ui";
455
+ import { MenuSubheader, Select, Typography } from "@elementor/ui";
456
456
  var DEFAULT_MENU_PROPS = {
457
457
  MenuListProps: {
458
458
  sx: {
@@ -461,14 +461,15 @@ var DEFAULT_MENU_PROPS = {
461
461
  }
462
462
  };
463
463
  var SelectControl = createControl(
464
- ({ options, onChange, MenuProps = DEFAULT_MENU_PROPS, ariaLabel }) => {
464
+ ({ options = [], groups = [], onChange, MenuProps = DEFAULT_MENU_PROPS, ariaLabel }) => {
465
465
  const { value, setValue, disabled, placeholder } = useBoundProp(stringPropTypeUtil2);
466
466
  const handleChange = (event) => {
467
467
  const newValue = event.target.value || null;
468
468
  onChange?.(newValue, value);
469
469
  setValue(newValue);
470
470
  };
471
- const isDisabled = disabled || options.length === 0;
471
+ const flatOptions = flattenGroupedOptions(options, groups);
472
+ const isDisabled = disabled || flatOptions.length === 0;
472
473
  return /* @__PURE__ */ React12.createElement(ControlActions, null, /* @__PURE__ */ React12.createElement(
473
474
  Select,
474
475
  {
@@ -477,16 +478,41 @@ var SelectControl = createControl(
477
478
  size: "tiny",
478
479
  MenuProps,
479
480
  "aria-label": ariaLabel || placeholder,
480
- renderValue: (selectedValue) => getSelectRenderValue(options, placeholder, selectedValue),
481
+ renderValue: (selectedValue) => getSelectRenderValue(flatOptions, placeholder, selectedValue),
481
482
  value: value ?? "",
482
483
  onChange: handleChange,
483
484
  disabled: isDisabled,
484
485
  fullWidth: true
485
486
  },
486
- options.map(({ label, ...props }) => /* @__PURE__ */ React12.createElement(MenuListItem, { key: props.value, ...props, value: props.value ?? "" }, label))
487
+ groups.length ? groups.flatMap((group) => renderGroup(group)) : options.map((option) => renderOption(option))
487
488
  ));
488
489
  }
489
490
  );
491
+ var GROUPED_OPTION_INDENT = 3.5;
492
+ function renderGroup(group) {
493
+ return [
494
+ /* @__PURE__ */ React12.createElement(MenuSubheader, { key: `group-${group.label}`, sx: { fontWeight: 400, color: "text.tertiary" } }, group.label),
495
+ ...group.options.map((option) => renderOption(option, true))
496
+ ];
497
+ }
498
+ function renderOption({ label, ...props }, isGrouped = false) {
499
+ return /* @__PURE__ */ React12.createElement(
500
+ MenuListItem,
501
+ {
502
+ key: props.value,
503
+ ...props,
504
+ value: props.value ?? "",
505
+ sx: isGrouped ? { pl: GROUPED_OPTION_INDENT } : void 0
506
+ },
507
+ label
508
+ );
509
+ }
510
+ function flattenGroupedOptions(options, groups) {
511
+ if (!groups.length) {
512
+ return options;
513
+ }
514
+ return groups.flatMap((group) => group.options);
515
+ }
490
516
  function getSelectRenderValue(options, placeholder, selectedValue) {
491
517
  const optionWithValue = (v) => options.find(({ value }) => value === v);
492
518
  if (!isUnsetSelectValue(selectedValue)) {
@@ -779,11 +805,11 @@ function useTypingBuffer(options = {}) {
779
805
  var lengthUnits = ["px", "%", "em", "rem", "vw", "vh", "ch"];
780
806
  var angleUnits = ["deg", "rad", "grad", "turn"];
781
807
  var timeUnits = ["s", "ms"];
782
- var defaultExtendedOptions = ["auto", "custom"];
783
808
  var DEFAULT_UNIT = "px";
784
809
  var DEFAULT_SIZE = NaN;
810
+ var extendedOptions = ["auto", "custom"];
785
811
  function isUnitExtendedOption(unit) {
786
- return defaultExtendedOptions.includes(unit);
812
+ return extendedOptions.includes(unit);
787
813
  }
788
814
 
789
815
  // src/components/size-control/text-field-inner-selection.tsx
@@ -1121,13 +1147,13 @@ var TextFieldPopover = (props) => {
1121
1147
  import { useMemo } from "react";
1122
1148
  function useSizeExtendedOptions(options, disableCustom) {
1123
1149
  return useMemo(() => {
1124
- const extendedOptions = [...options];
1125
- if (!disableCustom && !extendedOptions.includes("custom")) {
1126
- extendedOptions.push("custom");
1150
+ const extendedOptions2 = [...options];
1151
+ if (!disableCustom && !extendedOptions2.includes("custom")) {
1152
+ extendedOptions2.push("custom");
1127
1153
  } else if (options.includes("custom")) {
1128
- extendedOptions.splice(extendedOptions.indexOf("custom"), 1);
1154
+ extendedOptions2.splice(extendedOptions2.indexOf("custom"), 1);
1129
1155
  }
1130
- return extendedOptions;
1156
+ return extendedOptions2;
1131
1157
  }, [options, disableCustom]);
1132
1158
  }
1133
1159
 
@@ -1164,6 +1190,11 @@ var useSyncExternalState = ({
1164
1190
  return [internal, setInternalValue];
1165
1191
  };
1166
1192
 
1193
+ // src/controls/size-control/utils/settings/get-prop-type-settings.ts
1194
+ var getPropTypeSettings = (propType) => {
1195
+ return propType.settings;
1196
+ };
1197
+
1167
1198
  // src/controls/size-control.tsx
1168
1199
  var defaultSelectedUnit = {
1169
1200
  length: "px",
@@ -1184,7 +1215,7 @@ var SizeControl = createControl(
1184
1215
  placeholder,
1185
1216
  startIcon,
1186
1217
  anchorRef,
1187
- extendedOptions,
1218
+ extendedOptions: extendedOptions2,
1188
1219
  disableCustom,
1189
1220
  min = 0,
1190
1221
  enablePropTypeUnits = false,
@@ -1201,7 +1232,7 @@ var SizeControl = createControl(
1201
1232
  } = useBoundProp(sizePropTypeUtil2);
1202
1233
  const actualDefaultUnit = defaultUnit ?? externalPlaceholder?.unit ?? defaultSelectedUnit[variant];
1203
1234
  const activeBreakpoint = useActiveBreakpoint();
1204
- const actualExtendedOptions = useSizeExtendedOptions(extendedOptions || [], disableCustom ?? false);
1235
+ const actualExtendedOptions = useSizeExtendedOptions(extendedOptions2 || [], disableCustom ?? false);
1205
1236
  const actualUnits = resolveUnits(propType, enablePropTypeUnits, variant, units2, actualExtendedOptions);
1206
1237
  const popupState = usePopupState2({ variant: "popover" });
1207
1238
  const memorizedExternalState = useMemo2(
@@ -1290,7 +1321,7 @@ function resolveUnits(propType, enablePropTypeUnits, variant, externalUnits, act
1290
1321
  if (!enablePropTypeUnits) {
1291
1322
  return [...externalUnits ?? fallback, ...actualExtendedOptions || []];
1292
1323
  }
1293
- return propType.settings?.available_units ?? fallback;
1324
+ return getPropTypeSettings(propType)?.available_units ?? fallback;
1294
1325
  }
1295
1326
  function formatSize(size, unit) {
1296
1327
  if (isUnitExtendedOption(unit)) {
@@ -3626,11 +3657,6 @@ var resolvePlaceholder = (placeholder) => {
3626
3657
  return typeof size === "number" ? size.toString() : size;
3627
3658
  };
3628
3659
 
3629
- // src/controls/size-control/utils/settings/get-prop-type-settings.ts
3630
- var getPropTypeSettings = (propType) => {
3631
- return propType.settings;
3632
- };
3633
-
3634
3660
  // src/controls/size-control/utils/settings/get-default-unit.ts
3635
3661
  var getDefaultUnit = (propType) => {
3636
3662
  return getPropTypeSettings(propType)?.default_unit;
@@ -5105,7 +5131,7 @@ var GapControl = ({ label }) => {
5105
5131
  const disabled = sizeDisabled || directionDisabled;
5106
5132
  const propProviderProps = {
5107
5133
  propType,
5108
- value: directionValue ?? (!isLinked ? { row: masterPlaceholder, column: masterPlaceholder } : null),
5134
+ value: directionValue ?? (!isLinked ? { row: directionPlaceholder?.row, column: directionPlaceholder?.column } : null),
5109
5135
  setValue: (directions) => {
5110
5136
  const entries = Object.entries(directions);
5111
5137
  const filtered = entries.filter(([, value]) => Boolean(value));
@@ -8276,7 +8302,7 @@ function useFormFieldSuggestions(options) {
8276
8302
 
8277
8303
  // src/controls/email-form-action-control/email-chips-field.tsx
8278
8304
  import * as React116 from "react";
8279
- import { useState as useState19 } from "react";
8305
+ import { useMemo as useMemo18, useState as useState19 } from "react";
8280
8306
  import { stringArrayPropTypeUtil as stringArrayPropTypeUtil3, stringPropTypeUtil as stringPropTypeUtil22 } from "@elementor/editor-props";
8281
8307
  import { Autocomplete as Autocomplete4, Grid as Grid32, TextField as TextField11 } from "@elementor/ui";
8282
8308
 
@@ -8288,6 +8314,10 @@ var CHIP_TRIGGER_KEYS = /* @__PURE__ */ new Set([" ", ","]);
8288
8314
  function isValidEmail(email) {
8289
8315
  return z.string().email().safeParse(email).success;
8290
8316
  }
8317
+ var FORM_FIELD_SHORTCODE_PATTERN = /^\[[^[\]]+]$/;
8318
+ function isFormFieldShortcode(value) {
8319
+ return FORM_FIELD_SHORTCODE_PATTERN.test(value);
8320
+ }
8291
8321
  var shouldShowMentionsInfo = () => {
8292
8322
  if (!hasProInstalled3()) {
8293
8323
  return true;
@@ -8300,14 +8330,26 @@ var shouldShowMentionsInfo = () => {
8300
8330
  };
8301
8331
 
8302
8332
  // src/controls/email-form-action-control/email-chips-field.tsx
8303
- var EmailChipsField = ({ fieldLabel, placeholder }) => {
8333
+ var isValidRecipient = (address) => isValidEmail(address) || isFormFieldShortcode(address);
8334
+ function resolveMention(raw, suggestions) {
8335
+ if (!raw.startsWith("@")) {
8336
+ return raw;
8337
+ }
8338
+ const match = suggestions.find((suggestion) => createMentionPattern(suggestion.value, "start").test(raw));
8339
+ return match ? `[${match.value}]` : raw;
8340
+ }
8341
+ var EmailChipsControl = createControl(({ placeholder, suggestions = [] }) => {
8304
8342
  const { value, setValue, disabled } = useBoundProp(stringArrayPropTypeUtil3);
8305
8343
  const [inputValue, setInputValue] = useState19("");
8306
8344
  const items2 = value || [];
8307
8345
  const selectedValues = items2.map((item) => stringPropTypeUtil22.extract(item)).filter((val) => val !== null);
8346
+ const suggestionOptions = useMemo18(
8347
+ () => suggestions.map((suggestion) => `[${suggestion.value}]`),
8348
+ [suggestions]
8349
+ );
8308
8350
  const tryAddChip = (raw) => {
8309
- const address = raw.trim();
8310
- if (!address || selectedValues.includes(address) || !isValidEmail(address)) {
8351
+ const address = resolveMention(raw.trim(), suggestions);
8352
+ if (!address || selectedValues.includes(address) || !isValidRecipient(address)) {
8311
8353
  return;
8312
8354
  }
8313
8355
  setValue([...items2, stringPropTypeUtil22.create(address)]);
@@ -8316,8 +8358,8 @@ var EmailChipsField = ({ fieldLabel, placeholder }) => {
8316
8358
  const handleChange = (_, newValue) => {
8317
8359
  const updated = [];
8318
8360
  for (const entry of newValue) {
8319
- const address = entry.trim();
8320
- if (!address || !isValidEmail(address)) {
8361
+ const address = resolveMention(entry.trim(), suggestions);
8362
+ if (!address || !isValidRecipient(address)) {
8321
8363
  continue;
8322
8364
  }
8323
8365
  updated.push(stringPropTypeUtil22.create(address));
@@ -8336,7 +8378,7 @@ var EmailChipsField = ({ fieldLabel, placeholder }) => {
8336
8378
  tryAddChip(inputValue);
8337
8379
  }
8338
8380
  };
8339
- return /* @__PURE__ */ React116.createElement(Grid32, { container: true, direction: "column", gap: 0.5 }, /* @__PURE__ */ React116.createElement(Grid32, { item: true }, /* @__PURE__ */ React116.createElement(ControlFormLabel, null, fieldLabel)), /* @__PURE__ */ React116.createElement(Grid32, { item: true }, /* @__PURE__ */ React116.createElement(
8381
+ return /* @__PURE__ */ React116.createElement(ControlActions, null, /* @__PURE__ */ React116.createElement(
8340
8382
  Autocomplete4,
8341
8383
  {
8342
8384
  fullWidth: true,
@@ -8352,15 +8394,21 @@ var EmailChipsField = ({ fieldLabel, placeholder }) => {
8352
8394
  },
8353
8395
  value: selectedValues,
8354
8396
  onChange: handleChange,
8355
- options: [],
8397
+ options: suggestionOptions,
8398
+ filterOptions: (options, state) => {
8399
+ const query = state.inputValue.trim().replace(/^@/, "").toLowerCase();
8400
+ return query ? options.filter((option) => option.toLowerCase().includes(query)) : options;
8401
+ },
8402
+ filterSelectedOptions: true,
8356
8403
  onBlur: handleBlur,
8357
8404
  getOptionLabel: (option) => option,
8358
8405
  isOptionEqualToValue: (option, val) => option === val,
8359
8406
  renderInput: (params) => /* @__PURE__ */ React116.createElement(TextField11, { ...params, placeholder, onKeyDown: handleKeyDown }),
8360
8407
  renderTags: (tagValues, getTagProps) => /* @__PURE__ */ React116.createElement(ChipsList, { getLabel: (option) => option, getTagProps, values: tagValues })
8361
8408
  }
8362
- )));
8363
- };
8409
+ ));
8410
+ });
8411
+ var EmailChipsField = ({ fieldLabel, placeholder, suggestions }) => /* @__PURE__ */ React116.createElement(Grid32, { container: true, direction: "column", gap: 0.5 }, /* @__PURE__ */ React116.createElement(Grid32, { item: true }, /* @__PURE__ */ React116.createElement(ControlFormLabel, null, fieldLabel)), /* @__PURE__ */ React116.createElement(Grid32, { item: true }, /* @__PURE__ */ React116.createElement(EmailChipsControl, { placeholder, suggestions })));
8364
8412
 
8365
8413
  // src/controls/email-form-action-control/email-field.tsx
8366
8414
  import * as React117 from "react";
@@ -8368,7 +8416,17 @@ import { Grid as Grid33 } from "@elementor/ui";
8368
8416
  var EmailField = ({ bind, label, placeholder }) => /* @__PURE__ */ React117.createElement(PropKeyProvider, { bind }, /* @__PURE__ */ React117.createElement(Grid33, { container: true, direction: "column", gap: 0.5 }, /* @__PURE__ */ React117.createElement(Grid33, { item: true }, /* @__PURE__ */ React117.createElement(ControlFormLabel, null, label)), /* @__PURE__ */ React117.createElement(Grid33, { item: true }, /* @__PURE__ */ React117.createElement(TextControl, { placeholder }))));
8369
8417
 
8370
8418
  // src/controls/email-form-action-control/fields.tsx
8371
- var SendToField = ({ placeholder }) => /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: __57("Send to", "elementor"), placeholder });
8419
+ var SendToField = ({ placeholder }) => {
8420
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8421
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "to" }, /* @__PURE__ */ React118.createElement(Stack19, { gap: 0.5 }, /* @__PURE__ */ React118.createElement(
8422
+ EmailChipsField,
8423
+ {
8424
+ fieldLabel: __57("Send to", "elementor"),
8425
+ placeholder,
8426
+ suggestions
8427
+ }
8428
+ ), shouldShowMentionsInfo() && /* @__PURE__ */ React118.createElement(InfoAlert2, null, __57("Type @ or an email field name to insert its submitted value.", "elementor"))));
8429
+ };
8372
8430
  var SubjectField = () => /* @__PURE__ */ React118.createElement(
8373
8431
  EmailField,
8374
8432
  {
@@ -8412,8 +8470,14 @@ var ReplyToField = () => {
8412
8470
  }
8413
8471
  ))));
8414
8472
  };
8415
- var CcField = () => /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "cc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: __57("Cc", "elementor") }));
8416
- var BccField = () => /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "bcc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: __57("Bcc", "elementor") }));
8473
+ var CcField = () => {
8474
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8475
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "cc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: __57("Cc", "elementor"), suggestions }));
8476
+ };
8477
+ var BccField = () => {
8478
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8479
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "bcc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: __57("Bcc", "elementor"), suggestions }));
8480
+ };
8417
8481
  var MetaDataField = () => /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "meta-data" }, /* @__PURE__ */ React118.createElement(Stack19, { gap: 0.5 }, /* @__PURE__ */ React118.createElement(ControlFormLabel, null, __57("Metadata", "elementor")), /* @__PURE__ */ React118.createElement(
8418
8482
  ChipsControl,
8419
8483
  {
@@ -8440,7 +8504,7 @@ var SendAsField = () => /* @__PURE__ */ React118.createElement(PropKeyProvider,
8440
8504
  var EmailFormActionControl = createControl(
8441
8505
  ({ toPlaceholder, label }) => {
8442
8506
  const { value, setValue, ...propContext } = useBoundProp(emailsPropTypeUtil);
8443
- return /* @__PURE__ */ React119.createElement(PropProvider, { ...propContext, value, setValue }, /* @__PURE__ */ React119.createElement(Stack20, { gap: 2 }, /* @__PURE__ */ React119.createElement(ControlLabel, null, label ? label + " " + __58("settings", "elementor") : __58("Email settings", "elementor")), /* @__PURE__ */ React119.createElement(PropKeyProvider, { bind: "to" }, /* @__PURE__ */ React119.createElement(SendToField, { placeholder: toPlaceholder })), /* @__PURE__ */ React119.createElement(SubjectField, null), /* @__PURE__ */ React119.createElement(MessageField, null), /* @__PURE__ */ React119.createElement(FromEmailField, null), /* @__PURE__ */ React119.createElement(AdvancedSettings, null)));
8507
+ return /* @__PURE__ */ React119.createElement(PropProvider, { ...propContext, value, setValue }, /* @__PURE__ */ React119.createElement(Stack20, { gap: 2 }, /* @__PURE__ */ React119.createElement(ControlLabel, null, label ? label + " " + __58("settings", "elementor") : __58("Email settings", "elementor")), /* @__PURE__ */ React119.createElement(SendToField, { placeholder: toPlaceholder }), /* @__PURE__ */ React119.createElement(SubjectField, null), /* @__PURE__ */ React119.createElement(MessageField, null), /* @__PURE__ */ React119.createElement(FromEmailField, null), /* @__PURE__ */ React119.createElement(AdvancedSettings, null)));
8444
8508
  }
8445
8509
  );
8446
8510
  var AdvancedSettings = () => /* @__PURE__ */ React119.createElement(CollapsibleContent, { defaultOpen: false }, /* @__PURE__ */ React119.createElement(Box26, { sx: { pt: 2 } }, /* @__PURE__ */ React119.createElement(Stack20, { gap: 2 }, /* @__PURE__ */ React119.createElement(FromNameField, null), /* @__PURE__ */ React119.createElement(ReplyToField, null), /* @__PURE__ */ React119.createElement(CcField, null), /* @__PURE__ */ React119.createElement(BccField, null), /* @__PURE__ */ React119.createElement(Divider5, null), /* @__PURE__ */ React119.createElement(MetaDataField, null), /* @__PURE__ */ React119.createElement(SendAsField, null))));
@@ -8862,7 +8926,7 @@ var usePopover = (openOnMount, onOpen, onPopoverClose) => {
8862
8926
 
8863
8927
  // src/components/inline-editor-toolbar.tsx
8864
8928
  import * as React128 from "react";
8865
- import { useEffect as useEffect21, useMemo as useMemo18, useRef as useRef32, useState as useState22 } from "react";
8929
+ import { useEffect as useEffect21, useMemo as useMemo19, useRef as useRef32, useState as useState22 } from "react";
8866
8930
  import { getContainer as getContainer3, getElementSetting } from "@elementor/editor-elements";
8867
8931
  import {
8868
8932
  BoldIcon,
@@ -8961,7 +9025,7 @@ var InlineEditorToolbar = ({ editor, elementId, sx = {} }) => {
8961
9025
  editor,
8962
9026
  selector: (ctx) => possibleFormats.filter((format) => ctx.editor.isActive(format))
8963
9027
  });
8964
- const formatButtonsList = useMemo18(() => {
9028
+ const formatButtonsList = useMemo19(() => {
8965
9029
  const buttons = Object.values(formatButtons);
8966
9030
  if (isElementClickable) {
8967
9031
  return buttons.filter((button) => button.action !== "link");
@@ -9308,7 +9372,7 @@ var hasValue = (value) => {
9308
9372
  };
9309
9373
 
9310
9374
  // src/hooks/use-font-families.ts
9311
- import { useMemo as useMemo19 } from "react";
9375
+ import { useMemo as useMemo20 } from "react";
9312
9376
  import { getElementorConfig } from "@elementor/editor-v1-adapters";
9313
9377
  var getFontControlConfig = () => {
9314
9378
  const { controls } = getElementorConfig();
@@ -9316,7 +9380,7 @@ var getFontControlConfig = () => {
9316
9380
  };
9317
9381
  var useFontFamilies = () => {
9318
9382
  const { groups, options } = getFontControlConfig();
9319
- return useMemo19(() => {
9383
+ return useMemo20(() => {
9320
9384
  if (!groups || !options) {
9321
9385
  return [];
9322
9386
  }