@elementor/editor-controls 4.2.0-beta2 → 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)) {
@@ -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
  }