@elementor/editor-editing-panel 0.15.0 → 0.16.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/index.js +693 -120
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +711 -111
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +7 -6
  7. package/src/components/style-sections/position-section/position-section.tsx +15 -0
  8. package/src/components/style-sections/position-section/z-index-control.tsx +16 -0
  9. package/src/components/style-sections/size-section.tsx +9 -12
  10. package/src/components/style-sections/spacing-section/linked-dimensions-control.tsx +140 -0
  11. package/src/components/style-sections/spacing-section/spacing-section.tsx +22 -0
  12. package/src/components/style-sections/typography-section/letter-spacing-control.tsx +16 -0
  13. package/src/components/style-sections/typography-section/text-color-control.tsx +16 -0
  14. package/src/components/style-sections/typography-section/transform-control.tsx +23 -0
  15. package/src/components/style-sections/typography-section/typography-section.tsx +15 -1
  16. package/src/components/style-sections/typography-section/word-spacing-control.tsx +16 -0
  17. package/src/components/style-tab.tsx +29 -5
  18. package/src/contexts/style-context.tsx +8 -2
  19. package/src/controls/components/control-toggle-button-group.tsx +59 -0
  20. package/src/controls/components/text-field-inner-selection.tsx +79 -0
  21. package/src/controls/control-types/color-control.tsx +24 -0
  22. package/src/controls/control-types/number-control.tsx +25 -0
  23. package/src/controls/control-types/size-control.tsx +20 -34
  24. package/src/controls/control-types/toggle-control.tsx +25 -0
  25. package/src/controls/hooks/use-style-control.ts +2 -1
  26. package/src/controls/settings-control.tsx +1 -1
  27. package/src/dynamics/components/dynamic-selection-control.tsx +180 -0
  28. package/src/dynamics/components/dynamic-selection.tsx +144 -0
  29. package/src/dynamics/dynamic-control.tsx +42 -0
  30. package/src/dynamics/hooks/use-dynamic-tag.ts +10 -0
  31. package/src/{hooks/use-dynamic-tags-config.ts → dynamics/hooks/use-prop-dynamic-tags.ts} +6 -5
  32. package/src/dynamics/init.ts +10 -0
  33. package/src/{sync → dynamics/sync}/get-atomic-dynamic-tags.ts +1 -1
  34. package/src/{sync → dynamics/sync}/get-elementor-config.ts +1 -1
  35. package/src/dynamics/types.ts +32 -0
  36. package/src/dynamics/utils.ts +9 -0
  37. package/src/init.ts +4 -0
  38. package/src/props/is-transformable.ts +14 -0
  39. package/src/sync/types.ts +0 -13
  40. package/src/sync/update-style.ts +2 -2
  41. package/src/types.ts +9 -6
package/dist/index.mjs CHANGED
@@ -27,8 +27,8 @@ function useControl(defaultValue) {
27
27
  import { __createPanel as createPanel } from "@elementor/editor-panels";
28
28
 
29
29
  // src/components/editing-panel.tsx
30
- import * as React23 from "react";
31
- import { __ as __9 } from "@wordpress/i18n";
30
+ import * as React36 from "react";
31
+ import { __ as __17 } from "@wordpress/i18n";
32
32
 
33
33
  // src/hooks/use-selected-elements.ts
34
34
  import { __privateUseListenTo as useListenTo, commandEndEvent } from "@elementor/editor-v1-adapters";
@@ -112,13 +112,13 @@ function useElementContext() {
112
112
  }
113
113
 
114
114
  // src/components/editing-panel-tabs.tsx
115
- import { Stack as Stack9, Tabs, Tab, TabPanel, useTabs } from "@elementor/ui";
116
- import * as React22 from "react";
117
- import { __ as __8 } from "@wordpress/i18n";
115
+ import { Stack as Stack11, Tabs, Tab, TabPanel, useTabs } from "@elementor/ui";
116
+ import * as React35 from "react";
117
+ import { __ as __16 } from "@wordpress/i18n";
118
118
 
119
119
  // src/components/settings-tab.tsx
120
- import * as React12 from "react";
121
- import { Stack as Stack4 } from "@elementor/ui";
120
+ import * as React13 from "react";
121
+ import { Stack as Stack3 } from "@elementor/ui";
122
122
 
123
123
  // src/controls/settings-control.tsx
124
124
  import * as React4 from "react";
@@ -184,7 +184,7 @@ var ControlContainer = (props) => /* @__PURE__ */ React3.createElement(StyledSta
184
184
  // src/controls/settings-control.tsx
185
185
  var SettingsControlProvider = ({ bind, children }) => {
186
186
  const { element, elementType } = useElementContext();
187
- const defaultValue = elementType.propsSchema[bind]?.default;
187
+ const defaultValue = elementType.propsSchema[bind]?.type.default;
188
188
  const settingsValue = useWidgetSettings({ id: element.id, bind });
189
189
  const value = settingsValue ?? defaultValue ?? null;
190
190
  const setValue = (newValue) => {
@@ -212,7 +212,7 @@ var AccordionSection = ({ title, children }) => {
212
212
  };
213
213
 
214
214
  // src/controls/control.tsx
215
- import * as React11 from "react";
215
+ import * as React12 from "react";
216
216
  import { createError } from "@elementor/utils";
217
217
 
218
218
  // src/controls/control-types/image-control.tsx
@@ -296,8 +296,8 @@ var TextAreaControl = ({ placeholder }) => {
296
296
  };
297
297
 
298
298
  // src/controls/control-types/size-control.tsx
299
- import * as React9 from "react";
300
- import { MenuItem, Select, Stack as Stack3, TextField as TextField3 } from "@elementor/ui";
299
+ import * as React10 from "react";
300
+ import { InputAdornment as InputAdornment2 } from "@elementor/ui";
301
301
 
302
302
  // src/controls/hooks/use-sync-external-state.tsx
303
303
  import { useEffect, useState } from "react";
@@ -332,9 +332,61 @@ var useSyncExternalState = ({
332
332
  return [internal, setInternalValue];
333
333
  };
334
334
 
335
+ // src/controls/components/text-field-inner-selection.tsx
336
+ import * as React9 from "react";
337
+ import { bindMenu, bindTrigger, Button as Button2, InputAdornment, Menu, MenuItem, TextField as TextField3, usePopupState } from "@elementor/ui";
338
+ import { useId as useId2 } from "react";
339
+ var TextFieldInnerSelection = ({
340
+ placeholder,
341
+ type,
342
+ value,
343
+ onChange,
344
+ endAdornment,
345
+ startAdornment
346
+ }) => {
347
+ return /* @__PURE__ */ React9.createElement(
348
+ TextField3,
349
+ {
350
+ size: "tiny",
351
+ type,
352
+ value,
353
+ onChange,
354
+ placeholder,
355
+ InputProps: {
356
+ endAdornment,
357
+ startAdornment
358
+ }
359
+ }
360
+ );
361
+ };
362
+ var SelectionEndAdornment = ({
363
+ options: options2,
364
+ onClick,
365
+ value
366
+ }) => {
367
+ const popupState = usePopupState({
368
+ variant: "popover",
369
+ popupId: useId2()
370
+ });
371
+ const handleMenuItemClick = (index) => {
372
+ onClick(options2[index]);
373
+ popupState.close();
374
+ };
375
+ return /* @__PURE__ */ React9.createElement(InputAdornment, { position: "end" }, /* @__PURE__ */ React9.createElement(
376
+ Button2,
377
+ {
378
+ size: "small",
379
+ color: "inherit",
380
+ sx: { font: "inherit", minWidth: "initial" },
381
+ ...bindTrigger(popupState)
382
+ },
383
+ value.toUpperCase()
384
+ ), /* @__PURE__ */ React9.createElement(Menu, { MenuListProps: { dense: true }, ...bindMenu(popupState) }, options2.map((option, index) => /* @__PURE__ */ React9.createElement(MenuItem, { key: option, onClick: () => handleMenuItemClick(index) }, option.toUpperCase()))));
385
+ };
386
+
335
387
  // src/controls/control-types/size-control.tsx
336
388
  var defaultUnits = ["px", "%", "em", "rem", "vw"];
337
- var SizeControl = ({ units = defaultUnits, placeholder }) => {
389
+ var SizeControl = ({ units = defaultUnits, placeholder, startIcon }) => {
338
390
  const { value, setValue } = useControl();
339
391
  const [state, setState] = useSyncExternalState({
340
392
  external: value,
@@ -345,8 +397,7 @@ var SizeControl = ({ units = defaultUnits, placeholder }) => {
345
397
  value: { unit: controlValue?.value.unit || "px", size: NaN }
346
398
  })
347
399
  });
348
- const handleUnitChange = (event) => {
349
- const unit = event.target.value;
400
+ const handleUnitChange = (unit) => {
350
401
  setState((prev) => ({
351
402
  ...prev,
352
403
  value: {
@@ -365,39 +416,28 @@ var SizeControl = ({ units = defaultUnits, placeholder }) => {
365
416
  }
366
417
  }));
367
418
  };
368
- return /* @__PURE__ */ React9.createElement(Stack3, { direction: "row" }, /* @__PURE__ */ React9.createElement(
369
- TextField3,
419
+ return /* @__PURE__ */ React10.createElement(
420
+ TextFieldInnerSelection,
370
421
  {
371
- size: "tiny",
422
+ endAdornment: /* @__PURE__ */ React10.createElement(SelectionEndAdornment, { options: units, onClick: handleUnitChange, value: state.value.unit }),
423
+ placeholder,
424
+ startAdornment: startIcon ?? /* @__PURE__ */ React10.createElement(InputAdornment2, { position: "start" }, startIcon),
372
425
  type: "number",
373
426
  value: Number.isNaN(state.value.size) ? "" : state.value.size,
374
- onChange: handleSizeChange,
375
- placeholder
427
+ onChange: handleSizeChange
376
428
  }
377
- ), /* @__PURE__ */ React9.createElement(
378
- Select,
379
- {
380
- size: "tiny",
381
- value: state.value.unit,
382
- onChange: handleUnitChange,
383
- MenuProps: {
384
- anchorOrigin: { vertical: "bottom", horizontal: "right" },
385
- transformOrigin: { vertical: "top", horizontal: "right" }
386
- }
387
- },
388
- units.map((unit) => /* @__PURE__ */ React9.createElement(MenuItem, { key: unit, value: unit }, unit.toUpperCase()))
389
- ));
429
+ );
390
430
  };
391
431
 
392
432
  // src/controls/control-types/select-control.tsx
393
- import * as React10 from "react";
394
- import { MenuItem as MenuItem2, Select as Select2 } from "@elementor/ui";
395
- var SelectControl = ({ options }) => {
433
+ import * as React11 from "react";
434
+ import { MenuItem as MenuItem2, Select } from "@elementor/ui";
435
+ var SelectControl = ({ options: options2 }) => {
396
436
  const { value, setValue } = useControl();
397
437
  const handleChange = (event) => {
398
438
  setValue(event.target.value);
399
439
  };
400
- return /* @__PURE__ */ React10.createElement(Select2, { size: "tiny", value: value ?? "", onChange: handleChange }, options.map(({ label, ...props }) => /* @__PURE__ */ React10.createElement(MenuItem2, { key: props.value, ...props }, label)));
440
+ return /* @__PURE__ */ React11.createElement(Select, { size: "tiny", value: value ?? "", onChange: handleChange }, options2.map(({ label, ...props }) => /* @__PURE__ */ React11.createElement(MenuItem2, { key: props.value, ...props }, label)));
401
441
  };
402
442
 
403
443
  // src/controls/controls-registry.tsx
@@ -424,20 +464,20 @@ var Control = ({ props, type }) => {
424
464
  });
425
465
  }
426
466
  const ControlComponent = getControlReplacement({ value }) || ControlByType;
427
- return /* @__PURE__ */ React11.createElement(ControlComponent, { ...props });
467
+ return /* @__PURE__ */ React12.createElement(ControlComponent, { ...props });
428
468
  };
429
469
 
430
470
  // src/components/settings-tab.tsx
431
471
  var SettingsTab = () => {
432
472
  const { elementType } = useElementContext();
433
- return /* @__PURE__ */ React12.createElement(Stack4, null, elementType.controls.map(({ type, value }, index) => {
473
+ return /* @__PURE__ */ React13.createElement(Stack3, null, elementType.controls.map(({ type, value }, index) => {
434
474
  if (type === "control") {
435
- return /* @__PURE__ */ React12.createElement(Control2, { key: value.bind, control: value });
475
+ return /* @__PURE__ */ React13.createElement(Control2, { key: value.bind, control: value });
436
476
  }
437
477
  if (type === "section") {
438
- return /* @__PURE__ */ React12.createElement(AccordionSection, { key: type + "." + index, title: value.label }, value.items?.map((item) => {
478
+ return /* @__PURE__ */ React13.createElement(AccordionSection, { key: type + "." + index, title: value.label }, value.items?.map((item) => {
439
479
  if (item.type === "control") {
440
- return /* @__PURE__ */ React12.createElement(Control2, { key: item.value.bind, control: item.value });
480
+ return /* @__PURE__ */ React13.createElement(Control2, { key: item.value.bind, control: item.value });
441
481
  }
442
482
  return null;
443
483
  }));
@@ -449,21 +489,21 @@ var Control2 = ({ control }) => {
449
489
  if (!getControlByType(control.type)) {
450
490
  return null;
451
491
  }
452
- return /* @__PURE__ */ React12.createElement(SettingsControl, { bind: control.bind }, control.label ? /* @__PURE__ */ React12.createElement(SettingsControl.Label, null, control.label) : null, /* @__PURE__ */ React12.createElement(Control, { type: control.type, props: control.props }));
492
+ return /* @__PURE__ */ React13.createElement(SettingsControl, { bind: control.bind }, control.label ? /* @__PURE__ */ React13.createElement(SettingsControl.Label, null, control.label) : null, /* @__PURE__ */ React13.createElement(Control, { type: control.type, props: control.props }));
453
493
  };
454
494
 
455
495
  // src/components/style-tab.tsx
456
- import * as React21 from "react";
496
+ import * as React34 from "react";
457
497
 
458
498
  // src/contexts/style-context.tsx
459
- import * as React13 from "react";
499
+ import * as React14 from "react";
460
500
  import { createContext as createContext3, useContext as useContext3 } from "react";
461
501
  import { useActiveBreakpoint } from "@elementor/editor-responsive";
462
502
  var Context2 = createContext3(null);
463
- function StyleContext({ children, selectedStyleDef }) {
503
+ function StyleContext({ children, selectedStyleDef, selectedClassesProp }) {
464
504
  const breakpoint = useActiveBreakpoint();
465
505
  const selectedMeta = { breakpoint, state: null };
466
- return /* @__PURE__ */ React13.createElement(Context2.Provider, { value: { selectedStyleDef, selectedMeta } }, children);
506
+ return /* @__PURE__ */ React14.createElement(Context2.Provider, { value: { selectedStyleDef, selectedMeta, selectedClassesProp } }, children);
467
507
  }
468
508
  function useStyleContext() {
469
509
  const context = useContext3(Context2);
@@ -494,13 +534,13 @@ var useElementStyles = (elementID) => {
494
534
  };
495
535
 
496
536
  // src/components/style-tab.tsx
497
- import { Stack as Stack8 } from "@elementor/ui";
537
+ import { Stack as Stack10 } from "@elementor/ui";
498
538
 
499
539
  // src/components/style-sections/size-section.tsx
500
540
  import * as React16 from "react";
501
541
 
502
542
  // src/controls/style-control.tsx
503
- import * as React14 from "react";
543
+ import * as React15 from "react";
504
544
 
505
545
  // src/hooks/use-element-style-prop.ts
506
546
  import { commandEndEvent as commandEndEvent5, __privateUseListenTo as useListenTo5 } from "@elementor/editor-v1-adapters";
@@ -534,7 +574,7 @@ function getVariantByMeta(styleDef, meta) {
534
574
 
535
575
  // src/sync/update-style.ts
536
576
  import { __privateRunCommand as runCommand2 } from "@elementor/editor-v1-adapters";
537
- var updateStyle = ({ elementID, styleDefID, meta, props, bind = "classes" }) => {
577
+ var updateStyle = ({ elementID, styleDefID, meta, props, bind }) => {
538
578
  const container = getContainer(elementID);
539
579
  runCommand2("document/atomic-widgets/styles", {
540
580
  container,
@@ -548,7 +588,7 @@ var updateStyle = ({ elementID, styleDefID, meta, props, bind = "classes" }) =>
548
588
  // src/controls/hooks/use-style-control.ts
549
589
  var useStyleControl = (propName) => {
550
590
  const { element } = useElementContext();
551
- const { selectedStyleDef, selectedMeta } = useStyleContext();
591
+ const { selectedStyleDef, selectedMeta, selectedClassesProp } = useStyleContext();
552
592
  const value = useElementStyleProp({
553
593
  elementID: element.id,
554
594
  styleDefID: selectedStyleDef?.id,
@@ -560,7 +600,8 @@ var useStyleControl = (propName) => {
560
600
  elementID: element.id,
561
601
  styleDefID: selectedStyleDef?.id,
562
602
  props: { [propName]: newValue },
563
- meta: selectedMeta
603
+ meta: selectedMeta,
604
+ bind: selectedClassesProp
564
605
  });
565
606
  };
566
607
  return [value, setValue];
@@ -569,68 +610,35 @@ var useStyleControl = (propName) => {
569
610
  // src/controls/style-control.tsx
570
611
  var StyleControl = ({ bind, children }) => {
571
612
  const [value, setValue] = useStyleControl(bind);
572
- return /* @__PURE__ */ React14.createElement(ControlContext.Provider, { value: { bind, value, setValue } }, children);
613
+ return /* @__PURE__ */ React15.createElement(ControlContext.Provider, { value: { bind, value, setValue } }, children);
573
614
  };
574
615
  StyleControl.Label = ControlLabel;
575
616
 
576
- // src/components/collapsible-content.tsx
577
- import * as React15 from "react";
578
- import { useState as useState2 } from "react";
579
- import { ChevronDownIcon } from "@elementor/icons";
580
- import { Button as Button2, Collapse, Stack as Stack5, styled as styled2 } from "@elementor/ui";
581
- import { __ as __2 } from "@wordpress/i18n";
582
- var CollapsibleContent = ({ children, defaultOpen = false }) => {
583
- const [open, setOpen] = useState2(defaultOpen);
584
- const handleToggle = () => {
585
- setOpen((prevOpen) => !prevOpen);
586
- };
587
- return /* @__PURE__ */ React15.createElement(Stack5, { sx: { py: 0.5 } }, /* @__PURE__ */ React15.createElement(
588
- Button2,
589
- {
590
- fullWidth: true,
591
- size: "small",
592
- color: "secondary",
593
- variant: "outlined",
594
- onClick: handleToggle,
595
- endIcon: /* @__PURE__ */ React15.createElement(ChevronIcon, { open })
596
- },
597
- open ? __2("Show less", "elementor") : __2("Show more", "elementor")
598
- ), /* @__PURE__ */ React15.createElement(Collapse, { in: open, timeout: "auto" }, children));
599
- };
600
- var ChevronIcon = styled2(ChevronDownIcon, {
601
- shouldForwardProp: (prop) => prop !== "open"
602
- })(({ theme, open }) => ({
603
- transform: open ? "rotate(180deg)" : "rotate(0)",
604
- transition: theme.transitions.create("transform", {
605
- duration: theme.transitions.duration.standard
606
- })
607
- }));
608
-
609
617
  // src/components/style-sections/size-section.tsx
610
- import { Stack as Stack6 } from "@elementor/ui";
611
- import { __ as __3 } from "@wordpress/i18n";
618
+ import { Stack as Stack4 } from "@elementor/ui";
619
+ import { __ as __2 } from "@wordpress/i18n";
612
620
  var SizeSection = () => {
613
- return /* @__PURE__ */ React16.createElement(AccordionSection, { title: __3("Size", "elementor") }, /* @__PURE__ */ React16.createElement(Stack6, { gap: 1.5 }, /* @__PURE__ */ React16.createElement(Stack6, { direction: "row", gap: 2 }, /* @__PURE__ */ React16.createElement(Control3, { bind: "width", label: __3("Width", "elementor") }), /* @__PURE__ */ React16.createElement(Control3, { bind: "height", label: __3("Height", "elementor") })), /* @__PURE__ */ React16.createElement(CollapsibleContent, null, /* @__PURE__ */ React16.createElement(Stack6, { gap: 1.5, sx: { pt: 1.5 } }, /* @__PURE__ */ React16.createElement(Stack6, { direction: "row", gap: 2 }, /* @__PURE__ */ React16.createElement(Control3, { bind: "minWidth", label: __3("Min. Width", "elementor") }), /* @__PURE__ */ React16.createElement(Control3, { bind: "minHeight", label: __3("Min. Height", "elementor") })), /* @__PURE__ */ React16.createElement(Stack6, { direction: "row", gap: 2 }, /* @__PURE__ */ React16.createElement(Control3, { bind: "maxWidth", label: __3("Max. Width", "elementor") }), /* @__PURE__ */ React16.createElement(Control3, { bind: "maxHeight", label: __3("Max. Height", "elementor") }))))));
621
+ return /* @__PURE__ */ React16.createElement(AccordionSection, { title: __2("Size", "elementor") }, /* @__PURE__ */ React16.createElement(Stack4, { gap: 1.5 }, /* @__PURE__ */ React16.createElement(Stack4, { direction: "row", gap: 2 }, /* @__PURE__ */ React16.createElement(Control3, { bind: "width", label: __2("Width", "elementor") }), /* @__PURE__ */ React16.createElement(Control3, { bind: "height", label: __2("Height", "elementor") })), /* @__PURE__ */ React16.createElement(Stack4, { gap: 1.5, sx: { pt: 1.5 } }, /* @__PURE__ */ React16.createElement(Stack4, { direction: "row", gap: 2 }, /* @__PURE__ */ React16.createElement(Control3, { bind: "minWidth", label: __2("Min. Width", "elementor") }), /* @__PURE__ */ React16.createElement(Control3, { bind: "minHeight", label: __2("Min. Height", "elementor") })), /* @__PURE__ */ React16.createElement(Stack4, { direction: "row", gap: 2 }, /* @__PURE__ */ React16.createElement(Control3, { bind: "maxWidth", label: __2("Max. Width", "elementor") }), /* @__PURE__ */ React16.createElement(Control3, { bind: "maxHeight", label: __2("Max. Height", "elementor") })))));
614
622
  };
615
623
  var Control3 = ({ label, bind }) => {
616
624
  return /* @__PURE__ */ React16.createElement(StyleControl, { bind }, /* @__PURE__ */ React16.createElement(ControlContainer, { direction: "column" }, /* @__PURE__ */ React16.createElement(StyleControl.Label, null, label), /* @__PURE__ */ React16.createElement(Control, { type: "size" })));
617
625
  };
618
626
 
619
627
  // src/components/style-sections/typography-section/typography-section.tsx
620
- import * as React20 from "react";
621
- import { Divider, Stack as Stack7 } from "@elementor/ui";
628
+ import * as React28 from "react";
629
+ import { Divider, Stack as Stack6 } from "@elementor/ui";
622
630
 
623
631
  // src/components/style-sections/typography-section/text-style-control.tsx
624
632
  import * as React17 from "react";
625
633
  import { ToggleButton as ToggleButtonBase, ToggleButtonGroup } from "@elementor/ui";
626
634
  import { ItalicIcon, StrikethroughIcon, UnderlineIcon } from "@elementor/icons";
627
- import { __ as __4 } from "@wordpress/i18n";
635
+ import { __ as __3 } from "@wordpress/i18n";
628
636
  var buttonSize = "tiny";
629
637
  var TextStyleControl = () => {
630
638
  const [fontStyle, setFontStyle] = useStyleControl("fontStyle");
631
639
  const [textDecoration, setTextDecoration] = useStyleControl("textDecoration");
632
640
  const formats = [fontStyle, ...(textDecoration || "").split(" ")];
633
- return /* @__PURE__ */ React17.createElement(ControlContainer, null, /* @__PURE__ */ React17.createElement(ControlLabel, null, __4("Style", "elementor")), /* @__PURE__ */ React17.createElement(ToggleButtonGroup, { value: formats }, /* @__PURE__ */ React17.createElement(
641
+ return /* @__PURE__ */ React17.createElement(ControlContainer, null, /* @__PURE__ */ React17.createElement(ControlLabel, null, __3("Style", "elementor")), /* @__PURE__ */ React17.createElement(ToggleButtonGroup, { value: formats }, /* @__PURE__ */ React17.createElement(
634
642
  ToggleButton,
635
643
  {
636
644
  value: "italic",
@@ -685,46 +693,337 @@ var ToggleButton = ({ onChange, ...props }) => {
685
693
  };
686
694
 
687
695
  // src/components/style-sections/typography-section/typography-section.tsx
688
- import { __ as __7 } from "@wordpress/i18n";
696
+ import { __ as __11 } from "@wordpress/i18n";
689
697
 
690
698
  // src/components/style-sections/typography-section/font-size-control.tsx
691
699
  import * as React18 from "react";
692
- import { __ as __5 } from "@wordpress/i18n";
700
+ import { __ as __4 } from "@wordpress/i18n";
693
701
  var FontSizeControl = () => {
694
- return /* @__PURE__ */ React18.createElement(StyleControl, { bind: "font-size" }, /* @__PURE__ */ React18.createElement(ControlContainer, null, /* @__PURE__ */ React18.createElement(StyleControl.Label, null, __5("Font Size", "elementor")), /* @__PURE__ */ React18.createElement(SizeControl, null)));
702
+ return /* @__PURE__ */ React18.createElement(StyleControl, { bind: "font-size" }, /* @__PURE__ */ React18.createElement(ControlContainer, null, /* @__PURE__ */ React18.createElement(StyleControl.Label, null, __4("Font Size", "elementor")), /* @__PURE__ */ React18.createElement(SizeControl, null)));
695
703
  };
696
704
 
697
705
  // src/components/style-sections/typography-section/font-weight-control.tsx
698
706
  import * as React19 from "react";
699
- import { __ as __6 } from "@wordpress/i18n";
707
+ import { __ as __5 } from "@wordpress/i18n";
700
708
  var fontWeightOptions = [
701
- { label: __6("Light - 400", "elementor"), value: 400 },
702
- { label: __6("Regular - 500", "elementor"), value: 500 },
703
- { label: __6("Semi Bold - 600", "elementor"), value: 600 },
704
- { label: __6("Bold - 700", "elementor"), value: 700 },
705
- { label: __6("Black - 900", "elementor"), value: 900 }
709
+ { label: __5("Light - 400", "elementor"), value: 400 },
710
+ { label: __5("Regular - 500", "elementor"), value: 500 },
711
+ { label: __5("Semi Bold - 600", "elementor"), value: 600 },
712
+ { label: __5("Bold - 700", "elementor"), value: 700 },
713
+ { label: __5("Black - 900", "elementor"), value: 900 }
706
714
  ];
707
715
  var FontWeightControl = () => {
708
- return /* @__PURE__ */ React19.createElement(StyleControl, { bind: "fontWeight" }, /* @__PURE__ */ React19.createElement(ControlContainer, null, /* @__PURE__ */ React19.createElement(StyleControl.Label, null, __6("Font Weight", "elementor")), /* @__PURE__ */ React19.createElement(SelectControl, { options: fontWeightOptions })));
716
+ return /* @__PURE__ */ React19.createElement(StyleControl, { bind: "fontWeight" }, /* @__PURE__ */ React19.createElement(ControlContainer, null, /* @__PURE__ */ React19.createElement(StyleControl.Label, null, __5("Font Weight", "elementor")), /* @__PURE__ */ React19.createElement(SelectControl, { options: fontWeightOptions })));
717
+ };
718
+
719
+ // src/components/style-sections/typography-section/text-color-control.tsx
720
+ import * as React21 from "react";
721
+ import { __ as __6 } from "@wordpress/i18n";
722
+
723
+ // src/controls/control-types/color-control.tsx
724
+ import * as React20 from "react";
725
+ import { UnstableColorPicker } from "@elementor/ui";
726
+ var ColorControl = () => {
727
+ const { value, setValue } = useControl();
728
+ const handleChange = debounce((selectedColor) => {
729
+ setValue(selectedColor);
730
+ });
731
+ return /* @__PURE__ */ React20.createElement(UnstableColorPicker, { value, onChange: handleChange });
732
+ };
733
+ var debounce = (func, wait = 300) => {
734
+ let timer;
735
+ return (...args) => {
736
+ clearTimeout(timer);
737
+ timer = setTimeout(() => func(...args), wait);
738
+ };
739
+ };
740
+
741
+ // src/components/style-sections/typography-section/text-color-control.tsx
742
+ var TextColorControl = () => {
743
+ return /* @__PURE__ */ React21.createElement(StyleControl, { bind: "color" }, /* @__PURE__ */ React21.createElement(ControlContainer, null, /* @__PURE__ */ React21.createElement(StyleControl.Label, null, __6("Text Color", "elementor")), /* @__PURE__ */ React21.createElement(ColorControl, null)));
744
+ };
745
+
746
+ // src/components/style-sections/typography-section/letter-spacing-control.tsx
747
+ import * as React22 from "react";
748
+ import { __ as __7 } from "@wordpress/i18n";
749
+ var LetterSpacingControl = () => {
750
+ return /* @__PURE__ */ React22.createElement(StyleControl, { bind: "letter-spacing" }, /* @__PURE__ */ React22.createElement(ControlContainer, null, /* @__PURE__ */ React22.createElement(StyleControl.Label, null, __7("Letter Spacing", "elementor")), /* @__PURE__ */ React22.createElement(SizeControl, null)));
751
+ };
752
+
753
+ // src/components/style-sections/typography-section/word-spacing-control.tsx
754
+ import * as React23 from "react";
755
+ import { __ as __8 } from "@wordpress/i18n";
756
+ var WordSpacingControl = () => {
757
+ return /* @__PURE__ */ React23.createElement(StyleControl, { bind: "word-spacing" }, /* @__PURE__ */ React23.createElement(ControlContainer, null, /* @__PURE__ */ React23.createElement(StyleControl.Label, null, __8("Word Spacing", "elementor")), /* @__PURE__ */ React23.createElement(SizeControl, null)));
758
+ };
759
+
760
+ // src/components/collapsible-content.tsx
761
+ import * as React24 from "react";
762
+ import { useState as useState2 } from "react";
763
+ import { ChevronDownIcon } from "@elementor/icons";
764
+ import { Button as Button3, Collapse, Stack as Stack5, styled as styled2 } from "@elementor/ui";
765
+ import { __ as __9 } from "@wordpress/i18n";
766
+ var CollapsibleContent = ({ children, defaultOpen = false }) => {
767
+ const [open, setOpen] = useState2(defaultOpen);
768
+ const handleToggle = () => {
769
+ setOpen((prevOpen) => !prevOpen);
770
+ };
771
+ return /* @__PURE__ */ React24.createElement(Stack5, { sx: { py: 0.5 } }, /* @__PURE__ */ React24.createElement(
772
+ Button3,
773
+ {
774
+ fullWidth: true,
775
+ size: "small",
776
+ color: "secondary",
777
+ variant: "outlined",
778
+ onClick: handleToggle,
779
+ endIcon: /* @__PURE__ */ React24.createElement(ChevronIcon, { open })
780
+ },
781
+ open ? __9("Show less", "elementor") : __9("Show more", "elementor")
782
+ ), /* @__PURE__ */ React24.createElement(Collapse, { in: open, timeout: "auto" }, children));
783
+ };
784
+ var ChevronIcon = styled2(ChevronDownIcon, {
785
+ shouldForwardProp: (prop) => prop !== "open"
786
+ })(({ theme, open }) => ({
787
+ transform: open ? "rotate(180deg)" : "rotate(0)",
788
+ transition: theme.transitions.create("transform", {
789
+ duration: theme.transitions.duration.standard
790
+ })
791
+ }));
792
+
793
+ // src/components/style-sections/typography-section/transform-control.tsx
794
+ import * as React27 from "react";
795
+ import { __ as __10 } from "@wordpress/i18n";
796
+
797
+ // src/controls/control-types/toggle-control.tsx
798
+ import * as React26 from "react";
799
+
800
+ // src/controls/components/control-toggle-button-group.tsx
801
+ import * as React25 from "react";
802
+ import { styled as styled3, ToggleButton as ToggleButton2, ToggleButtonGroup as ToggleButtonGroup2 } from "@elementor/ui";
803
+ var StyledToggleButtonGroup = styled3(ToggleButtonGroup2)`
804
+ ${({ justify }) => `justify-content: ${justify};`}
805
+ `;
806
+ var ControlToggleButtonGroup = ({
807
+ justify = "end",
808
+ size = "tiny",
809
+ value,
810
+ onChange,
811
+ items,
812
+ exclusive = false
813
+ }) => {
814
+ const handleChange = (_, newValue) => {
815
+ onChange(newValue);
816
+ };
817
+ return /* @__PURE__ */ React25.createElement(StyledToggleButtonGroup, { justify, value, onChange: handleChange, exclusive }, items.map(({ label, value: buttonValue, icon: Icon }) => /* @__PURE__ */ React25.createElement(ToggleButton2, { key: buttonValue, value: buttonValue, "aria-label": label, size }, /* @__PURE__ */ React25.createElement(Icon, { fontSize: size }))));
818
+ };
819
+
820
+ // src/controls/control-types/toggle-control.tsx
821
+ var ToggleControl = ({ options: options2 }) => {
822
+ const { value, setValue } = useControl();
823
+ const handleToggle = (option) => {
824
+ setValue(option || void 0);
825
+ };
826
+ return /* @__PURE__ */ React26.createElement(
827
+ ControlToggleButtonGroup,
828
+ {
829
+ items: options2,
830
+ value: value || null,
831
+ onChange: handleToggle,
832
+ exclusive: true
833
+ }
834
+ );
835
+ };
836
+
837
+ // src/components/style-sections/typography-section/transform-control.tsx
838
+ import { LetterCaseIcon, LetterCaseLowerIcon, LetterCaseUpperIcon } from "@elementor/icons";
839
+ var options = [
840
+ { value: "capitalize", label: __10("Capitalize", "elementor"), icon: LetterCaseIcon },
841
+ { value: "uppercase", label: __10("Uppercase", "elementor"), icon: LetterCaseUpperIcon },
842
+ { value: "lowercase", label: __10("Lowercase", "elementor"), icon: LetterCaseLowerIcon }
843
+ ];
844
+ var TransformControl = () => {
845
+ return /* @__PURE__ */ React27.createElement(ControlContainer, null, /* @__PURE__ */ React27.createElement(StyleControl.Label, null, __10("Transform", "elementor")), /* @__PURE__ */ React27.createElement(StyleControl, { bind: "text-transform" }, /* @__PURE__ */ React27.createElement(ToggleControl, { options })));
709
846
  };
710
847
 
711
848
  // src/components/style-sections/typography-section/typography-section.tsx
712
849
  var TypographySection = () => {
713
- return /* @__PURE__ */ React20.createElement(AccordionSection, { title: __7("Typography", "elementor") }, /* @__PURE__ */ React20.createElement(Stack7, { gap: 1.5 }, /* @__PURE__ */ React20.createElement(FontWeightControl, null), /* @__PURE__ */ React20.createElement(FontSizeControl, null), /* @__PURE__ */ React20.createElement(Divider, null), /* @__PURE__ */ React20.createElement(TextStyleControl, null)));
850
+ return /* @__PURE__ */ React28.createElement(AccordionSection, { title: __11("Typography", "elementor") }, /* @__PURE__ */ React28.createElement(Stack6, { gap: 1.5 }, /* @__PURE__ */ React28.createElement(FontWeightControl, null), /* @__PURE__ */ React28.createElement(FontSizeControl, null), /* @__PURE__ */ React28.createElement(Divider, null), /* @__PURE__ */ React28.createElement(TextColorControl, null), /* @__PURE__ */ React28.createElement(CollapsibleContent, null, /* @__PURE__ */ React28.createElement(Stack6, { gap: 1.5, sx: { pt: 1.5 } }, /* @__PURE__ */ React28.createElement(LetterSpacingControl, null), /* @__PURE__ */ React28.createElement(WordSpacingControl, null), /* @__PURE__ */ React28.createElement(Divider, null), /* @__PURE__ */ React28.createElement(TextStyleControl, null), /* @__PURE__ */ React28.createElement(TransformControl, null)))));
851
+ };
852
+
853
+ // src/components/style-sections/position-section/position-section.tsx
854
+ import * as React31 from "react";
855
+ import { Stack as Stack7 } from "@elementor/ui";
856
+
857
+ // src/components/style-sections/position-section/z-index-control.tsx
858
+ import * as React30 from "react";
859
+ import { __ as __12 } from "@wordpress/i18n";
860
+
861
+ // src/controls/control-types/number-control.tsx
862
+ import * as React29 from "react";
863
+ import { TextField as TextField4 } from "@elementor/ui";
864
+ var isEmptyOrNaN = (value) => value === void 0 || value === "" || Number.isNaN(Number(value));
865
+ var NumberControl = ({ placeholder }) => {
866
+ const { value, setValue } = useControl();
867
+ const handleChange = (event) => {
868
+ const eventValue = event.target.value;
869
+ setValue(isEmptyOrNaN(eventValue) ? void 0 : Number(eventValue));
870
+ };
871
+ return /* @__PURE__ */ React29.createElement(
872
+ TextField4,
873
+ {
874
+ size: "tiny",
875
+ type: "number",
876
+ value: isEmptyOrNaN(value) ? "" : value,
877
+ onChange: handleChange,
878
+ placeholder
879
+ }
880
+ );
881
+ };
882
+
883
+ // src/components/style-sections/position-section/z-index-control.tsx
884
+ var ZIndexControl = () => {
885
+ return /* @__PURE__ */ React30.createElement(StyleControl, { bind: "zIndex" }, /* @__PURE__ */ React30.createElement(ControlContainer, null, /* @__PURE__ */ React30.createElement(StyleControl.Label, null, __12("Z-Index", "elementor")), /* @__PURE__ */ React30.createElement(NumberControl, null)));
886
+ };
887
+
888
+ // src/components/style-sections/position-section/position-section.tsx
889
+ import { __ as __13 } from "@wordpress/i18n";
890
+ var PositionSection = () => {
891
+ return /* @__PURE__ */ React31.createElement(AccordionSection, { title: __13("Position", "elementor") }, /* @__PURE__ */ React31.createElement(Stack7, { gap: 1.5 }, /* @__PURE__ */ React31.createElement(ZIndexControl, null)));
892
+ };
893
+
894
+ // src/components/style-sections/spacing-section/spacing-section.tsx
895
+ import * as React33 from "react";
896
+ import { Divider as Divider2, Stack as Stack9 } from "@elementor/ui";
897
+ import { __ as __15 } from "@wordpress/i18n";
898
+
899
+ // src/components/style-sections/spacing-section/linked-dimensions-control.tsx
900
+ import * as React32 from "react";
901
+ import { Stack as Stack8, ToggleButton as ToggleButton3 } from "@elementor/ui";
902
+ import { DetachIcon, LinkIcon, SideBottomIcon, SideLeftIcon, SideRightIcon, SideTopIcon } from "@elementor/icons";
903
+ import { __ as __14 } from "@wordpress/i18n";
904
+ var LinkedDimensionsControl = ({ label }) => {
905
+ const { value, setValue } = useControl();
906
+ const { top, right, bottom, left, isLinked = false } = value?.value || {};
907
+ const setLinkedValue = (position, newValue) => {
908
+ const updatedValue = {
909
+ isLinked,
910
+ top: isLinked ? newValue : top,
911
+ right: isLinked ? newValue : right,
912
+ bottom: isLinked ? newValue : bottom,
913
+ left: isLinked ? newValue : left,
914
+ [position]: newValue
915
+ };
916
+ setValue({
917
+ $$type: "linked-dimensions",
918
+ value: updatedValue
919
+ });
920
+ };
921
+ const toggleLinked = () => {
922
+ const updatedValue = {
923
+ isLinked: !isLinked,
924
+ top,
925
+ right: !isLinked ? top : right,
926
+ bottom: !isLinked ? top : bottom,
927
+ left: !isLinked ? top : left
928
+ };
929
+ setValue({
930
+ $$type: "linked-dimensions",
931
+ value: updatedValue
932
+ });
933
+ };
934
+ const LinkedIcon = isLinked ? LinkIcon : DetachIcon;
935
+ return /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(Stack8, { direction: "row", gap: 2 }, /* @__PURE__ */ React32.createElement(ControlLabel, null, label), /* @__PURE__ */ React32.createElement(
936
+ ToggleButton3,
937
+ {
938
+ "aria-label": __14("Link Inputs", "elementor"),
939
+ size: "tiny",
940
+ value: "check",
941
+ selected: isLinked,
942
+ sx: { marginLeft: "auto" },
943
+ onChange: toggleLinked
944
+ },
945
+ /* @__PURE__ */ React32.createElement(LinkedIcon, { fontSize: "tiny" })
946
+ )), /* @__PURE__ */ React32.createElement(Stack8, { direction: "row", gap: 2 }, /* @__PURE__ */ React32.createElement(ControlContainer, { direction: "column" }, /* @__PURE__ */ React32.createElement(ControlLabel, null, __14("Top", "elementor")), /* @__PURE__ */ React32.createElement(
947
+ Control4,
948
+ {
949
+ bind: "top",
950
+ value: top,
951
+ setValue: setLinkedValue,
952
+ startIcon: /* @__PURE__ */ React32.createElement(SideTopIcon, { fontSize: "tiny" })
953
+ }
954
+ )), /* @__PURE__ */ React32.createElement(ControlContainer, { direction: "column" }, /* @__PURE__ */ React32.createElement(ControlLabel, null, __14("Right", "elementor")), /* @__PURE__ */ React32.createElement(
955
+ Control4,
956
+ {
957
+ bind: "right",
958
+ value: right,
959
+ setValue: setLinkedValue,
960
+ startIcon: /* @__PURE__ */ React32.createElement(SideRightIcon, { fontSize: "tiny" })
961
+ }
962
+ ))), /* @__PURE__ */ React32.createElement(Stack8, { direction: "row", gap: 2 }, /* @__PURE__ */ React32.createElement(ControlContainer, { direction: "column" }, /* @__PURE__ */ React32.createElement(ControlLabel, null, __14("Bottom", "elementor")), /* @__PURE__ */ React32.createElement(
963
+ Control4,
964
+ {
965
+ bind: "bottom",
966
+ value: bottom,
967
+ setValue: setLinkedValue,
968
+ startIcon: /* @__PURE__ */ React32.createElement(SideBottomIcon, { fontSize: "tiny" })
969
+ }
970
+ )), /* @__PURE__ */ React32.createElement(ControlContainer, { direction: "column" }, /* @__PURE__ */ React32.createElement(ControlLabel, null, __14("Left", "elementor")), /* @__PURE__ */ React32.createElement(
971
+ Control4,
972
+ {
973
+ bind: "left",
974
+ value: left,
975
+ setValue: setLinkedValue,
976
+ startIcon: /* @__PURE__ */ React32.createElement(SideLeftIcon, { fontSize: "tiny" })
977
+ }
978
+ ))));
979
+ };
980
+ var Control4 = ({
981
+ bind,
982
+ startIcon,
983
+ value,
984
+ setValue
985
+ }) => /* @__PURE__ */ React32.createElement(
986
+ ControlContext.Provider,
987
+ {
988
+ value: {
989
+ bind,
990
+ setValue: (newValue) => setValue(bind, newValue),
991
+ value
992
+ }
993
+ },
994
+ /* @__PURE__ */ React32.createElement(SizeControl, { startIcon })
995
+ );
996
+
997
+ // src/components/style-sections/spacing-section/spacing-section.tsx
998
+ var SpacingSection = () => {
999
+ return /* @__PURE__ */ React33.createElement(AccordionSection, { title: __15("Spacing", "elementor") }, /* @__PURE__ */ React33.createElement(Stack9, { gap: 1.5 }, /* @__PURE__ */ React33.createElement(StyleControl, { bind: "padding" }, /* @__PURE__ */ React33.createElement(LinkedDimensionsControl, { label: __15("Padding", "elementor") })), /* @__PURE__ */ React33.createElement(Divider2, null), /* @__PURE__ */ React33.createElement(StyleControl, { bind: "margin" }, /* @__PURE__ */ React33.createElement(LinkedDimensionsControl, { label: __15("Margin", "elementor") }))));
714
1000
  };
715
1001
 
716
1002
  // src/components/style-tab.tsx
1003
+ var CLASSES_PROP_KEY = "classes";
717
1004
  var StyleTab = () => {
1005
+ const styleDefinition = useStyleDefinition();
1006
+ const classesProp = useClassesProp();
1007
+ return /* @__PURE__ */ React34.createElement(StyleContext, { selectedStyleDef: styleDefinition, selectedClassesProp: classesProp }, /* @__PURE__ */ React34.createElement(Stack10, null, /* @__PURE__ */ React34.createElement(SizeSection, null), /* @__PURE__ */ React34.createElement(PositionSection, null), /* @__PURE__ */ React34.createElement(TypographySection, null), /* @__PURE__ */ React34.createElement(SpacingSection, null)));
1008
+ };
1009
+ function useClassesProp() {
1010
+ const { elementType } = useElementContext();
1011
+ const prop = Object.entries(elementType.propsSchema).find(([, { type }]) => type.key === CLASSES_PROP_KEY);
1012
+ if (!prop) {
1013
+ throw new Error("Element does not have a classes prop");
1014
+ }
1015
+ return prop[0];
1016
+ }
1017
+ function useStyleDefinition() {
718
1018
  const { element } = useElementContext();
719
1019
  const elementStyles = useElementStyles(element.id);
720
- const [selectedStyleDef = null] = Object.values(elementStyles || {});
721
- return /* @__PURE__ */ React21.createElement(StyleContext, { selectedStyleDef }, /* @__PURE__ */ React21.createElement(Stack8, null, /* @__PURE__ */ React21.createElement(SizeSection, null), /* @__PURE__ */ React21.createElement(TypographySection, null)));
722
- };
1020
+ return Object.values(elementStyles || {})[0] ?? null;
1021
+ }
723
1022
 
724
1023
  // src/components/editing-panel-tabs.tsx
725
1024
  var EditingPanelTabs = () => {
726
1025
  const { getTabProps, getTabPanelProps, getTabsProps } = useTabs("settings");
727
- return /* @__PURE__ */ React22.createElement(Stack9, { direction: "column", sx: { width: "100%" } }, /* @__PURE__ */ React22.createElement(Tabs, { variant: "fullWidth", indicatorColor: "secondary", textColor: "inherit", ...getTabsProps() }, /* @__PURE__ */ React22.createElement(Tab, { label: __8("General", "elementor"), ...getTabProps("settings") }), /* @__PURE__ */ React22.createElement(Tab, { label: __8("Style", "elementor"), ...getTabProps("style") })), /* @__PURE__ */ React22.createElement(TabPanel, { ...getTabPanelProps("settings"), disablePadding: true }, /* @__PURE__ */ React22.createElement(SettingsTab, null)), /* @__PURE__ */ React22.createElement(TabPanel, { ...getTabPanelProps("style"), disablePadding: true }, /* @__PURE__ */ React22.createElement(StyleTab, null)));
1026
+ return /* @__PURE__ */ React35.createElement(Stack11, { direction: "column", sx: { width: "100%" } }, /* @__PURE__ */ React35.createElement(Tabs, { variant: "fullWidth", indicatorColor: "secondary", textColor: "inherit", ...getTabsProps() }, /* @__PURE__ */ React35.createElement(Tab, { label: __16("General", "elementor"), ...getTabProps("settings") }), /* @__PURE__ */ React35.createElement(Tab, { label: __16("Style", "elementor"), ...getTabProps("style") })), /* @__PURE__ */ React35.createElement(TabPanel, { ...getTabPanelProps("settings"), disablePadding: true }, /* @__PURE__ */ React35.createElement(SettingsTab, null)), /* @__PURE__ */ React35.createElement(TabPanel, { ...getTabPanelProps("style"), disablePadding: true }, /* @__PURE__ */ React35.createElement(StyleTab, null)));
728
1027
  };
729
1028
 
730
1029
  // src/components/editing-panel.tsx
@@ -735,8 +1034,8 @@ var EditingPanel = () => {
735
1034
  if (elements.length !== 1 || !elementType) {
736
1035
  return null;
737
1036
  }
738
- const panelTitle = __9("Edit %s", "elementor").replace("%s", elementType.title);
739
- return /* @__PURE__ */ React23.createElement(Panel, null, /* @__PURE__ */ React23.createElement(PanelHeader, null, /* @__PURE__ */ React23.createElement(PanelHeaderTitle, null, panelTitle)), /* @__PURE__ */ React23.createElement(PanelBody, null, /* @__PURE__ */ React23.createElement(ElementContext, { element: selectedElement, elementType }, /* @__PURE__ */ React23.createElement(EditingPanelTabs, null))));
1037
+ const panelTitle = __17("Edit %s", "elementor").replace("%s", elementType.title);
1038
+ return /* @__PURE__ */ React36.createElement(Panel, null, /* @__PURE__ */ React36.createElement(PanelHeader, null, /* @__PURE__ */ React36.createElement(PanelHeaderTitle, null, panelTitle)), /* @__PURE__ */ React36.createElement(PanelBody, null, /* @__PURE__ */ React36.createElement(ElementContext, { element: selectedElement, elementType }, /* @__PURE__ */ React36.createElement(EditingPanelTabs, null))));
740
1039
  };
741
1040
 
742
1041
  // src/panel.ts
@@ -781,13 +1080,314 @@ var EditingPanelHooks = () => {
781
1080
  // src/init.ts
782
1081
  import { __registerPanel as registerPanel } from "@elementor/editor-panels";
783
1082
  import { __privateBlockDataCommand as blockDataCommand } from "@elementor/editor-v1-adapters";
784
- function init() {
1083
+
1084
+ // src/dynamics/components/dynamic-selection-control.tsx
1085
+ import * as React39 from "react";
1086
+ import { useId as useId3 } from "react";
1087
+
1088
+ // src/dynamics/dynamic-control.tsx
1089
+ import * as React37 from "react";
1090
+
1091
+ // src/dynamics/hooks/use-prop-dynamic-tags.ts
1092
+ import { useMemo } from "react";
1093
+
1094
+ // src/dynamics/sync/get-elementor-config.ts
1095
+ var getElementorConfig = () => {
1096
+ const extendedWindow = window;
1097
+ return extendedWindow.elementor?.config ?? {};
1098
+ };
1099
+
1100
+ // src/dynamics/sync/get-atomic-dynamic-tags.ts
1101
+ var getAtomicDynamicTags = () => {
1102
+ const { atomicDynamicTags } = getElementorConfig();
1103
+ if (!atomicDynamicTags) {
1104
+ return null;
1105
+ }
1106
+ return {
1107
+ tags: atomicDynamicTags.tags,
1108
+ groups: atomicDynamicTags.groups
1109
+ };
1110
+ };
1111
+
1112
+ // src/props/is-transformable.ts
1113
+ import { z } from "@elementor/schema";
1114
+ var transformableSchema = z.object({
1115
+ $$type: z.string(),
1116
+ value: z.any()
1117
+ });
1118
+ var isTransformable = (value) => {
1119
+ return transformableSchema.safeParse(value).success;
1120
+ };
1121
+
1122
+ // src/dynamics/utils.ts
1123
+ var isDynamicType = (prop) => prop.key === "dynamic";
1124
+ var isDynamicPropValue = (prop) => {
1125
+ return isTransformable(prop) && prop.$$type === "dynamic";
1126
+ };
1127
+
1128
+ // src/dynamics/hooks/use-prop-dynamic-tags.ts
1129
+ var usePropDynamicTags = (propName) => {
1130
+ let categories = [];
1131
+ const { elementType } = useElementContext();
1132
+ const propSchema = elementType.propsSchema?.[propName];
1133
+ if (propSchema) {
1134
+ const propDynamicType = propSchema.additional_types.find(isDynamicType);
1135
+ categories = propDynamicType?.settings.categories || [];
1136
+ }
1137
+ return useMemo(() => getDynamicTagsByCategories(categories), [categories.join()]);
1138
+ };
1139
+ var getDynamicTagsByCategories = (categories) => {
1140
+ const dynamicTags = getAtomicDynamicTags();
1141
+ if (!categories.length || !dynamicTags?.tags) {
1142
+ return [];
1143
+ }
1144
+ const _categories = new Set(categories);
1145
+ return Object.values(dynamicTags.tags).filter(
1146
+ (dynamicTag) => dynamicTag.categories.some((category) => _categories.has(category))
1147
+ );
1148
+ };
1149
+
1150
+ // src/dynamics/hooks/use-dynamic-tag.ts
1151
+ import { useMemo as useMemo2 } from "react";
1152
+ var useDynamicTag = (propName, tagName) => {
1153
+ const dynamicTags = usePropDynamicTags(propName);
1154
+ return useMemo2(() => dynamicTags.find((tag) => tag.name === tagName) ?? null, [dynamicTags, tagName]);
1155
+ };
1156
+
1157
+ // src/dynamics/dynamic-control.tsx
1158
+ var DynamicControl = ({ bind, children }) => {
1159
+ const { value, setValue, bind: propName } = useControl();
1160
+ const { name = "", settings } = value?.value ?? {};
1161
+ const dynamicTag = useDynamicTag(propName, name);
1162
+ if (!dynamicTag) {
1163
+ throw new Error(`Dynamic tag ${name} not found`);
1164
+ }
1165
+ const defaultValue = dynamicTag.props_schema[bind]?.type.default;
1166
+ const dynamicValue = settings?.[bind] ?? defaultValue;
1167
+ const setDynamicValue = (newValue) => {
1168
+ setValue({
1169
+ $$type: "dynamic",
1170
+ value: {
1171
+ name,
1172
+ settings: {
1173
+ ...settings,
1174
+ [bind]: newValue
1175
+ }
1176
+ }
1177
+ });
1178
+ };
1179
+ return /* @__PURE__ */ React37.createElement(ControlContext.Provider, { value: { setValue: setDynamicValue, value: dynamicValue, bind } }, children);
1180
+ };
1181
+
1182
+ // src/dynamics/components/dynamic-selection-control.tsx
1183
+ import { DatabaseIcon, SettingsIcon, XIcon } from "@elementor/icons";
1184
+
1185
+ // src/dynamics/components/dynamic-selection.tsx
1186
+ import * as React38 from "react";
1187
+ import { useState as useState3, Fragment as Fragment2 } from "react";
1188
+ import { SearchIcon, PhotoIcon } from "@elementor/icons";
1189
+ import {
1190
+ Box,
1191
+ Divider as Divider3,
1192
+ InputAdornment as InputAdornment3,
1193
+ Link,
1194
+ ListSubheader,
1195
+ MenuItem as MenuItem3,
1196
+ MenuList,
1197
+ Stack as Stack12,
1198
+ TextField as TextField5,
1199
+ Typography as Typography2
1200
+ } from "@elementor/ui";
1201
+ import { __ as __18 } from "@wordpress/i18n";
1202
+ var SIZE = "tiny";
1203
+ var DynamicSelection = ({ onSelect }) => {
1204
+ const [searchValue, setSearchValue] = useState3("");
1205
+ const { groups: dynamicGroups } = getAtomicDynamicTags() || {};
1206
+ const { bind, value: dynamicValue, setValue } = useControl();
1207
+ const options2 = useFilteredOptions(bind, searchValue);
1208
+ const handleSearch = (event) => {
1209
+ setSearchValue(event.target.value);
1210
+ };
1211
+ return /* @__PURE__ */ React38.createElement(Stack12, null, /* @__PURE__ */ React38.createElement(Box, { px: 1.5, pb: 1 }, /* @__PURE__ */ React38.createElement(
1212
+ TextField5,
1213
+ {
1214
+ fullWidth: true,
1215
+ size: SIZE,
1216
+ value: searchValue,
1217
+ onChange: handleSearch,
1218
+ placeholder: __18("Search dynamic tag", "elementor"),
1219
+ InputProps: {
1220
+ startAdornment: /* @__PURE__ */ React38.createElement(InputAdornment3, { position: "start" }, /* @__PURE__ */ React38.createElement(SearchIcon, { fontSize: SIZE }))
1221
+ }
1222
+ }
1223
+ )), /* @__PURE__ */ React38.createElement(Divider3, null), /* @__PURE__ */ React38.createElement(Box, { sx: { overflowY: "auto", height: 260, width: 220 } }, options2.length > 0 ? /* @__PURE__ */ React38.createElement(MenuList, { role: "listbox", tabIndex: 0 }, options2.map(([category, items], index) => /* @__PURE__ */ React38.createElement(Fragment2, { key: index }, /* @__PURE__ */ React38.createElement(ListSubheader, { sx: { typography: "caption", color: "text.tertiary" } }, dynamicGroups?.[category]?.title || category), items.map(({ value, label: tagLabel }) => {
1224
+ const isSelected = value === dynamicValue?.value?.name;
1225
+ return /* @__PURE__ */ React38.createElement(
1226
+ MenuItem3,
1227
+ {
1228
+ key: value,
1229
+ selected: isSelected,
1230
+ autoFocus: isSelected,
1231
+ sx: { typography: "caption" },
1232
+ onClick: () => {
1233
+ setValue({ $$type: "dynamic", value: { name: value } });
1234
+ onSelect?.();
1235
+ }
1236
+ },
1237
+ tagLabel
1238
+ );
1239
+ })))) : /* @__PURE__ */ React38.createElement(Stack12, { alignItems: "center", p: 2.5, gap: 1.5 }, /* @__PURE__ */ React38.createElement(PhotoIcon, { fontSize: "large" }), /* @__PURE__ */ React38.createElement(Typography2, { align: "center", variant: "caption", color: "text.secondary" }, __18("Sorry, nothing matched", "elementor"), /* @__PURE__ */ React38.createElement("br", null), "\u201C", searchValue, "\u201D."), /* @__PURE__ */ React38.createElement(Typography2, { align: "center", variant: "caption", color: "text.secondary" }, /* @__PURE__ */ React38.createElement(
1240
+ Link,
1241
+ {
1242
+ color: "secondary",
1243
+ variant: "caption",
1244
+ component: "button",
1245
+ onClick: () => setSearchValue("")
1246
+ },
1247
+ __18("Clear the filters", "elementor")
1248
+ ), "\xA0", __18("and try again.", "elementor")))));
1249
+ };
1250
+ var useFilteredOptions = (bind, searchValue) => {
1251
+ const dynamicTags = usePropDynamicTags(bind);
1252
+ const options2 = dynamicTags.reduce((categories, { name, label, group }) => {
1253
+ const isVisible = label.toLowerCase().includes(searchValue.trim().toLowerCase());
1254
+ if (!isVisible) {
1255
+ return categories;
1256
+ }
1257
+ if (!categories.has(group)) {
1258
+ categories.set(group, []);
1259
+ }
1260
+ categories.get(group)?.push({ label, value: name });
1261
+ return categories;
1262
+ }, /* @__PURE__ */ new Map());
1263
+ return [...options2];
1264
+ };
1265
+
1266
+ // src/dynamics/components/dynamic-selection-control.tsx
1267
+ import {
1268
+ bindPopover,
1269
+ bindTrigger as bindTrigger2,
1270
+ Box as Box2,
1271
+ IconButton,
1272
+ Paper,
1273
+ Popover,
1274
+ Stack as Stack13,
1275
+ Typography as Typography3,
1276
+ UnstableTag as Tag,
1277
+ usePopupState as usePopupState2,
1278
+ Tabs as Tabs2,
1279
+ Divider as Divider4,
1280
+ useTabs as useTabs2,
1281
+ Tab as Tab2,
1282
+ TabPanel as TabPanel2
1283
+ } from "@elementor/ui";
1284
+ import { __ as __19 } from "@wordpress/i18n";
1285
+ var SIZE2 = "tiny";
1286
+ var DynamicSelectionControl = () => {
1287
+ const { bind, value, setValue } = useControl();
1288
+ const { name: tagName = "" } = value?.value || {};
1289
+ const selectionPopoverId = useId3();
1290
+ const selectionPopoverState = usePopupState2({ variant: "popover", popupId: selectionPopoverId });
1291
+ const dynamicTag = useDynamicTag(bind, tagName);
1292
+ const removeDynamicTag = () => {
1293
+ setValue(null);
1294
+ };
1295
+ if (!dynamicTag) {
1296
+ throw new Error(`Dynamic tag ${tagName} not found`);
1297
+ }
1298
+ return /* @__PURE__ */ React39.createElement(Box2, { sx: { width: "100%" } }, /* @__PURE__ */ React39.createElement(
1299
+ Tag,
1300
+ {
1301
+ fullWidth: true,
1302
+ showActionsOnHover: true,
1303
+ label: dynamicTag.label,
1304
+ startIcon: /* @__PURE__ */ React39.createElement(DatabaseIcon, { fontSize: SIZE2 }),
1305
+ ...bindTrigger2(selectionPopoverState),
1306
+ actions: /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(DynamicSettingsPopover, { dynamicTag }), /* @__PURE__ */ React39.createElement(
1307
+ IconButton,
1308
+ {
1309
+ size: SIZE2,
1310
+ onClick: removeDynamicTag,
1311
+ "aria-label": __19("Remove dynamic value", "elementor")
1312
+ },
1313
+ /* @__PURE__ */ React39.createElement(XIcon, { fontSize: SIZE2 })
1314
+ ))
1315
+ }
1316
+ ), /* @__PURE__ */ React39.createElement(
1317
+ Popover,
1318
+ {
1319
+ disablePortal: true,
1320
+ disableScrollLock: true,
1321
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
1322
+ ...bindPopover(selectionPopoverState)
1323
+ },
1324
+ /* @__PURE__ */ React39.createElement(Stack13, null, /* @__PURE__ */ React39.createElement(Stack13, { direction: "row", alignItems: "center", pl: 1.5, pr: 0.5, py: 1.5 }, /* @__PURE__ */ React39.createElement(DatabaseIcon, { fontSize: SIZE2, sx: { mr: 0.5 } }), /* @__PURE__ */ React39.createElement(Typography3, { variant: "subtitle2" }, __19("Dynamic Tags", "elementor")), /* @__PURE__ */ React39.createElement(IconButton, { size: SIZE2, sx: { ml: "auto" }, onClick: selectionPopoverState.close }, /* @__PURE__ */ React39.createElement(XIcon, { fontSize: SIZE2 }))), /* @__PURE__ */ React39.createElement(DynamicSelection, { onSelect: selectionPopoverState.close }))
1325
+ ));
1326
+ };
1327
+ var DynamicSettingsPopover = ({ dynamicTag }) => {
1328
+ const popupId = useId3();
1329
+ const settingsPopupState = usePopupState2({ variant: "popover", popupId });
1330
+ const hasDynamicSettings = !!dynamicTag.atomic_controls.length;
1331
+ if (!hasDynamicSettings) {
1332
+ return null;
1333
+ }
1334
+ return /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(
1335
+ IconButton,
1336
+ {
1337
+ size: SIZE2,
1338
+ ...bindTrigger2(settingsPopupState),
1339
+ "aria-label": __19("Settings", "elementor")
1340
+ },
1341
+ /* @__PURE__ */ React39.createElement(SettingsIcon, { fontSize: SIZE2 })
1342
+ ), /* @__PURE__ */ React39.createElement(
1343
+ Popover,
1344
+ {
1345
+ disableScrollLock: true,
1346
+ anchorOrigin: { vertical: "bottom", horizontal: "center" },
1347
+ ...bindPopover(settingsPopupState)
1348
+ },
1349
+ /* @__PURE__ */ React39.createElement(Paper, { component: Stack13, sx: { minHeight: "300px", width: "220px" } }, /* @__PURE__ */ React39.createElement(Stack13, { direction: "row", alignItems: "center", px: 1.5, pt: 2, pb: 1 }, /* @__PURE__ */ React39.createElement(DatabaseIcon, { fontSize: SIZE2, sx: { mr: 0.5 } }), /* @__PURE__ */ React39.createElement(Typography3, { variant: "subtitle2" }, dynamicTag.label), /* @__PURE__ */ React39.createElement(IconButton, { sx: { ml: "auto" }, size: SIZE2, onClick: settingsPopupState.close }, /* @__PURE__ */ React39.createElement(XIcon, { fontSize: SIZE2 }))), /* @__PURE__ */ React39.createElement(DynamicSettings, { controls: dynamicTag.atomic_controls }))
1350
+ ));
1351
+ };
1352
+ var DynamicSettings = ({ controls }) => {
1353
+ const tabs = controls.filter(({ type }) => type === "section");
1354
+ const { getTabsProps, getTabProps, getTabPanelProps } = useTabs2(0);
1355
+ if (!tabs.length) {
1356
+ return null;
1357
+ }
1358
+ return /* @__PURE__ */ React39.createElement(React39.Fragment, null, /* @__PURE__ */ React39.createElement(Tabs2, { indicatorColor: "secondary", textColor: "secondary", ...getTabsProps() }, tabs.map(({ value }, index) => /* @__PURE__ */ React39.createElement(Tab2, { key: index, label: value.label, sx: { px: 1, py: 0.5 }, ...getTabProps(index) }))), /* @__PURE__ */ React39.createElement(Divider4, null), tabs.map(({ value }, index) => {
1359
+ return /* @__PURE__ */ React39.createElement(TabPanel2, { key: index, sx: { flexGrow: 1 }, ...getTabPanelProps(index) }, /* @__PURE__ */ React39.createElement(Stack13, { gap: 1, px: 2 }, value.items.map((item) => {
1360
+ if (item.type === "control") {
1361
+ return /* @__PURE__ */ React39.createElement(Control5, { key: item.value.bind, control: item.value });
1362
+ }
1363
+ return null;
1364
+ })));
1365
+ }));
1366
+ };
1367
+ var Control5 = ({ control }) => {
1368
+ if (!getControlByType(control.type)) {
1369
+ return null;
1370
+ }
1371
+ return /* @__PURE__ */ React39.createElement(DynamicControl, { bind: control.bind }, control.label ? /* @__PURE__ */ React39.createElement(ControlLabel, null, control.label) : null, /* @__PURE__ */ React39.createElement(Control, { type: control.type, props: control.props }));
1372
+ };
1373
+
1374
+ // src/dynamics/init.ts
1375
+ var init = () => {
1376
+ replaceControl({
1377
+ component: DynamicSelectionControl,
1378
+ condition: ({ value }) => isDynamicPropValue(value)
1379
+ });
1380
+ };
1381
+
1382
+ // src/init.ts
1383
+ function init2() {
785
1384
  registerPanel(panel);
786
1385
  blockV1Panel();
787
1386
  injectIntoLogic({
788
1387
  id: "editing-panel-hooks",
789
1388
  component: EditingPanelHooks
790
1389
  });
1390
+ init();
791
1391
  }
792
1392
  var blockV1Panel = () => {
793
1393
  blockDataCommand({
@@ -797,7 +1397,7 @@ var blockV1Panel = () => {
797
1397
  };
798
1398
 
799
1399
  // src/index.ts
800
- init();
1400
+ init2();
801
1401
  export {
802
1402
  replaceControl,
803
1403
  useControl