@elementor/editor-controls 4.3.0-1008 → 4.3.0-1010

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)) {
@@ -8275,7 +8301,7 @@ function useFormFieldSuggestions(options) {
8275
8301
 
8276
8302
  // src/controls/email-form-action-control/email-chips-field.tsx
8277
8303
  import * as React116 from "react";
8278
- import { useState as useState19 } from "react";
8304
+ import { useMemo as useMemo18, useState as useState19 } from "react";
8279
8305
  import { stringArrayPropTypeUtil as stringArrayPropTypeUtil3, stringPropTypeUtil as stringPropTypeUtil22 } from "@elementor/editor-props";
8280
8306
  import { Autocomplete as Autocomplete4, Grid as Grid32, TextField as TextField11 } from "@elementor/ui";
8281
8307
 
@@ -8287,6 +8313,10 @@ var CHIP_TRIGGER_KEYS = /* @__PURE__ */ new Set([" ", ","]);
8287
8313
  function isValidEmail(email) {
8288
8314
  return z.string().email().safeParse(email).success;
8289
8315
  }
8316
+ var FORM_FIELD_SHORTCODE_PATTERN = /^\[[^[\]]+]$/;
8317
+ function isFormFieldShortcode(value) {
8318
+ return FORM_FIELD_SHORTCODE_PATTERN.test(value);
8319
+ }
8290
8320
  var shouldShowMentionsInfo = () => {
8291
8321
  if (!hasProInstalled3()) {
8292
8322
  return true;
@@ -8299,14 +8329,26 @@ var shouldShowMentionsInfo = () => {
8299
8329
  };
8300
8330
 
8301
8331
  // src/controls/email-form-action-control/email-chips-field.tsx
8302
- var EmailChipsControl = createControl(({ placeholder }) => {
8332
+ var isValidRecipient = (address) => isValidEmail(address) || isFormFieldShortcode(address);
8333
+ function resolveMention(raw, suggestions) {
8334
+ if (!raw.startsWith("@")) {
8335
+ return raw;
8336
+ }
8337
+ const match = suggestions.find((suggestion) => createMentionPattern(suggestion.value, "start").test(raw));
8338
+ return match ? `[${match.value}]` : raw;
8339
+ }
8340
+ var EmailChipsControl = createControl(({ placeholder, suggestions = [] }) => {
8303
8341
  const { value, setValue, disabled } = useBoundProp(stringArrayPropTypeUtil3);
8304
8342
  const [inputValue, setInputValue] = useState19("");
8305
8343
  const items2 = value || [];
8306
8344
  const selectedValues = items2.map((item) => stringPropTypeUtil22.extract(item)).filter((val) => val !== null);
8345
+ const suggestionOptions = useMemo18(
8346
+ () => suggestions.map((suggestion) => `[${suggestion.value}]`),
8347
+ [suggestions]
8348
+ );
8307
8349
  const tryAddChip = (raw) => {
8308
- const address = raw.trim();
8309
- if (!address || selectedValues.includes(address) || !isValidEmail(address)) {
8350
+ const address = resolveMention(raw.trim(), suggestions);
8351
+ if (!address || selectedValues.includes(address) || !isValidRecipient(address)) {
8310
8352
  return;
8311
8353
  }
8312
8354
  setValue([...items2, stringPropTypeUtil22.create(address)]);
@@ -8315,8 +8357,8 @@ var EmailChipsControl = createControl(({ placeholder }) => {
8315
8357
  const handleChange = (_, newValue) => {
8316
8358
  const updated = [];
8317
8359
  for (const entry of newValue) {
8318
- const address = entry.trim();
8319
- if (!address || !isValidEmail(address)) {
8360
+ const address = resolveMention(entry.trim(), suggestions);
8361
+ if (!address || !isValidRecipient(address)) {
8320
8362
  continue;
8321
8363
  }
8322
8364
  updated.push(stringPropTypeUtil22.create(address));
@@ -8351,7 +8393,12 @@ var EmailChipsControl = createControl(({ placeholder }) => {
8351
8393
  },
8352
8394
  value: selectedValues,
8353
8395
  onChange: handleChange,
8354
- options: [],
8396
+ options: suggestionOptions,
8397
+ filterOptions: (options, state) => {
8398
+ const query = state.inputValue.trim().replace(/^@/, "").toLowerCase();
8399
+ return query ? options.filter((option) => option.toLowerCase().includes(query)) : options;
8400
+ },
8401
+ filterSelectedOptions: true,
8355
8402
  onBlur: handleBlur,
8356
8403
  getOptionLabel: (option) => option,
8357
8404
  isOptionEqualToValue: (option, val) => option === val,
@@ -8360,7 +8407,7 @@ var EmailChipsControl = createControl(({ placeholder }) => {
8360
8407
  }
8361
8408
  ));
8362
8409
  });
8363
- var EmailChipsField = ({ fieldLabel, placeholder }) => /* @__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 })));
8410
+ 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
8411
 
8365
8412
  // src/controls/email-form-action-control/email-field.tsx
8366
8413
  import * as React117 from "react";
@@ -8368,7 +8415,17 @@ import { Grid as Grid33 } from "@elementor/ui";
8368
8415
  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
8416
 
8370
8417
  // src/controls/email-form-action-control/fields.tsx
8371
- var SendToField = ({ placeholder }) => /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "to" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: __57("Send to", "elementor"), placeholder }));
8418
+ var SendToField = ({ placeholder }) => {
8419
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8420
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "to" }, /* @__PURE__ */ React118.createElement(Stack19, { gap: 0.5 }, /* @__PURE__ */ React118.createElement(
8421
+ EmailChipsField,
8422
+ {
8423
+ fieldLabel: __57("Send to", "elementor"),
8424
+ placeholder,
8425
+ suggestions
8426
+ }
8427
+ ), shouldShowMentionsInfo() && /* @__PURE__ */ React118.createElement(InfoAlert2, null, __57("Type @ or an email field name to insert its submitted value.", "elementor"))));
8428
+ };
8372
8429
  var SubjectField = () => /* @__PURE__ */ React118.createElement(
8373
8430
  EmailField,
8374
8431
  {
@@ -8412,8 +8469,14 @@ var ReplyToField = () => {
8412
8469
  }
8413
8470
  ))));
8414
8471
  };
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") }));
8472
+ var CcField = () => {
8473
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8474
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "cc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: __57("Cc", "elementor"), suggestions }));
8475
+ };
8476
+ var BccField = () => {
8477
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8478
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "bcc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: __57("Bcc", "elementor"), suggestions }));
8479
+ };
8417
8480
  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
8481
  ChipsControl,
8419
8482
  {
@@ -8863,7 +8926,7 @@ var usePopover = (openOnMount, onOpen, onPopoverClose) => {
8863
8926
 
8864
8927
  // src/components/inline-editor-toolbar.tsx
8865
8928
  import * as React128 from "react";
8866
- 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";
8867
8930
  import { getContainer as getContainer3, getElementSetting } from "@elementor/editor-elements";
8868
8931
  import {
8869
8932
  BoldIcon,
@@ -8962,7 +9025,7 @@ var InlineEditorToolbar = ({ editor, elementId, sx = {} }) => {
8962
9025
  editor,
8963
9026
  selector: (ctx) => possibleFormats.filter((format) => ctx.editor.isActive(format))
8964
9027
  });
8965
- const formatButtonsList = useMemo18(() => {
9028
+ const formatButtonsList = useMemo19(() => {
8966
9029
  const buttons = Object.values(formatButtons);
8967
9030
  if (isElementClickable) {
8968
9031
  return buttons.filter((button) => button.action !== "link");
@@ -9309,7 +9372,7 @@ var hasValue = (value) => {
9309
9372
  };
9310
9373
 
9311
9374
  // src/hooks/use-font-families.ts
9312
- import { useMemo as useMemo19 } from "react";
9375
+ import { useMemo as useMemo20 } from "react";
9313
9376
  import { getElementorConfig } from "@elementor/editor-v1-adapters";
9314
9377
  var getFontControlConfig = () => {
9315
9378
  const { controls } = getElementorConfig();
@@ -9317,7 +9380,7 @@ var getFontControlConfig = () => {
9317
9380
  };
9318
9381
  var useFontFamilies = () => {
9319
9382
  const { groups, options } = getFontControlConfig();
9320
- return useMemo19(() => {
9383
+ return useMemo20(() => {
9321
9384
  if (!groups || !options) {
9322
9385
  return [];
9323
9386
  }