@elementor/editor-controls 0.1.0 → 0.2.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.
package/dist/index.js CHANGED
@@ -37,9 +37,11 @@ __export(src_exports, {
37
37
  ControlActionsProvider: () => ControlActionsProvider,
38
38
  ControlLabel: () => ControlLabel,
39
39
  ControlReplacementProvider: () => ControlReplacementProvider,
40
+ ControlToggleButtonGroup: () => ControlToggleButtonGroup,
40
41
  EqualUnequalSizesControl: () => EqualUnequalSizesControl,
41
42
  FontFamilyControl: () => FontFamilyControl,
42
43
  ImageControl: () => ImageControl,
44
+ LinkControl: () => LinkControl,
43
45
  LinkedDimensionsControl: () => LinkedDimensionsControl,
44
46
  NumberControl: () => NumberControl,
45
47
  SelectControl: () => SelectControl,
@@ -48,6 +50,7 @@ __export(src_exports, {
48
50
  TextAreaControl: () => TextAreaControl,
49
51
  TextControl: () => TextControl,
50
52
  ToggleControl: () => ToggleControl,
53
+ UrlControl: () => UrlControl,
51
54
  createControlReplacement: () => createControlReplacement,
52
55
  useBoundProp: () => useBoundProp,
53
56
  useControlActions: () => useControlActions,
@@ -57,6 +60,7 @@ module.exports = __toCommonJS(src_exports);
57
60
 
58
61
  // src/controls/image-control.tsx
59
62
  var React9 = __toESM(require("react"));
63
+ var import_editor_props3 = require("@elementor/editor-props");
60
64
  var import_ui6 = require("@elementor/ui");
61
65
  var import_i18n2 = require("@wordpress/i18n");
62
66
 
@@ -67,12 +71,26 @@ var BoundPropContext = (0, import_react.createContext)(null);
67
71
  var BoundPropProvider = ({ children, value, setValue, bind }) => {
68
72
  return /* @__PURE__ */ React.createElement(BoundPropContext.Provider, { value: { value, setValue, bind } }, children);
69
73
  };
70
- function useBoundProp(defaultValue) {
74
+ function useBoundProp(propTypeUtil) {
71
75
  const boundPropContext = (0, import_react.useContext)(BoundPropContext);
72
76
  if (!boundPropContext) {
73
- throw new Error("useBoundProp must be used within a BoundPropContext");
77
+ throw new Error("useBoundProp must be used within a BoundPropProvider");
74
78
  }
75
- return { ...boundPropContext, value: boundPropContext.value ?? defaultValue };
79
+ if (!propTypeUtil) {
80
+ return boundPropContext;
81
+ }
82
+ function setValue(value2, options) {
83
+ if (value2 === null) {
84
+ return boundPropContext.setValue(null);
85
+ }
86
+ return boundPropContext.setValue(propTypeUtil?.create(value2, options));
87
+ }
88
+ const value = propTypeUtil.extract(boundPropContext.value);
89
+ return {
90
+ ...boundPropContext,
91
+ setValue,
92
+ value
93
+ };
76
94
  }
77
95
 
78
96
  // src/components/control-label.tsx
@@ -132,6 +150,7 @@ function createControl(Component, { supportsReplacements = true } = {}) {
132
150
 
133
151
  // src/controls/image-media-control.tsx
134
152
  var React7 = __toESM(require("react"));
153
+ var import_editor_props = require("@elementor/editor-props");
135
154
  var import_icons = require("@elementor/icons");
136
155
  var import_ui4 = require("@elementor/ui");
137
156
  var import_wp_media = require("@elementor/wp-media");
@@ -173,8 +192,8 @@ function ControlActions({ children }) {
173
192
 
174
193
  // src/controls/image-media-control.tsx
175
194
  var ImageMediaControl = createControl(() => {
176
- const { value, setValue } = useBoundProp();
177
- const { id, url } = value?.value ?? {};
195
+ const { value, setValue } = useBoundProp(import_editor_props.imageSrcPropTypeUtil);
196
+ const { id, url } = value ?? {};
178
197
  const { data: attachment, isFetching } = (0, import_wp_media.useWpMediaAttachment)(id?.value || null);
179
198
  const src = attachment?.url ?? url;
180
199
  const { open } = (0, import_wp_media.useWpMediaFrame)({
@@ -183,14 +202,11 @@ var ImageMediaControl = createControl(() => {
183
202
  selected: id?.value || null,
184
203
  onSelect: (selectedAttachment) => {
185
204
  setValue({
186
- $$type: "image-src",
187
- value: {
188
- id: {
189
- $$type: "image-attachment-id",
190
- value: selectedAttachment.id
191
- },
192
- url: null
193
- }
205
+ id: {
206
+ $$type: "image-attachment-id",
207
+ value: selectedAttachment.id
208
+ },
209
+ url: null
194
210
  });
195
211
  }
196
212
  });
@@ -218,9 +234,10 @@ var ImageMediaControl = createControl(() => {
218
234
 
219
235
  // src/controls/select-control.tsx
220
236
  var React8 = __toESM(require("react"));
237
+ var import_editor_props2 = require("@elementor/editor-props");
221
238
  var import_ui5 = require("@elementor/ui");
222
239
  var SelectControl = createControl(({ options }) => {
223
- const { value, setValue } = useBoundProp();
240
+ const { value, setValue } = useBoundProp(import_editor_props2.stringPropTypeUtil);
224
241
  const handleChange = (event) => {
225
242
  setValue(event.target.value);
226
243
  };
@@ -229,24 +246,18 @@ var SelectControl = createControl(({ options }) => {
229
246
 
230
247
  // src/controls/image-control.tsx
231
248
  var ImageControl = createControl((props) => {
232
- const { value, setValue } = useBoundProp();
233
- const { src, size } = value?.value || {};
249
+ const { value, setValue } = useBoundProp(import_editor_props3.imagePropTypeUtil);
250
+ const { src, size } = value || {};
234
251
  const setImageSrc = (newValue) => {
235
252
  setValue({
236
- $$type: "image",
237
- value: {
238
- src: newValue,
239
- size
240
- }
253
+ src: newValue,
254
+ size
241
255
  });
242
256
  };
243
257
  const setImageSize = (newValue) => {
244
258
  setValue({
245
- $$type: "image",
246
- value: {
247
- src,
248
- size: newValue
249
- }
259
+ src,
260
+ size: newValue
250
261
  });
251
262
  };
252
263
  return /* @__PURE__ */ React9.createElement(import_ui6.Stack, { gap: 1.5 }, /* @__PURE__ */ React9.createElement(BoundPropProvider, { value: src, setValue: setImageSrc, bind: "src" }, /* @__PURE__ */ React9.createElement(ImageMediaControl, null)), /* @__PURE__ */ React9.createElement(BoundPropProvider, { value: size, setValue: setImageSize, bind: "size" }, /* @__PURE__ */ React9.createElement(import_ui6.Grid, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap" }, /* @__PURE__ */ React9.createElement(import_ui6.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React9.createElement(ControlLabel, null, " ", (0, import_i18n2.__)("Image Resolution", "elementor"))), /* @__PURE__ */ React9.createElement(import_ui6.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React9.createElement(SelectControl, { options: props.sizes })))));
@@ -254,18 +265,20 @@ var ImageControl = createControl((props) => {
254
265
 
255
266
  // src/controls/text-control.tsx
256
267
  var React10 = __toESM(require("react"));
268
+ var import_editor_props4 = require("@elementor/editor-props");
257
269
  var import_ui7 = require("@elementor/ui");
258
270
  var TextControl = createControl(({ placeholder }) => {
259
- const { value, setValue } = useBoundProp("");
271
+ const { value, setValue } = useBoundProp(import_editor_props4.stringPropTypeUtil);
260
272
  const handleChange = (event) => setValue(event.target.value);
261
273
  return /* @__PURE__ */ React10.createElement(ControlActions, null, /* @__PURE__ */ React10.createElement(import_ui7.TextField, { size: "tiny", fullWidth: true, value, onChange: handleChange, placeholder }));
262
274
  });
263
275
 
264
276
  // src/controls/text-area-control.tsx
265
277
  var React11 = __toESM(require("react"));
278
+ var import_editor_props5 = require("@elementor/editor-props");
266
279
  var import_ui8 = require("@elementor/ui");
267
280
  var TextAreaControl = createControl(({ placeholder }) => {
268
- const { value, setValue } = useBoundProp();
281
+ const { value, setValue } = useBoundProp(import_editor_props5.stringPropTypeUtil);
269
282
  const handleChange = (event) => {
270
283
  setValue(event.target.value);
271
284
  };
@@ -285,6 +298,7 @@ var TextAreaControl = createControl(({ placeholder }) => {
285
298
 
286
299
  // src/controls/size-control.tsx
287
300
  var React13 = __toESM(require("react"));
301
+ var import_editor_props6 = require("@elementor/editor-props");
288
302
  var import_ui10 = require("@elementor/ui");
289
303
 
290
304
  // src/components/text-field-inner-selection.tsx
@@ -348,7 +362,7 @@ var useSyncExternalState = ({
348
362
  if (persistWhen(internalValue)) {
349
363
  return internalValue;
350
364
  }
351
- return void 0;
365
+ return null;
352
366
  }
353
367
  function toInternal(externalValue, internalValue) {
354
368
  if (!externalValue) {
@@ -356,7 +370,7 @@ var useSyncExternalState = ({
356
370
  }
357
371
  return externalValue;
358
372
  }
359
- const [internal, setInternal] = (0, import_react5.useState)(toInternal(external, void 0));
373
+ const [internal, setInternal] = (0, import_react5.useState)(toInternal(external, null));
360
374
  (0, import_react5.useEffect)(() => {
361
375
  setInternal((prevInternal) => toInternal(external, prevInternal));
362
376
  }, [external]);
@@ -374,33 +388,24 @@ var defaultUnits = ["px", "%", "em", "rem", "vw", "vh"];
374
388
  var defaultUnit = "px";
375
389
  var defaultSize = NaN;
376
390
  var SizeControl = createControl(({ units: units2 = defaultUnits, placeholder, startIcon }) => {
377
- const { value, setValue } = useBoundProp();
391
+ const { value, setValue } = useBoundProp(import_editor_props6.sizePropTypeUtil);
378
392
  const [state, setState] = useSyncExternalState({
379
393
  external: value,
380
394
  setExternal: setValue,
381
- persistWhen: (controlValue) => !!controlValue?.value?.size || controlValue?.value?.size === 0,
382
- fallback: (controlValue) => ({
383
- $$type: "size",
384
- value: { unit: controlValue?.value?.unit || defaultUnit, size: defaultSize }
385
- })
395
+ persistWhen: (controlValue) => !!controlValue?.size || controlValue?.size === 0,
396
+ fallback: (controlValue) => ({ unit: controlValue?.unit || defaultUnit, size: defaultSize })
386
397
  });
387
398
  const handleUnitChange = (unit) => {
388
399
  setState((prev) => ({
389
- ...prev,
390
- value: {
391
- ...prev.value,
392
- unit
393
- }
400
+ size: prev?.size ?? defaultSize,
401
+ unit
394
402
  }));
395
403
  };
396
404
  const handleSizeChange = (event) => {
397
405
  const { value: size } = event.target;
398
406
  setState((prev) => ({
399
407
  ...prev,
400
- value: {
401
- ...prev.value,
402
- size: size || size === "0" ? parseFloat(size) : defaultSize
403
- }
408
+ size: size || size === "0" ? parseFloat(size) : defaultSize
404
409
  }));
405
410
  };
406
411
  return /* @__PURE__ */ React13.createElement(ControlActions, null, /* @__PURE__ */ React13.createElement(
@@ -411,13 +416,13 @@ var SizeControl = createControl(({ units: units2 = defaultUnits, placeholder, st
411
416
  {
412
417
  options: units2,
413
418
  onClick: handleUnitChange,
414
- value: state.value.unit ?? defaultUnit
419
+ value: state?.unit ?? defaultUnit
415
420
  }
416
421
  ),
417
422
  placeholder,
418
423
  startAdornment: startIcon ?? /* @__PURE__ */ React13.createElement(import_ui10.InputAdornment, { position: "start" }, startIcon),
419
424
  type: "number",
420
- value: Number.isNaN(state.value.size) ? "" : state.value.size,
425
+ value: Number.isNaN(state?.size) ? "" : state?.size,
421
426
  onChange: handleSizeChange
422
427
  }
423
428
  ));
@@ -425,80 +430,48 @@ var SizeControl = createControl(({ units: units2 = defaultUnits, placeholder, st
425
430
 
426
431
  // src/controls/stroke-control.tsx
427
432
  var React15 = __toESM(require("react"));
433
+ var import_editor_props8 = require("@elementor/editor-props");
428
434
  var import_ui12 = require("@elementor/ui");
429
435
  var import_i18n3 = require("@wordpress/i18n");
430
436
 
431
437
  // src/controls/color-control.tsx
432
438
  var React14 = __toESM(require("react"));
439
+ var import_editor_props7 = require("@elementor/editor-props");
433
440
  var import_ui11 = require("@elementor/ui");
434
441
  var ColorControl = createControl(
435
442
  (props) => {
436
- const { value, setValue } = useBoundProp();
443
+ const { value, setValue } = useBoundProp(import_editor_props7.colorPropTypeUtil);
437
444
  const handleChange = (selectedColor) => {
438
- setValue({
439
- $$type: "color",
440
- value: selectedColor
441
- });
445
+ setValue(selectedColor);
442
446
  };
443
- return /* @__PURE__ */ React14.createElement(ControlActions, null, /* @__PURE__ */ React14.createElement(
444
- import_ui11.UnstableColorField,
445
- {
446
- size: "tiny",
447
- ...props,
448
- value: value?.value,
449
- onChange: handleChange,
450
- fullWidth: true
451
- }
452
- ));
447
+ return /* @__PURE__ */ React14.createElement(ControlActions, null, /* @__PURE__ */ React14.createElement(import_ui11.UnstableColorField, { size: "tiny", ...props, value, onChange: handleChange, fullWidth: true }));
453
448
  }
454
449
  );
455
450
 
456
451
  // src/controls/stroke-control.tsx
457
- var defaultStrokeControlValue = {
458
- $$type: "stroke",
459
- value: {
460
- color: {
461
- $$type: "color",
462
- value: "#000000"
463
- },
464
- width: {
465
- $$type: "size",
466
- value: {
467
- unit: "px",
468
- size: NaN
469
- }
470
- }
471
- }
472
- };
473
452
  var units = ["px", "em", "rem"];
474
453
  var StrokeControl = createControl(() => {
475
- const { value, setValue } = useBoundProp(defaultStrokeControlValue);
454
+ const { value, setValue } = useBoundProp(import_editor_props8.strokePropTypeUtil);
476
455
  const setStrokeWidth = (newValue) => {
477
456
  const updatedValue = {
478
- ...value?.value ?? defaultStrokeControlValue.value,
457
+ ...value,
479
458
  width: newValue
480
459
  };
481
- setValue({
482
- $$type: "stroke",
483
- value: updatedValue
484
- });
460
+ setValue(updatedValue);
485
461
  };
486
462
  const setStrokeColor = (newValue) => {
487
463
  const updatedValue = {
488
- ...value?.value ?? defaultStrokeControlValue.value,
464
+ ...value,
489
465
  color: newValue
490
466
  };
491
- setValue({
492
- $$type: "stroke",
493
- value: updatedValue
494
- });
467
+ setValue(updatedValue);
495
468
  };
496
469
  return /* @__PURE__ */ React15.createElement(import_ui12.Stack, { gap: 1.5 }, /* @__PURE__ */ React15.createElement(
497
470
  Control,
498
471
  {
499
472
  bind: "width",
500
473
  label: (0, import_i18n3.__)("Stroke Width", "elementor"),
501
- value: value?.value.width ?? defaultStrokeControlValue.value.width,
474
+ value: value?.width,
502
475
  setValue: setStrokeWidth
503
476
  },
504
477
  /* @__PURE__ */ React15.createElement(SizeControl, { units })
@@ -507,22 +480,17 @@ var StrokeControl = createControl(() => {
507
480
  {
508
481
  bind: "color",
509
482
  label: (0, import_i18n3.__)("Stroke Color", "elementor"),
510
- value: value?.value.color ?? defaultStrokeControlValue.value.color,
483
+ value: value?.color,
511
484
  setValue: setStrokeColor
512
485
  },
513
486
  /* @__PURE__ */ React15.createElement(ColorControl, null)
514
487
  ));
515
488
  });
516
- var Control = ({
517
- bind,
518
- value,
519
- setValue,
520
- label,
521
- children
522
- }) => /* @__PURE__ */ React15.createElement(BoundPropProvider, { bind, value, setValue }, /* @__PURE__ */ React15.createElement(import_ui12.Grid, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap" }, /* @__PURE__ */ React15.createElement(import_ui12.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React15.createElement(ControlLabel, null, label)), /* @__PURE__ */ React15.createElement(import_ui12.Grid, { item: true, xs: 6 }, children)));
489
+ var Control = ({ bind, value, setValue, label, children }) => /* @__PURE__ */ React15.createElement(BoundPropProvider, { bind, value, setValue }, /* @__PURE__ */ React15.createElement(import_ui12.Grid, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap" }, /* @__PURE__ */ React15.createElement(import_ui12.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React15.createElement(ControlLabel, null, label)), /* @__PURE__ */ React15.createElement(import_ui12.Grid, { item: true, xs: 6 }, children)));
523
490
 
524
491
  // src/controls/box-shadow-repeater-control.tsx
525
492
  var React17 = __toESM(require("react"));
493
+ var import_editor_props9 = require("@elementor/editor-props");
526
494
  var import_ui14 = require("@elementor/ui");
527
495
  var import_i18n5 = require("@wordpress/i18n");
528
496
 
@@ -656,18 +624,14 @@ var RepeaterItem = ({
656
624
 
657
625
  // src/controls/box-shadow-repeater-control.tsx
658
626
  var BoxShadowRepeaterControl = createControl(() => {
659
- const { value, setValue } = useBoundProp();
660
- const boxShadowValues = value?.value;
627
+ const { value: boxShadowValues, setValue } = useBoundProp(import_editor_props9.boxShadowPropTypeUtil);
661
628
  const setBoxShadow = (newValue) => {
662
- setValue({
663
- $$type: "box-shadow",
664
- value: newValue
665
- });
629
+ setValue(newValue);
666
630
  };
667
631
  return /* @__PURE__ */ React17.createElement(
668
632
  Repeater,
669
633
  {
670
- values: boxShadowValues,
634
+ values: boxShadowValues ?? [],
671
635
  setValues: setBoxShadow,
672
636
  label: (0, import_i18n5.__)("Box shadow", "elementor"),
673
637
  itemSettings: {
@@ -822,16 +786,13 @@ var initialShadow = {
822
786
 
823
787
  // src/controls/background-overlay-repeater-control.tsx
824
788
  var React18 = __toESM(require("react"));
789
+ var import_editor_props10 = require("@elementor/editor-props");
825
790
  var import_ui15 = require("@elementor/ui");
826
791
  var import_i18n6 = require("@wordpress/i18n");
827
792
  var BackgroundOverlayRepeaterControl = createControl(() => {
828
- const { value, setValue } = useBoundProp();
829
- const colorOverlayValues = value?.value;
793
+ const { value: colorOverlayValues, setValue } = useBoundProp(import_editor_props10.backgroundImagePropTypeUtil);
830
794
  const setColorOverlay = (newValue) => {
831
- setValue({
832
- $$type: "background-image",
833
- value: newValue
834
- });
795
+ setValue(newValue);
835
796
  };
836
797
  return /* @__PURE__ */ React18.createElement(
837
798
  Repeater,
@@ -893,6 +854,7 @@ var initialGradient = {
893
854
 
894
855
  // src/controls/toggle-control.tsx
895
856
  var React20 = __toESM(require("react"));
857
+ var import_editor_props11 = require("@elementor/editor-props");
896
858
 
897
859
  // src/components/control-toggle-button-group.tsx
898
860
  var React19 = __toESM(require("react"));
@@ -909,28 +871,41 @@ var ControlToggleButtonGroup = ({
909
871
  exclusive = false,
910
872
  fullWidth = false
911
873
  }) => {
874
+ const isRtl = "rtl" === (0, import_ui16.useTheme)().direction;
912
875
  const handleChange = (_, newValue) => {
913
876
  onChange(newValue);
914
877
  };
915
- return /* @__PURE__ */ React19.createElement(StyledToggleButtonGroup, { justify, value, onChange: handleChange, exclusive }, items.map(
916
- ({ label, value: buttonValue, renderContent: Content, showTooltip }) => showTooltip ? /* @__PURE__ */ React19.createElement(import_ui16.Tooltip, { key: buttonValue, title: label, disableFocusListener: true, placement: "top" }, /* @__PURE__ */ React19.createElement(import_ui16.ToggleButton, { value: buttonValue, "aria-label": label, size, fullWidth }, /* @__PURE__ */ React19.createElement(Content, { size }))) : /* @__PURE__ */ React19.createElement(
917
- import_ui16.ToggleButton,
918
- {
919
- key: buttonValue,
920
- value: buttonValue,
921
- "aria-label": label,
922
- size,
923
- fullWidth
924
- },
925
- /* @__PURE__ */ React19.createElement(Content, { size })
878
+ return /* @__PURE__ */ React19.createElement(
879
+ StyledToggleButtonGroup,
880
+ {
881
+ justify,
882
+ value,
883
+ onChange: handleChange,
884
+ exclusive,
885
+ sx: {
886
+ direction: isRtl ? "rtl /* @noflip */" : "ltr /* @noflip */"
887
+ }
888
+ },
889
+ items.map(
890
+ ({ label, value: buttonValue, renderContent: Content, showTooltip }) => showTooltip ? /* @__PURE__ */ React19.createElement(import_ui16.Tooltip, { key: buttonValue, title: label, disableFocusListener: true, placement: "top" }, /* @__PURE__ */ React19.createElement(import_ui16.ToggleButton, { value: buttonValue, "aria-label": label, size, fullWidth }, /* @__PURE__ */ React19.createElement(Content, { size }))) : /* @__PURE__ */ React19.createElement(
891
+ import_ui16.ToggleButton,
892
+ {
893
+ key: buttonValue,
894
+ value: buttonValue,
895
+ "aria-label": label,
896
+ size,
897
+ fullWidth
898
+ },
899
+ /* @__PURE__ */ React19.createElement(Content, { size })
900
+ )
926
901
  )
927
- ));
902
+ );
928
903
  };
929
904
 
930
905
  // src/controls/toggle-control.tsx
931
906
  var ToggleControl = createControl(
932
907
  ({ options, fullWidth = false, size = "tiny" }) => {
933
- const { value, setValue } = useBoundProp();
908
+ const { value, setValue } = useBoundProp(import_editor_props11.stringPropTypeUtil);
934
909
  const handleToggle = (option) => {
935
910
  setValue(option);
936
911
  };
@@ -938,7 +913,7 @@ var ToggleControl = createControl(
938
913
  ControlToggleButtonGroup,
939
914
  {
940
915
  items: options,
941
- value: value || null,
916
+ value: value ?? null,
942
917
  onChange: handleToggle,
943
918
  exclusive: true,
944
919
  fullWidth,
@@ -950,76 +925,89 @@ var ToggleControl = createControl(
950
925
 
951
926
  // src/controls/number-control.tsx
952
927
  var React21 = __toESM(require("react"));
928
+ var import_editor_props12 = require("@elementor/editor-props");
953
929
  var import_ui17 = require("@elementor/ui");
954
- var isEmptyOrNaN = (value) => value === void 0 || value === "" || Number.isNaN(Number(value));
955
- var NumberControl = createControl(({ placeholder }) => {
956
- const { value, setValue } = useBoundProp();
957
- const handleChange = (event) => {
958
- const eventValue = event.target.value;
959
- setValue(isEmptyOrNaN(eventValue) ? void 0 : Number(eventValue));
960
- };
961
- return /* @__PURE__ */ React21.createElement(ControlActions, null, /* @__PURE__ */ React21.createElement(
962
- import_ui17.TextField,
963
- {
964
- size: "tiny",
965
- type: "number",
966
- fullWidth: true,
967
- value: isEmptyOrNaN(value) ? "" : value,
968
- onChange: handleChange,
969
- placeholder
970
- }
971
- ));
972
- });
930
+ var isEmptyOrNaN = (value) => value === null || value === void 0 || value === "" || Number.isNaN(Number(value));
931
+ var NumberControl = createControl(
932
+ ({
933
+ placeholder,
934
+ max = Number.MAX_VALUE,
935
+ min = -Number.MAX_VALUE,
936
+ step = 1,
937
+ shouldForceInt = false
938
+ }) => {
939
+ const { value, setValue } = useBoundProp(import_editor_props12.numberPropTypeUtil);
940
+ const handleChange = (event) => {
941
+ const eventValue = event.target.value;
942
+ if (isEmptyOrNaN(eventValue)) {
943
+ setValue(null);
944
+ return;
945
+ }
946
+ const formattedValue = shouldForceInt ? +parseInt(eventValue) : Number(eventValue);
947
+ setValue(Math.min(Math.max(formattedValue, min), max));
948
+ };
949
+ return /* @__PURE__ */ React21.createElement(ControlActions, null, /* @__PURE__ */ React21.createElement(
950
+ import_ui17.TextField,
951
+ {
952
+ size: "tiny",
953
+ type: "number",
954
+ fullWidth: true,
955
+ value: isEmptyOrNaN(value) ? "" : value,
956
+ onChange: handleChange,
957
+ placeholder,
958
+ inputProps: { step }
959
+ }
960
+ ));
961
+ }
962
+ );
973
963
 
974
964
  // src/controls/equal-unequal-sizes-control.tsx
975
965
  var React22 = __toESM(require("react"));
976
966
  var import_react7 = require("react");
967
+ var import_editor_props13 = require("@elementor/editor-props");
977
968
  var import_ui18 = require("@elementor/ui");
978
969
  var import_i18n7 = require("@wordpress/i18n");
979
- function hasMixedSizes(values) {
970
+ var isEqualSizes = (values, items) => {
971
+ if (values.length !== items.length) {
972
+ return false;
973
+ }
980
974
  const [firstValue, ...restValues] = values;
981
- return restValues.some(
982
- (value) => value?.value?.size !== firstValue?.value?.size || value?.value?.unit !== firstValue?.value?.unit
975
+ return restValues.every(
976
+ (value) => value.value?.size === firstValue.value?.size && value.value?.unit === firstValue.value?.unit
983
977
  );
984
- }
985
- function getMultiSizeProps(controlValue, items) {
986
- return controlValue?.$$type === "size" ? items.reduce((values, item) => {
987
- const { bind } = item;
988
- values[bind] = controlValue;
989
- return values;
990
- }, {}) : controlValue?.value ?? {};
991
- }
992
- function EqualUnequalSizesControl({ label, icon, items, multiSizeType }) {
978
+ };
979
+ function EqualUnequalSizesControl({
980
+ label,
981
+ icon,
982
+ items,
983
+ multiSizePropTypeUtil
984
+ }) {
993
985
  const popupId = (0, import_react7.useId)();
994
986
  const controlRef = (0, import_react7.useRef)(null);
995
- const { value: controlValue, setValue: setControlValue } = useBoundProp();
996
- const setMultiSizeValue = (newValue) => {
997
- setControlValue({ $$type: multiSizeType, value: newValue });
987
+ const popupState = (0, import_ui18.usePopupState)({ variant: "popover", popupId });
988
+ const { value: sizeValue, setValue: setSizeValue } = useBoundProp(import_editor_props13.sizePropTypeUtil);
989
+ const { value: multiSizeValue, setValue: setMultiSizeValue } = useBoundProp(multiSizePropTypeUtil);
990
+ const splitEqualValue = () => {
991
+ return items.reduce((acc, item) => ({ ...acc, [item.bind]: import_editor_props13.sizePropTypeUtil.create(sizeValue) }), {});
998
992
  };
999
- const mappedValues = getMultiSizeProps(controlValue, items);
1000
993
  const setNestedProp = (item, newValue) => {
1001
- const { bind } = item;
1002
994
  const newMappedValues = {
1003
- ...mappedValues,
1004
- [bind]: newValue
995
+ ...multiSizeValue ?? splitEqualValue(),
996
+ [item.bind]: newValue
1005
997
  };
1006
- const sizes = Object.values(newMappedValues);
1007
- const isMixed = hasMixedSizes(sizes);
1008
- if (isMixed) {
1009
- setMultiSizeValue(newMappedValues);
1010
- return;
998
+ const isEqual = isEqualSizes(Object.values(newMappedValues), items);
999
+ if (isEqual) {
1000
+ return setSizeValue(newValue?.value);
1011
1001
  }
1012
- setControlValue(newValue);
1002
+ setMultiSizeValue(newMappedValues);
1013
1003
  };
1014
- const popupState = (0, import_ui18.usePopupState)({
1015
- variant: "popover",
1016
- popupId
1017
- });
1018
1004
  return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(import_ui18.Grid, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap", ref: controlRef }, /* @__PURE__ */ React22.createElement(import_ui18.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React22.createElement(ControlLabel, null, label)), /* @__PURE__ */ React22.createElement(import_ui18.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React22.createElement(
1019
- EqualValuesControl,
1005
+ EqualSizeControl,
1020
1006
  {
1021
- value: mappedValues,
1022
- setValue: setControlValue,
1007
+ items,
1008
+ value: sizeValue,
1009
+ multiSizeValue,
1010
+ setValue: setSizeValue,
1023
1011
  iconButton: /* @__PURE__ */ React22.createElement(
1024
1012
  import_ui18.ToggleButton,
1025
1013
  {
@@ -1051,79 +1039,86 @@ function EqualUnequalSizesControl({ label, icon, items, multiSizeType }) {
1051
1039
  }
1052
1040
  },
1053
1041
  /* @__PURE__ */ React22.createElement(import_ui18.Stack, { gap: 1.5 }, /* @__PURE__ */ React22.createElement(import_ui18.Grid, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap" }, /* @__PURE__ */ React22.createElement(
1054
- NestedValueControl,
1042
+ MultiSizeValueControl,
1055
1043
  {
1056
1044
  item: items[0],
1057
- value: mappedValues,
1058
- setNestedProp
1045
+ value: multiSizeValue,
1046
+ setNestedProp,
1047
+ splitEqualValue
1059
1048
  }
1060
1049
  ), /* @__PURE__ */ React22.createElement(
1061
- NestedValueControl,
1050
+ MultiSizeValueControl,
1062
1051
  {
1063
1052
  item: items[1],
1064
- value: mappedValues,
1065
- setNestedProp
1053
+ value: multiSizeValue,
1054
+ setNestedProp,
1055
+ splitEqualValue
1066
1056
  }
1067
1057
  )), /* @__PURE__ */ React22.createElement(import_ui18.Grid, { container: true, gap: 2, alignItems: "center", flexWrap: "nowrap" }, /* @__PURE__ */ React22.createElement(
1068
- NestedValueControl,
1058
+ MultiSizeValueControl,
1069
1059
  {
1070
1060
  item: items[3],
1071
- value: mappedValues,
1072
- setNestedProp
1061
+ value: multiSizeValue,
1062
+ setNestedProp,
1063
+ splitEqualValue
1073
1064
  }
1074
1065
  ), /* @__PURE__ */ React22.createElement(
1075
- NestedValueControl,
1066
+ MultiSizeValueControl,
1076
1067
  {
1077
1068
  item: items[2],
1078
- value: mappedValues,
1079
- setNestedProp
1069
+ value: multiSizeValue,
1070
+ setNestedProp,
1071
+ splitEqualValue
1080
1072
  }
1081
1073
  )))
1082
1074
  ));
1083
1075
  }
1084
- var NestedValueControl = ({
1076
+ var MultiSizeValueControl = ({
1085
1077
  item,
1086
1078
  value,
1087
- setNestedProp
1079
+ setNestedProp,
1080
+ splitEqualValue
1088
1081
  }) => {
1089
- const { bind } = item;
1090
- const nestedValue = value?.[bind] ? value[bind] : void 0;
1091
- return /* @__PURE__ */ React22.createElement(
1092
- BoundPropProvider,
1093
- {
1094
- bind: "",
1095
- setValue: (val) => setNestedProp(item, val),
1096
- value: nestedValue
1097
- },
1098
- /* @__PURE__ */ React22.createElement(import_ui18.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React22.createElement(import_ui18.Grid, { container: true, gap: 1, alignItems: "center" }, /* @__PURE__ */ React22.createElement(import_ui18.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React22.createElement(ControlLabel, null, item.label)), /* @__PURE__ */ React22.createElement(import_ui18.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React22.createElement(SizeControl, { startIcon: item.icon }))))
1099
- );
1082
+ const handleChange = (val) => setNestedProp(item, val);
1083
+ const getMultiSizeValues = () => {
1084
+ if (value) {
1085
+ return value?.[item.bind] ?? null;
1086
+ }
1087
+ return splitEqualValue()?.[item.bind] ?? null;
1088
+ };
1089
+ return /* @__PURE__ */ React22.createElement(BoundPropProvider, { bind: "", setValue: handleChange, value: getMultiSizeValues() }, /* @__PURE__ */ React22.createElement(import_ui18.Grid, { item: true, xs: 6 }, /* @__PURE__ */ React22.createElement(import_ui18.Grid, { container: true, gap: 1, alignItems: "center" }, /* @__PURE__ */ React22.createElement(import_ui18.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React22.createElement(ControlLabel, null, item.label)), /* @__PURE__ */ React22.createElement(import_ui18.Grid, { item: true, xs: 12 }, /* @__PURE__ */ React22.createElement(SizeControl, { startIcon: item.icon })))));
1100
1090
  };
1101
- var EqualValuesControl = ({
1091
+ var EqualSizeControl = ({
1102
1092
  value,
1093
+ items,
1103
1094
  setValue,
1104
- iconButton
1095
+ iconButton,
1096
+ multiSizeValue
1105
1097
  }) => {
1106
- const values = Object.values(value ?? {});
1107
- const isMixed = hasMixedSizes(values);
1108
- return /* @__PURE__ */ React22.createElement(
1109
- BoundPropProvider,
1110
- {
1111
- bind: "",
1112
- setValue: (val) => setValue(val),
1113
- value: isMixed ? void 0 : values[0]
1114
- },
1115
- /* @__PURE__ */ React22.createElement(import_ui18.Stack, { direction: "row", alignItems: "center", gap: 1 }, /* @__PURE__ */ React22.createElement(SizeControl, { placeholder: (0, import_i18n7.__)("MIXED", "elementor") }), iconButton)
1116
- );
1098
+ const handleChange = (newValue) => {
1099
+ setValue(newValue.value);
1100
+ };
1101
+ const getDisplayValue = () => {
1102
+ if (value) {
1103
+ return import_editor_props13.sizePropTypeUtil.create(value);
1104
+ }
1105
+ const multiValues = Object.values(multiSizeValue ?? {});
1106
+ if (isEqualSizes(multiValues, items)) {
1107
+ return import_editor_props13.sizePropTypeUtil.create(multiValues[0].value);
1108
+ }
1109
+ };
1110
+ return /* @__PURE__ */ React22.createElement(BoundPropProvider, { bind: "", setValue: handleChange, value: getDisplayValue() ?? null }, /* @__PURE__ */ React22.createElement(import_ui18.Stack, { direction: "row", alignItems: "center", gap: 1 }, /* @__PURE__ */ React22.createElement(SizeControl, { placeholder: (0, import_i18n7.__)("MIXED", "elementor") }), iconButton));
1117
1111
  };
1118
1112
 
1119
1113
  // src/controls/linked-dimensions-control.tsx
1120
1114
  var React23 = __toESM(require("react"));
1115
+ var import_editor_props14 = require("@elementor/editor-props");
1121
1116
  var import_icons3 = require("@elementor/icons");
1122
1117
  var import_ui19 = require("@elementor/ui");
1123
1118
  var import_i18n8 = require("@wordpress/i18n");
1124
1119
  var LinkedDimensionsControl = createControl(({ label }) => {
1125
- const { value, setValue } = useBoundProp();
1126
- const { top, right, bottom, left, isLinked = true } = value?.value || {};
1120
+ const { value, setValue } = useBoundProp(import_editor_props14.linkedDimensionsPropTypeUtil);
1121
+ const { top, right, bottom, left, isLinked = true } = value || {};
1127
1122
  const setLinkedValue = (position, newValue) => {
1128
1123
  const updatedValue = {
1129
1124
  isLinked,
@@ -1133,10 +1128,7 @@ var LinkedDimensionsControl = createControl(({ label }) => {
1133
1128
  left: isLinked ? newValue : left,
1134
1129
  [position]: newValue
1135
1130
  };
1136
- setValue({
1137
- $$type: "linked-dimensions",
1138
- value: updatedValue
1139
- });
1131
+ setValue(updatedValue);
1140
1132
  };
1141
1133
  const toggleLinked = () => {
1142
1134
  const updatedValue = {
@@ -1146,10 +1138,7 @@ var LinkedDimensionsControl = createControl(({ label }) => {
1146
1138
  bottom: !isLinked ? top : bottom,
1147
1139
  left: !isLinked ? top : left
1148
1140
  };
1149
- setValue({
1150
- $$type: "linked-dimensions",
1151
- value: updatedValue
1152
- });
1141
+ setValue(updatedValue);
1153
1142
  };
1154
1143
  const LinkedIcon = isLinked ? import_icons3.LinkIcon : import_icons3.DetachIcon;
1155
1144
  return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(import_ui19.Stack, { direction: "row", gap: 2, flexWrap: "nowrap" }, /* @__PURE__ */ React23.createElement(ControlLabel, null, label), /* @__PURE__ */ React23.createElement(
@@ -1207,6 +1196,7 @@ var Control4 = ({
1207
1196
  // src/controls/font-family-control.tsx
1208
1197
  var import_react8 = require("react");
1209
1198
  var React24 = __toESM(require("react"));
1199
+ var import_editor_props15 = require("@elementor/editor-props");
1210
1200
  var import_icons4 = require("@elementor/icons");
1211
1201
  var import_ui20 = require("@elementor/ui");
1212
1202
  var import_i18n10 = require("@wordpress/i18n");
@@ -1244,8 +1234,8 @@ var useFilteredFontFamilies = (fontFamilies, searchValue) => {
1244
1234
  // src/controls/font-family-control.tsx
1245
1235
  var SIZE2 = "tiny";
1246
1236
  var FontFamilyControl = createControl(({ fontFamilies }) => {
1247
- const { value: fontFamily, setValue: setFontFamily } = useBoundProp();
1248
1237
  const [searchValue, setSearchValue] = (0, import_react8.useState)("");
1238
+ const { value: fontFamily, setValue: setFontFamily } = useBoundProp(import_editor_props15.stringPropTypeUtil);
1249
1239
  const popupId = (0, import_react8.useId)();
1250
1240
  const popoverState = (0, import_ui20.usePopupState)({ variant: "popover", popupId });
1251
1241
  const filteredFontFamilies = useFilteredFontFamilies(fontFamilies, searchValue);
@@ -1318,6 +1308,87 @@ var FontFamilyControl = createControl(({ fontFamilies }) => {
1318
1308
  ), "\xA0", (0, import_i18n10.__)("and try again.", "elementor")))))
1319
1309
  ));
1320
1310
  });
1311
+
1312
+ // src/controls/url-control.tsx
1313
+ var React25 = __toESM(require("react"));
1314
+ var import_ui21 = require("@elementor/ui");
1315
+ var UrlControl = createControl(({ placeholder }) => {
1316
+ const { value, setValue } = useBoundProp();
1317
+ const handleChange = (event) => setValue({
1318
+ $$type: "url",
1319
+ value: event.target.value
1320
+ });
1321
+ return /* @__PURE__ */ React25.createElement(ControlActions, null, /* @__PURE__ */ React25.createElement(
1322
+ import_ui21.TextField,
1323
+ {
1324
+ size: "tiny",
1325
+ fullWidth: true,
1326
+ value: value?.value,
1327
+ onChange: handleChange,
1328
+ placeholder
1329
+ }
1330
+ ));
1331
+ });
1332
+
1333
+ // src/controls/link-control.tsx
1334
+ var React26 = __toESM(require("react"));
1335
+ var import_icons5 = require("@elementor/icons");
1336
+ var import_ui22 = require("@elementor/ui");
1337
+ var import_i18n11 = require("@wordpress/i18n");
1338
+ var SIZE3 = "tiny";
1339
+ var DEFAULT_LINK_CONTROL_VALUE = {
1340
+ $$type: "link",
1341
+ value: {
1342
+ enabled: false,
1343
+ href: {
1344
+ $$type: "url",
1345
+ value: ""
1346
+ },
1347
+ isTargetBlank: false
1348
+ }
1349
+ };
1350
+ var LinkControl = createControl(() => {
1351
+ const { value = DEFAULT_LINK_CONTROL_VALUE, setValue } = useBoundProp();
1352
+ const { enabled, href, isTargetBlank } = value?.value || {};
1353
+ const handleOnChange = (key, newValue) => {
1354
+ setValue({
1355
+ $$type: "link",
1356
+ value: {
1357
+ ...value?.value ?? DEFAULT_LINK_CONTROL_VALUE.value,
1358
+ [key]: newValue
1359
+ }
1360
+ });
1361
+ };
1362
+ return /* @__PURE__ */ React26.createElement(import_ui22.Stack, { gap: 1.5 }, /* @__PURE__ */ React26.createElement(import_ui22.Divider, null), /* @__PURE__ */ React26.createElement(
1363
+ import_ui22.Stack,
1364
+ {
1365
+ direction: "row",
1366
+ sx: {
1367
+ justifyContent: "space-between",
1368
+ alignItems: "center"
1369
+ }
1370
+ },
1371
+ /* @__PURE__ */ React26.createElement(ControlLabel, null, (0, import_i18n11.__)("Link", "elementor")),
1372
+ /* @__PURE__ */ React26.createElement(import_ui22.IconButton, { size: SIZE3, onClick: () => handleOnChange("enabled", !enabled) }, enabled ? /* @__PURE__ */ React26.createElement(import_icons5.MinusIcon, { fontSize: SIZE3 }) : /* @__PURE__ */ React26.createElement(import_icons5.PlusIcon, { fontSize: SIZE3 }))
1373
+ ), /* @__PURE__ */ React26.createElement(import_ui22.Collapse, { in: enabled, timeout: "auto", unmountOnExit: true }, /* @__PURE__ */ React26.createElement(import_ui22.Stack, { gap: 1.5 }, /* @__PURE__ */ React26.createElement(
1374
+ BoundPropProvider,
1375
+ {
1376
+ value: href,
1377
+ setValue: (newHref) => handleOnChange("href", newHref),
1378
+ bind: "href"
1379
+ },
1380
+ /* @__PURE__ */ React26.createElement(UrlControl, { placeholder: (0, import_i18n11.__)("Paste URL or type", "elementor") })
1381
+ ), /* @__PURE__ */ React26.createElement(
1382
+ SwitchControl,
1383
+ {
1384
+ value: isTargetBlank,
1385
+ onSwitch: () => handleOnChange("isTargetBlank", !isTargetBlank)
1386
+ }
1387
+ ))));
1388
+ });
1389
+ var SwitchControl = ({ value, onSwitch }) => {
1390
+ return /* @__PURE__ */ React26.createElement(import_ui22.Grid, { container: true, alignItems: "center", flexWrap: "nowrap", justifyContent: "space-between" }, /* @__PURE__ */ React26.createElement(import_ui22.Grid, { item: true }, /* @__PURE__ */ React26.createElement(ControlLabel, null, (0, import_i18n11.__)("Open in new tab", "elementor"))), /* @__PURE__ */ React26.createElement(import_ui22.Grid, { item: true }, /* @__PURE__ */ React26.createElement(import_ui22.Switch, { checked: value, onChange: onSwitch })));
1391
+ };
1321
1392
  // Annotate the CommonJS export names for ESM import in node:
1322
1393
  0 && (module.exports = {
1323
1394
  BackgroundOverlayRepeaterControl,
@@ -1327,9 +1398,11 @@ var FontFamilyControl = createControl(({ fontFamilies }) => {
1327
1398
  ControlActionsProvider,
1328
1399
  ControlLabel,
1329
1400
  ControlReplacementProvider,
1401
+ ControlToggleButtonGroup,
1330
1402
  EqualUnequalSizesControl,
1331
1403
  FontFamilyControl,
1332
1404
  ImageControl,
1405
+ LinkControl,
1333
1406
  LinkedDimensionsControl,
1334
1407
  NumberControl,
1335
1408
  SelectControl,
@@ -1338,6 +1411,7 @@ var FontFamilyControl = createControl(({ fontFamilies }) => {
1338
1411
  TextAreaControl,
1339
1412
  TextControl,
1340
1413
  ToggleControl,
1414
+ UrlControl,
1341
1415
  createControlReplacement,
1342
1416
  useBoundProp,
1343
1417
  useControlActions,