@elementor/editor-controls 4.2.0-beta2 → 4.2.4

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.d.mts CHANGED
@@ -105,13 +105,18 @@ type SelectOption$1 = {
105
105
  value: StringPropValue['value'];
106
106
  disabled?: boolean;
107
107
  };
108
- type SelectControlProps = {
108
+ type SelectOptionGroup = {
109
+ label: string;
109
110
  options: SelectOption$1[];
111
+ };
112
+ type SelectControlProps = {
113
+ options?: SelectOption$1[];
114
+ groups?: SelectOptionGroup[];
110
115
  onChange?: (newValue: string | null, previousValue: string | null | undefined) => void;
111
116
  MenuProps?: SelectProps['MenuProps'];
112
117
  ariaLabel?: string;
113
118
  };
114
- declare const SelectControl: ControlComponent$1<({ options, onChange, MenuProps, ariaLabel }: SelectControlProps) => React$1.JSX.Element>;
119
+ declare const SelectControl: ControlComponent$1<({ options, groups, onChange, MenuProps, ariaLabel }: SelectControlProps) => React$1.JSX.Element>;
115
120
 
116
121
  declare const collectionMethods: {
117
122
  readonly 'off-canvas': () => SelectOption$1[];
package/dist/index.d.ts CHANGED
@@ -105,13 +105,18 @@ type SelectOption$1 = {
105
105
  value: StringPropValue['value'];
106
106
  disabled?: boolean;
107
107
  };
108
- type SelectControlProps = {
108
+ type SelectOptionGroup = {
109
+ label: string;
109
110
  options: SelectOption$1[];
111
+ };
112
+ type SelectControlProps = {
113
+ options?: SelectOption$1[];
114
+ groups?: SelectOptionGroup[];
110
115
  onChange?: (newValue: string | null, previousValue: string | null | undefined) => void;
111
116
  MenuProps?: SelectProps['MenuProps'];
112
117
  ariaLabel?: string;
113
118
  };
114
- declare const SelectControl: ControlComponent$1<({ options, onChange, MenuProps, ariaLabel }: SelectControlProps) => React$1.JSX.Element>;
119
+ declare const SelectControl: ControlComponent$1<({ options, groups, onChange, MenuProps, ariaLabel }: SelectControlProps) => React$1.JSX.Element>;
115
120
 
116
121
  declare const collectionMethods: {
117
122
  readonly 'off-canvas': () => SelectOption$1[];
package/dist/index.js CHANGED
@@ -584,14 +584,15 @@ var DEFAULT_MENU_PROPS = {
584
584
  }
585
585
  };
586
586
  var SelectControl = createControl(
587
- ({ options, onChange, MenuProps = DEFAULT_MENU_PROPS, ariaLabel }) => {
587
+ ({ options = [], groups = [], onChange, MenuProps = DEFAULT_MENU_PROPS, ariaLabel }) => {
588
588
  const { value, setValue, disabled, placeholder } = useBoundProp(import_editor_props2.stringPropTypeUtil);
589
589
  const handleChange = (event) => {
590
590
  const newValue = event.target.value || null;
591
591
  onChange?.(newValue, value);
592
592
  setValue(newValue);
593
593
  };
594
- const isDisabled = disabled || options.length === 0;
594
+ const flatOptions = flattenGroupedOptions(options, groups);
595
+ const isDisabled = disabled || flatOptions.length === 0;
595
596
  return /* @__PURE__ */ React12.createElement(ControlActions, null, /* @__PURE__ */ React12.createElement(
596
597
  import_ui5.Select,
597
598
  {
@@ -600,16 +601,41 @@ var SelectControl = createControl(
600
601
  size: "tiny",
601
602
  MenuProps,
602
603
  "aria-label": ariaLabel || placeholder,
603
- renderValue: (selectedValue) => getSelectRenderValue(options, placeholder, selectedValue),
604
+ renderValue: (selectedValue) => getSelectRenderValue(flatOptions, placeholder, selectedValue),
604
605
  value: value ?? "",
605
606
  onChange: handleChange,
606
607
  disabled: isDisabled,
607
608
  fullWidth: true
608
609
  },
609
- options.map(({ label, ...props }) => /* @__PURE__ */ React12.createElement(import_editor_ui2.MenuListItem, { key: props.value, ...props, value: props.value ?? "" }, label))
610
+ groups.length ? groups.flatMap((group) => renderGroup(group)) : options.map((option) => renderOption(option))
610
611
  ));
611
612
  }
612
613
  );
614
+ var GROUPED_OPTION_INDENT = 3.5;
615
+ function renderGroup(group) {
616
+ return [
617
+ /* @__PURE__ */ React12.createElement(import_ui5.MenuSubheader, { key: `group-${group.label}`, sx: { fontWeight: 400, color: "text.tertiary" } }, group.label),
618
+ ...group.options.map((option) => renderOption(option, true))
619
+ ];
620
+ }
621
+ function renderOption({ label, ...props }, isGrouped = false) {
622
+ return /* @__PURE__ */ React12.createElement(
623
+ import_editor_ui2.MenuListItem,
624
+ {
625
+ key: props.value,
626
+ ...props,
627
+ value: props.value ?? "",
628
+ sx: isGrouped ? { pl: GROUPED_OPTION_INDENT } : void 0
629
+ },
630
+ label
631
+ );
632
+ }
633
+ function flattenGroupedOptions(options, groups) {
634
+ if (!groups.length) {
635
+ return options;
636
+ }
637
+ return groups.flatMap((group) => group.options);
638
+ }
613
639
  function getSelectRenderValue(options, placeholder, selectedValue) {
614
640
  const optionWithValue = (v) => options.find(({ value }) => value === v);
615
641
  if (!isUnsetSelectValue(selectedValue)) {
@@ -8300,6 +8326,10 @@ var CHIP_TRIGGER_KEYS = /* @__PURE__ */ new Set([" ", ","]);
8300
8326
  function isValidEmail(email) {
8301
8327
  return import_schema.z.string().email().safeParse(email).success;
8302
8328
  }
8329
+ var FORM_FIELD_SHORTCODE_PATTERN = /^\[[^[\]]+]$/;
8330
+ function isFormFieldShortcode(value) {
8331
+ return FORM_FIELD_SHORTCODE_PATTERN.test(value);
8332
+ }
8303
8333
  var shouldShowMentionsInfo = () => {
8304
8334
  if (!(0, import_utils9.hasProInstalled)()) {
8305
8335
  return true;
@@ -8312,14 +8342,26 @@ var shouldShowMentionsInfo = () => {
8312
8342
  };
8313
8343
 
8314
8344
  // src/controls/email-form-action-control/email-chips-field.tsx
8315
- var EmailChipsField = ({ fieldLabel, placeholder }) => {
8345
+ var isValidRecipient = (address) => isValidEmail(address) || isFormFieldShortcode(address);
8346
+ function resolveMention(raw, suggestions) {
8347
+ if (!raw.startsWith("@")) {
8348
+ return raw;
8349
+ }
8350
+ const match = suggestions.find((suggestion) => createMentionPattern(suggestion.value, "start").test(raw));
8351
+ return match ? `[${match.value}]` : raw;
8352
+ }
8353
+ var EmailChipsControl = createControl(({ placeholder, suggestions = [] }) => {
8316
8354
  const { value, setValue, disabled } = useBoundProp(import_editor_props65.stringArrayPropTypeUtil);
8317
8355
  const [inputValue, setInputValue] = (0, import_react69.useState)("");
8318
8356
  const items2 = value || [];
8319
8357
  const selectedValues = items2.map((item) => import_editor_props65.stringPropTypeUtil.extract(item)).filter((val) => val !== null);
8358
+ const suggestionOptions = (0, import_react69.useMemo)(
8359
+ () => suggestions.map((suggestion) => `[${suggestion.value}]`),
8360
+ [suggestions]
8361
+ );
8320
8362
  const tryAddChip = (raw) => {
8321
- const address = raw.trim();
8322
- if (!address || selectedValues.includes(address) || !isValidEmail(address)) {
8363
+ const address = resolveMention(raw.trim(), suggestions);
8364
+ if (!address || selectedValues.includes(address) || !isValidRecipient(address)) {
8323
8365
  return;
8324
8366
  }
8325
8367
  setValue([...items2, import_editor_props65.stringPropTypeUtil.create(address)]);
@@ -8328,8 +8370,8 @@ var EmailChipsField = ({ fieldLabel, placeholder }) => {
8328
8370
  const handleChange = (_, newValue) => {
8329
8371
  const updated = [];
8330
8372
  for (const entry of newValue) {
8331
- const address = entry.trim();
8332
- if (!address || !isValidEmail(address)) {
8373
+ const address = resolveMention(entry.trim(), suggestions);
8374
+ if (!address || !isValidRecipient(address)) {
8333
8375
  continue;
8334
8376
  }
8335
8377
  updated.push(import_editor_props65.stringPropTypeUtil.create(address));
@@ -8348,7 +8390,7 @@ var EmailChipsField = ({ fieldLabel, placeholder }) => {
8348
8390
  tryAddChip(inputValue);
8349
8391
  }
8350
8392
  };
8351
- return /* @__PURE__ */ React116.createElement(import_ui100.Grid, { container: true, direction: "column", gap: 0.5 }, /* @__PURE__ */ React116.createElement(import_ui100.Grid, { item: true }, /* @__PURE__ */ React116.createElement(ControlFormLabel, null, fieldLabel)), /* @__PURE__ */ React116.createElement(import_ui100.Grid, { item: true }, /* @__PURE__ */ React116.createElement(
8393
+ return /* @__PURE__ */ React116.createElement(ControlActions, null, /* @__PURE__ */ React116.createElement(
8352
8394
  import_ui100.Autocomplete,
8353
8395
  {
8354
8396
  fullWidth: true,
@@ -8364,15 +8406,21 @@ var EmailChipsField = ({ fieldLabel, placeholder }) => {
8364
8406
  },
8365
8407
  value: selectedValues,
8366
8408
  onChange: handleChange,
8367
- options: [],
8409
+ options: suggestionOptions,
8410
+ filterOptions: (options, state) => {
8411
+ const query = state.inputValue.trim().replace(/^@/, "").toLowerCase();
8412
+ return query ? options.filter((option) => option.toLowerCase().includes(query)) : options;
8413
+ },
8414
+ filterSelectedOptions: true,
8368
8415
  onBlur: handleBlur,
8369
8416
  getOptionLabel: (option) => option,
8370
8417
  isOptionEqualToValue: (option, val) => option === val,
8371
8418
  renderInput: (params) => /* @__PURE__ */ React116.createElement(import_ui100.TextField, { ...params, placeholder, onKeyDown: handleKeyDown }),
8372
8419
  renderTags: (tagValues, getTagProps) => /* @__PURE__ */ React116.createElement(ChipsList, { getLabel: (option) => option, getTagProps, values: tagValues })
8373
8420
  }
8374
- )));
8375
- };
8421
+ ));
8422
+ });
8423
+ var EmailChipsField = ({ fieldLabel, placeholder, suggestions }) => /* @__PURE__ */ React116.createElement(import_ui100.Grid, { container: true, direction: "column", gap: 0.5 }, /* @__PURE__ */ React116.createElement(import_ui100.Grid, { item: true }, /* @__PURE__ */ React116.createElement(ControlFormLabel, null, fieldLabel)), /* @__PURE__ */ React116.createElement(import_ui100.Grid, { item: true }, /* @__PURE__ */ React116.createElement(EmailChipsControl, { placeholder, suggestions })));
8376
8424
 
8377
8425
  // src/controls/email-form-action-control/email-field.tsx
8378
8426
  var React117 = __toESM(require("react"));
@@ -8380,7 +8428,17 @@ var import_ui101 = require("@elementor/ui");
8380
8428
  var EmailField = ({ bind, label, placeholder }) => /* @__PURE__ */ React117.createElement(PropKeyProvider, { bind }, /* @__PURE__ */ React117.createElement(import_ui101.Grid, { container: true, direction: "column", gap: 0.5 }, /* @__PURE__ */ React117.createElement(import_ui101.Grid, { item: true }, /* @__PURE__ */ React117.createElement(ControlFormLabel, null, label)), /* @__PURE__ */ React117.createElement(import_ui101.Grid, { item: true }, /* @__PURE__ */ React117.createElement(TextControl, { placeholder }))));
8381
8429
 
8382
8430
  // src/controls/email-form-action-control/fields.tsx
8383
- var SendToField = ({ placeholder }) => /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: (0, import_i18n57.__)("Send to", "elementor"), placeholder });
8431
+ var SendToField = ({ placeholder }) => {
8432
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8433
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "to" }, /* @__PURE__ */ React118.createElement(import_ui102.Stack, { gap: 0.5 }, /* @__PURE__ */ React118.createElement(
8434
+ EmailChipsField,
8435
+ {
8436
+ fieldLabel: (0, import_i18n57.__)("Send to", "elementor"),
8437
+ placeholder,
8438
+ suggestions
8439
+ }
8440
+ ), shouldShowMentionsInfo() && /* @__PURE__ */ React118.createElement(import_editor_ui15.InfoAlert, null, (0, import_i18n57.__)("Type @ or an email field name to insert its submitted value.", "elementor"))));
8441
+ };
8384
8442
  var SubjectField = () => /* @__PURE__ */ React118.createElement(
8385
8443
  EmailField,
8386
8444
  {
@@ -8424,8 +8482,14 @@ var ReplyToField = () => {
8424
8482
  }
8425
8483
  ))));
8426
8484
  };
8427
- var CcField = () => /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "cc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: (0, import_i18n57.__)("Cc", "elementor") }));
8428
- var BccField = () => /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "bcc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: (0, import_i18n57.__)("Bcc", "elementor") }));
8485
+ var CcField = () => {
8486
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8487
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "cc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: (0, import_i18n57.__)("Cc", "elementor"), suggestions }));
8488
+ };
8489
+ var BccField = () => {
8490
+ const suggestions = useFormFieldSuggestions({ inputType: "email" });
8491
+ return /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "bcc" }, /* @__PURE__ */ React118.createElement(EmailChipsField, { fieldLabel: (0, import_i18n57.__)("Bcc", "elementor"), suggestions }));
8492
+ };
8429
8493
  var MetaDataField = () => /* @__PURE__ */ React118.createElement(PropKeyProvider, { bind: "meta-data" }, /* @__PURE__ */ React118.createElement(import_ui102.Stack, { gap: 0.5 }, /* @__PURE__ */ React118.createElement(ControlFormLabel, null, (0, import_i18n57.__)("Metadata", "elementor")), /* @__PURE__ */ React118.createElement(
8430
8494
  ChipsControl,
8431
8495
  {
@@ -8452,7 +8516,7 @@ var SendAsField = () => /* @__PURE__ */ React118.createElement(PropKeyProvider,
8452
8516
  var EmailFormActionControl = createControl(
8453
8517
  ({ toPlaceholder, label }) => {
8454
8518
  const { value, setValue, ...propContext } = useBoundProp(import_editor_props66.emailsPropTypeUtil);
8455
- return /* @__PURE__ */ React119.createElement(PropProvider, { ...propContext, value, setValue }, /* @__PURE__ */ React119.createElement(import_ui103.Stack, { gap: 2 }, /* @__PURE__ */ React119.createElement(ControlLabel, null, label ? label + " " + (0, import_i18n58.__)("settings", "elementor") : (0, import_i18n58.__)("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)));
8519
+ return /* @__PURE__ */ React119.createElement(PropProvider, { ...propContext, value, setValue }, /* @__PURE__ */ React119.createElement(import_ui103.Stack, { gap: 2 }, /* @__PURE__ */ React119.createElement(ControlLabel, null, label ? label + " " + (0, import_i18n58.__)("settings", "elementor") : (0, import_i18n58.__)("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)));
8456
8520
  }
8457
8521
  );
8458
8522
  var AdvancedSettings = () => /* @__PURE__ */ React119.createElement(import_editor_ui16.CollapsibleContent, { defaultOpen: false }, /* @__PURE__ */ React119.createElement(import_ui103.Box, { sx: { pt: 2 } }, /* @__PURE__ */ React119.createElement(import_ui103.Stack, { 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(import_ui103.Divider, null), /* @__PURE__ */ React119.createElement(MetaDataField, null), /* @__PURE__ */ React119.createElement(SendAsField, null))));