@kgalexander/mcreate 0.0.16 → 0.0.17

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
@@ -3512,7 +3512,7 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
3512
3512
 
3513
3513
  background-color: var(--background);
3514
3514
  border-radius: 4px;
3515
- padding: 4px;
3515
+ padding: 0px;
3516
3516
  border: 1px solid var(--border);
3517
3517
  color: #000000;
3518
3518
  }
@@ -11660,12 +11660,13 @@ var init_text_link_menu = __esm({
11660
11660
  const [isLinkTypeOpen, setIsLinkTypeOpen] = (0, import_react9.useState)(false);
11661
11661
  const currentHref = editor.getAttributes("link").href || "";
11662
11662
  const hasLink = !!currentHref;
11663
- (0, import_react9.useEffect)(() => {
11664
- if (isOpen) {
11663
+ const handleOpenChange = (0, import_react9.useCallback)((open) => {
11664
+ setIsOpen(open);
11665
+ if (open) {
11665
11666
  setLinkType(detectLinkType(currentHref));
11666
11667
  setInputValue(stripPrefix(currentHref));
11667
11668
  }
11668
- }, [isOpen, currentHref]);
11669
+ }, [currentHref]);
11669
11670
  const handleInputChange = (e) => {
11670
11671
  setInputValue(e.target.value);
11671
11672
  };
@@ -11702,7 +11703,7 @@ var init_text_link_menu = __esm({
11702
11703
  editor.chain().focus().unsetLink().run();
11703
11704
  setInputValue("");
11704
11705
  };
11705
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
11706
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Popover, { open: isOpen, onOpenChange: handleOpenChange, children: [
11706
11707
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
11707
11708
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PopoverTrigger, { asChild: true, children: hasLink ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
11708
11709
  Button,
@@ -12608,7 +12609,7 @@ var init_tiptap_overlay = __esm({
12608
12609
  .tiptap-overlay .ProseMirror .merge-field-tag {
12609
12610
  background-color: var(--background);
12610
12611
  border-radius: 4px;
12611
- padding: 4px;
12612
+ padding: 0px;
12612
12613
  border: 1px solid var(--border);
12613
12614
  color: #000000;
12614
12615
  }
@@ -12957,13 +12958,14 @@ var init_href_menu = __esm({
12957
12958
  setInputValue(value);
12958
12959
  setIsPresetOpen(false);
12959
12960
  }, []);
12960
- (0, import_react14.useEffect)(() => {
12961
- if (isOpen) {
12961
+ const handleOpenChange = (0, import_react14.useCallback)((open) => {
12962
+ setIsOpen(open);
12963
+ if (open) {
12962
12964
  setLinkType(detectLinkType(href));
12963
12965
  setInputValue(stripPrefix(href));
12964
12966
  setIsPresetOpen(true);
12965
12967
  }
12966
- }, [isOpen, href]);
12968
+ }, [href]);
12967
12969
  const handleInputChange = (e) => {
12968
12970
  setInputValue(e.target.value);
12969
12971
  setIsPresetOpen(true);
@@ -13008,7 +13010,7 @@ var init_href_menu = __esm({
13008
13010
  setHref(buildHref(inputValue));
13009
13011
  setIsOpen(false);
13010
13012
  };
13011
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
13013
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(DropdownMenu, { open: isOpen, onOpenChange: handleOpenChange, children: [
13012
13014
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Tooltip, { children: [
13013
13015
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
13014
13016
  Button,
@@ -13481,12 +13483,13 @@ var init_social_item_menu = __esm({
13481
13483
  return (0, import_lodash4.get)(template, path);
13482
13484
  }, [focusIdx, template]);
13483
13485
  const content = element?.data?.value?.content || "";
13484
- (0, import_react18.useEffect)(() => {
13485
- if (isOpen) {
13486
+ const handleOpenChange = (0, import_react18.useCallback)((open) => {
13487
+ setIsOpen(open);
13488
+ if (open) {
13486
13489
  setHrefInputValue(href);
13487
13490
  setContentInputValue(content);
13488
13491
  }
13489
- }, [isOpen, href, content]);
13492
+ }, [href, content]);
13490
13493
  const handleCopy = (0, import_react18.useCallback)(async () => {
13491
13494
  await copyHref();
13492
13495
  setShowCopied(true);
@@ -13506,7 +13509,7 @@ var init_social_item_menu = __esm({
13506
13509
  }
13507
13510
  setIsOpen(false);
13508
13511
  }, [hrefInputValue, contentInputValue, setHref, focusIdx, element, updateElement]);
13509
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
13512
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(DropdownMenu, { open: isOpen, onOpenChange: handleOpenChange, children: [
13510
13513
  /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(Tooltip, { children: [
13511
13514
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DropdownMenuTrigger, { asChild: true, children: hasHref ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
13512
13515
  Button,
@@ -13662,11 +13665,12 @@ var init_float6 = __esm({
13662
13665
  const parentSocial = focusIdx ? getParentByIdx(template, focusIdx) : null;
13663
13666
  const childrenCount = parentSocial?.children?.length || 0;
13664
13667
  const canDelete = childrenCount > 1;
13665
- (0, import_react20.useEffect)(() => {
13666
- if (dropdownOpen) {
13668
+ const handleDropdownOpenChange = (0, import_react20.useCallback)((open) => {
13669
+ setDropdownOpen(open);
13670
+ if (open) {
13667
13671
  setAltInputValue(alt);
13668
13672
  }
13669
- }, [dropdownOpen, alt]);
13673
+ }, [alt]);
13670
13674
  const handleSaveAlt = () => {
13671
13675
  setAlt(altInputValue);
13672
13676
  setDropdownOpen(false);
@@ -13692,7 +13696,7 @@ var init_float6 = __esm({
13692
13696
  ) }),
13693
13697
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TooltipContent, { side: "bottom", children: canDelete ? "Delete" : "Cannot delete last item" })
13694
13698
  ] }),
13695
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
13699
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(DropdownMenu, { open: dropdownOpen, onOpenChange: handleDropdownOpenChange, children: [
13696
13700
  /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(Tooltip, { children: [
13697
13701
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react24.MoreHorizontalIcon, { className: "w-4 h-4" }) }) }) }),
13698
13702
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TooltipContent, { side: "bottom", children: "More" })
@@ -13807,11 +13811,12 @@ var init_float8 = __esm({
13807
13811
  }
13808
13812
  updateElement(focusIdx, { attributes: newAttributes });
13809
13813
  }, [focusIdx, element, isFluidOnMobile, updateElement]);
13810
- (0, import_react21.useEffect)(() => {
13811
- if (dropdownOpen) {
13814
+ const handleDropdownOpenChange = (0, import_react21.useCallback)((open) => {
13815
+ setDropdownOpen(open);
13816
+ if (open) {
13812
13817
  setAltInputValue(alt);
13813
13818
  }
13814
- }, [dropdownOpen, alt]);
13819
+ }, [alt]);
13815
13820
  const handleSaveAlt = () => {
13816
13821
  setAlt(altInputValue);
13817
13822
  setDropdownOpen(false);
@@ -13821,7 +13826,7 @@ var init_float8 = __esm({
13821
13826
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(HrefMenu, {}),
13822
13827
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(DuplicateButton, {}),
13823
13828
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(DeleteButton, {}),
13824
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
13829
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(DropdownMenu, { open: dropdownOpen, onOpenChange: handleDropdownOpenChange, children: [
13825
13830
  /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(Tooltip, { children: [
13826
13831
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Button, { variant: "ghost", size: "icon", className: floatButtonVariants, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react25.MoreHorizontalIcon, { className: "w-4 h-4" }) }) }) }),
13827
13832
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(TooltipContent, { side: "bottom", children: "More" })
@@ -15694,6 +15699,7 @@ function Editor({ setEditorLoading }) {
15694
15699
  const lastSyncedTemplateRef = (0, import_react37.useRef)(null);
15695
15700
  const prevTextEditingIdxRef = (0, import_react37.useRef)(null);
15696
15701
  const lastRenderSyncNeededRef = (0, import_react37.useRef)(0);
15702
+ const hasNotifiedLoadedRef = (0, import_react37.useRef)(false);
15697
15703
  const imageReplaceTargetRef = (0, import_react37.useRef)(null);
15698
15704
  const imagePreviewOriginalSrcRef = (0, import_react37.useRef)(null);
15699
15705
  (0, import_react37.useEffect)(() => {
@@ -15711,15 +15717,14 @@ function Editor({ setEditorLoading }) {
15711
15717
  }
15712
15718
  if (!(0, import_lodash6.isEqual)(template, renderData)) {
15713
15719
  setRenderData((0, import_lodash6.cloneDeep)(template));
15720
+ if (!hasNotifiedLoadedRef.current && setEditorLoading) {
15721
+ hasNotifiedLoadedRef.current = true;
15722
+ setEditorLoading(false);
15723
+ }
15714
15724
  }
15715
15725
  lastSyncedTemplateRef.current = template;
15716
15726
  }
15717
- }, [template, renderData, isEditing, textEditing, renderSyncNeeded]);
15718
- (0, import_react37.useEffect)(() => {
15719
- if (renderData && setEditorLoading) {
15720
- setEditorLoading(false);
15721
- }
15722
- }, [renderData, setEditorLoading]);
15727
+ }, [template, renderData, isEditing, textEditing, renderSyncNeeded, setEditorLoading]);
15723
15728
  (0, import_react37.useEffect)(() => {
15724
15729
  if (!pendingTextEditRequest || !shadowRootRef.current) return;
15725
15730
  const { idx, cursorPosition } = pendingTextEditRequest;
@@ -19484,22 +19489,55 @@ var ColorPicker = ({
19484
19489
  );
19485
19490
  const [alpha2, setAlpha] = (0, import_react55.useState)(selectedColor.alpha() * 100 || defaultColor.alpha() * 100);
19486
19491
  const [mode, setMode] = (0, import_react55.useState)("hex");
19492
+ const hueRef = (0, import_react55.useRef)(hue);
19493
+ const saturationRef = (0, import_react55.useRef)(saturation);
19494
+ const lightnessRef = (0, import_react55.useRef)(lightness);
19495
+ const alphaRef = (0, import_react55.useRef)(alpha2);
19496
+ hueRef.current = hue;
19497
+ saturationRef.current = saturation;
19498
+ lightnessRef.current = lightness;
19499
+ alphaRef.current = alpha2;
19487
19500
  (0, import_react55.useEffect)(() => {
19488
19501
  if (value) {
19489
- const color = import_color.default.rgb(value).rgb().object();
19490
- setHue(color.r);
19491
- setSaturation(color.g);
19492
- setLightness(color.b);
19493
- setAlpha(color.a);
19502
+ const color = (0, import_color.default)(value);
19503
+ const hsl = color.hsl().object();
19504
+ setHue(hsl.h);
19505
+ setSaturation(hsl.s);
19506
+ setLightness(hsl.l);
19507
+ setAlpha(color.alpha() * 100);
19508
+ hueRef.current = hsl.h;
19509
+ saturationRef.current = hsl.s;
19510
+ lightnessRef.current = hsl.l;
19511
+ alphaRef.current = color.alpha() * 100;
19494
19512
  }
19495
19513
  }, [value]);
19496
- (0, import_react55.useEffect)(() => {
19514
+ const updateColor = (0, import_react55.useCallback)((updates) => {
19515
+ const newH = updates.h ?? hueRef.current;
19516
+ const newS = updates.s ?? saturationRef.current;
19517
+ const newL = updates.l ?? lightnessRef.current;
19518
+ const newA = updates.a ?? alphaRef.current;
19519
+ if (updates.h !== void 0) {
19520
+ setHue(updates.h);
19521
+ hueRef.current = updates.h;
19522
+ }
19523
+ if (updates.s !== void 0) {
19524
+ setSaturation(updates.s);
19525
+ saturationRef.current = updates.s;
19526
+ }
19527
+ if (updates.l !== void 0) {
19528
+ setLightness(updates.l);
19529
+ lightnessRef.current = updates.l;
19530
+ }
19531
+ if (updates.a !== void 0) {
19532
+ setAlpha(updates.a);
19533
+ alphaRef.current = updates.a;
19534
+ }
19497
19535
  if (onChange) {
19498
- const color = import_color.default.hsl(hue, saturation, lightness).alpha(alpha2 / 100);
19536
+ const color = import_color.default.hsl(newH, newS, newL).alpha(newA / 100);
19499
19537
  const rgba = color.rgb().array();
19500
- onChange([rgba[0], rgba[1], rgba[2], alpha2 / 100]);
19538
+ onChange([rgba[0], rgba[1], rgba[2], newA / 100]);
19501
19539
  }
19502
- }, [hue, saturation, lightness, alpha2, onChange]);
19540
+ }, [onChange]);
19503
19541
  return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
19504
19542
  ColorPickerContext.Provider,
19505
19543
  {
@@ -19509,10 +19547,7 @@ var ColorPicker = ({
19509
19547
  lightness,
19510
19548
  alpha: alpha2,
19511
19549
  mode,
19512
- setHue,
19513
- setSaturation,
19514
- setLightness,
19515
- setAlpha,
19550
+ updateColor,
19516
19551
  setMode
19517
19552
  },
19518
19553
  children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: cn("flex size-full flex-col gap-4", className), ...props })
@@ -19524,7 +19559,7 @@ var ColorPickerSelection = (0, import_react55.memo)(({ className, ...props }) =>
19524
19559
  const [isDragging, setIsDragging] = (0, import_react55.useState)(false);
19525
19560
  const [positionX, setPositionX] = (0, import_react55.useState)(0);
19526
19561
  const [positionY, setPositionY] = (0, import_react55.useState)(0);
19527
- const { hue, setSaturation, setLightness } = useColorPicker();
19562
+ const { hue, updateColor } = useColorPicker();
19528
19563
  const backgroundGradient = (0, import_react55.useMemo)(() => {
19529
19564
  return `linear-gradient(0deg, rgba(0,0,0,1), rgba(0,0,0,0)),
19530
19565
  linear-gradient(90deg, rgba(255,255,255,1), rgba(255,255,255,0)),
@@ -19540,12 +19575,12 @@ var ColorPickerSelection = (0, import_react55.memo)(({ className, ...props }) =>
19540
19575
  const y = Math.max(0, Math.min(1, (event.clientY - rect.top) / rect.height));
19541
19576
  setPositionX(x);
19542
19577
  setPositionY(y);
19543
- setSaturation(x * 100);
19578
+ const newSaturation = x * 100;
19544
19579
  const topLightness = x < 0.01 ? 100 : 50 + 50 * (1 - x);
19545
- const lightness = topLightness * (1 - y);
19546
- setLightness(lightness);
19580
+ const newLightness = topLightness * (1 - y);
19581
+ updateColor({ s: newSaturation, l: newLightness });
19547
19582
  },
19548
- [isDragging, setSaturation, setLightness]
19583
+ [isDragging, updateColor]
19549
19584
  );
19550
19585
  (0, import_react55.useEffect)(() => {
19551
19586
  const handlePointerUp = () => setIsDragging(false);
@@ -19588,13 +19623,13 @@ var ColorPickerSelection = (0, import_react55.memo)(({ className, ...props }) =>
19588
19623
  });
19589
19624
  ColorPickerSelection.displayName = "ColorPickerSelection";
19590
19625
  var ColorPickerHue = ({ className, ...props }) => {
19591
- const { hue, setHue } = useColorPicker();
19626
+ const { hue, updateColor } = useColorPicker();
19592
19627
  return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
19593
19628
  import_radix_ui.Slider.Root,
19594
19629
  {
19595
19630
  className: cn("relative flex h-4 w-full touch-none", className),
19596
19631
  max: 360,
19597
- onValueChange: ([hue2]) => setHue(hue2),
19632
+ onValueChange: ([h]) => updateColor({ h }),
19598
19633
  step: 1,
19599
19634
  value: [hue],
19600
19635
  ...props,
@@ -19606,17 +19641,14 @@ var ColorPickerHue = ({ className, ...props }) => {
19606
19641
  );
19607
19642
  };
19608
19643
  var ColorPickerEyeDropper = ({ className, ...props }) => {
19609
- const { setHue, setSaturation, setLightness, setAlpha } = useColorPicker();
19644
+ const { updateColor } = useColorPicker();
19610
19645
  const handleEyeDropper = async () => {
19611
19646
  try {
19612
19647
  const eyeDropper = new EyeDropper();
19613
19648
  const result = await eyeDropper.open();
19614
19649
  const color = (0, import_color.default)(result.sRGBHex);
19615
19650
  const [h, s, l] = color.hsl().array();
19616
- setHue(h);
19617
- setSaturation(s);
19618
- setLightness(l);
19619
- setAlpha(100);
19651
+ updateColor({ h, s, l, a: 100 });
19620
19652
  } catch (error) {
19621
19653
  console.error("EyeDropper failed:", error);
19622
19654
  }
@@ -20791,11 +20823,13 @@ function TemplateSidebar({ editorLoading }) {
20791
20823
  attributes: { ...element.attributes, [attributeName]: imageSrc }
20792
20824
  });
20793
20825
  }, [imageTarget]);
20794
- (0, import_react59.useEffect)(() => {
20826
+ const prevActiveViewRef = (0, import_react59.useRef)(activeView);
20827
+ if (activeView !== prevActiveViewRef.current) {
20828
+ prevActiveViewRef.current = activeView;
20795
20829
  if (PICKER_VIEWS2.has(activeView)) {
20796
20830
  setOpenSidebar(true);
20797
20831
  }
20798
- }, [activeView]);
20832
+ }
20799
20833
  const handleCloseSidebar = () => setOpenSidebar(!openSidebar);
20800
20834
  const handleViewClick = (view) => {
20801
20835
  setActiveView(view);
@@ -21073,7 +21107,7 @@ var PlainToolbar = () => {
21073
21107
  };
21074
21108
 
21075
21109
  // src/core/editor/components/element-gear/text/toolbar.tsx
21076
- var import_react69 = require("react");
21110
+ var import_react70 = require("react");
21077
21111
  init_dropdown_menu();
21078
21112
  init_popover();
21079
21113
  init_button();
@@ -21153,15 +21187,81 @@ function Slider2({
21153
21187
 
21154
21188
  // src/core/editor/components/paragraph-text-settings.tsx
21155
21189
  init_input();
21156
- var import_react62 = require("react");
21190
+ var import_react63 = require("react");
21157
21191
  init_editor();
21158
21192
  init_configuration();
21193
+
21194
+ // src/core/editor/hooks/use-editable-value.ts
21195
+ var import_react62 = require("react");
21196
+ function useEditableValue(options) {
21197
+ const { externalValue, onChange, toLocal, toExternal } = options;
21198
+ const convert = toLocal ?? String;
21199
+ const [localValue, setLocalValue] = (0, import_react62.useState)(convert(externalValue));
21200
+ const [isFocused, setIsFocused] = (0, import_react62.useState)(false);
21201
+ const displayValue = isFocused ? localValue : convert(externalValue);
21202
+ const handleFocus = (0, import_react62.useCallback)(() => {
21203
+ setLocalValue(convert(externalValue));
21204
+ setIsFocused(true);
21205
+ }, [externalValue, convert]);
21206
+ const handleBlur = (0, import_react62.useCallback)(() => {
21207
+ setIsFocused(false);
21208
+ if (toExternal) {
21209
+ const parsed = toExternal(localValue);
21210
+ if (parsed !== null) {
21211
+ onChange(parsed);
21212
+ }
21213
+ } else {
21214
+ onChange(localValue);
21215
+ }
21216
+ }, [localValue, toExternal, onChange]);
21217
+ const handleKeyDown = (0, import_react62.useCallback)((e) => {
21218
+ if (e.key === "Enter") {
21219
+ e.currentTarget.blur();
21220
+ }
21221
+ }, []);
21222
+ return {
21223
+ displayValue,
21224
+ setLocalValue,
21225
+ handleFocus,
21226
+ handleBlur,
21227
+ handleKeyDown,
21228
+ isFocused
21229
+ };
21230
+ }
21231
+ function useEditableNumber(options) {
21232
+ const { value, onChange, min = -Infinity, max = Infinity } = options;
21233
+ return useEditableValue({
21234
+ externalValue: value,
21235
+ onChange,
21236
+ toLocal: (n) => n.toString(),
21237
+ toExternal: (s) => {
21238
+ const parsed = parseInt(s, 10);
21239
+ if (isNaN(parsed)) return null;
21240
+ return Math.max(min, Math.min(max, parsed));
21241
+ }
21242
+ });
21243
+ }
21244
+ function useEditableFloat(options) {
21245
+ const { value, onChange, min = -Infinity, max = Infinity } = options;
21246
+ return useEditableValue({
21247
+ externalValue: value,
21248
+ onChange,
21249
+ toLocal: (n) => n.toString(),
21250
+ toExternal: (s) => {
21251
+ const parsed = parseFloat(s);
21252
+ if (isNaN(parsed) || s === "") return null;
21253
+ return Math.max(min, Math.min(max, parsed));
21254
+ }
21255
+ });
21256
+ }
21257
+
21258
+ // src/core/editor/components/paragraph-text-settings.tsx
21159
21259
  var import_jsx_runtime91 = require("react/jsx-runtime");
21160
- var ParagraphTextSettings = (0, import_react62.memo)(function ParagraphTextSettings2() {
21161
- const [isOpen, setIsOpen] = (0, import_react62.useState)(false);
21260
+ var ParagraphTextSettings = (0, import_react63.memo)(function ParagraphTextSettings2() {
21261
+ const [isOpen, setIsOpen] = (0, import_react63.useState)(false);
21162
21262
  const tiptapEditor = useEditorStore((s) => s.tiptapEditor);
21163
- const [updateCounter, forceUpdate] = (0, import_react62.useState)(0);
21164
- (0, import_react62.useEffect)(() => {
21263
+ const [updateCounter, forceUpdate] = (0, import_react63.useState)(0);
21264
+ (0, import_react63.useEffect)(() => {
21165
21265
  if (!tiptapEditor) return;
21166
21266
  const handler = () => forceUpdate((n) => n + 1);
21167
21267
  tiptapEditor.on("selectionUpdate", handler);
@@ -21169,7 +21269,7 @@ var ParagraphTextSettings = (0, import_react62.memo)(function ParagraphTextSetti
21169
21269
  tiptapEditor.off("selectionUpdate", handler);
21170
21270
  };
21171
21271
  }, [tiptapEditor]);
21172
- const currentLetterSpacing = (0, import_react62.useMemo)(() => {
21272
+ const currentLetterSpacing = (0, import_react63.useMemo)(() => {
21173
21273
  if (!tiptapEditor) return DEFAULT_LETTER_SPACING;
21174
21274
  const textStyleAttrs = tiptapEditor.getAttributes("textStyle");
21175
21275
  if (textStyleAttrs.letterSpacing) {
@@ -21178,7 +21278,7 @@ var ParagraphTextSettings = (0, import_react62.memo)(function ParagraphTextSetti
21178
21278
  }
21179
21279
  return DEFAULT_LETTER_SPACING;
21180
21280
  }, [tiptapEditor, updateCounter]);
21181
- const currentLineHeight = (0, import_react62.useMemo)(() => {
21281
+ const currentLineHeight = (0, import_react63.useMemo)(() => {
21182
21282
  if (!tiptapEditor) return DEFAULT_LINE_HEIGHT;
21183
21283
  const textStyleAttrs = tiptapEditor.getAttributes("textStyle");
21184
21284
  if (textStyleAttrs.lineHeight) {
@@ -21187,92 +21287,34 @@ var ParagraphTextSettings = (0, import_react62.memo)(function ParagraphTextSetti
21187
21287
  }
21188
21288
  return DEFAULT_LINE_HEIGHT;
21189
21289
  }, [tiptapEditor, updateCounter]);
21190
- const [letterSpacingInputValue, setLetterSpacingInputValue] = (0, import_react62.useState)(
21191
- String(currentLetterSpacing)
21192
- );
21193
- const [isLetterSpacingInputFocused, setIsLetterSpacingInputFocused] = (0, import_react62.useState)(false);
21194
- const [lineHeightInputValue, setLineHeightInputValue] = (0, import_react62.useState)(
21195
- String(currentLineHeight)
21196
- );
21197
- const [isLineHeightInputFocused, setIsLineHeightInputFocused] = (0, import_react62.useState)(false);
21198
- (0, import_react62.useEffect)(() => {
21199
- if (!isLetterSpacingInputFocused) {
21200
- setLetterSpacingInputValue(String(currentLetterSpacing));
21201
- }
21202
- }, [currentLetterSpacing, isLetterSpacingInputFocused]);
21203
- (0, import_react62.useEffect)(() => {
21204
- if (!isLineHeightInputFocused) {
21205
- setLineHeightInputValue(String(currentLineHeight));
21206
- }
21207
- }, [currentLineHeight, isLineHeightInputFocused]);
21208
- const handleLetterSpacingSliderChange = (0, import_react62.useCallback)((values) => {
21290
+ const commitLetterSpacing = (0, import_react63.useCallback)((value) => {
21209
21291
  if (!tiptapEditor) return;
21210
- const value = values[0];
21211
- setLetterSpacingInputValue(String(value));
21212
21292
  tiptapEditor.chain().setLetterSpacing(`${value}px`).run();
21213
21293
  forceUpdate((n) => n + 1);
21214
21294
  }, [tiptapEditor]);
21215
- const handleLetterSpacingInputChange = (0, import_react62.useCallback)((e) => {
21216
- setLetterSpacingInputValue(e.target.value);
21217
- }, []);
21218
- const applyLetterSpacing = (0, import_react62.useCallback)(() => {
21219
- if (!tiptapEditor) return;
21220
- const parsed = parseFloat(letterSpacingInputValue);
21221
- if (isNaN(parsed) || letterSpacingInputValue === "") {
21222
- setLetterSpacingInputValue(String(currentLetterSpacing));
21223
- tiptapEditor.chain().focus().run();
21224
- return;
21225
- }
21226
- const clampedValue = Math.max(MIN_LETTER_SPACING, Math.min(parsed, MAX_LETTER_SPACING));
21227
- setLetterSpacingInputValue(String(clampedValue));
21228
- tiptapEditor.chain().focus().setLetterSpacing(`${clampedValue}px`).run();
21229
- forceUpdate((n) => n + 1);
21230
- }, [tiptapEditor, letterSpacingInputValue, currentLetterSpacing]);
21231
- const handleLetterSpacingInputBlur = (0, import_react62.useCallback)(() => {
21232
- setIsLetterSpacingInputFocused(false);
21233
- applyLetterSpacing();
21234
- }, [applyLetterSpacing]);
21235
- const handleLetterSpacingInputKeyDown = (0, import_react62.useCallback)((e) => {
21236
- if (e.key === "Enter") {
21237
- e.preventDefault();
21238
- applyLetterSpacing();
21239
- e.target.blur();
21240
- }
21241
- }, [applyLetterSpacing]);
21242
- const handleLineHeightSliderChange = (0, import_react62.useCallback)((values) => {
21295
+ const commitLineHeight = (0, import_react63.useCallback)((value) => {
21243
21296
  if (!tiptapEditor) return;
21244
- const value = values[0];
21245
- setLineHeightInputValue(String(value));
21246
21297
  tiptapEditor.chain().setLineHeight(String(value)).run();
21247
21298
  forceUpdate((n) => n + 1);
21248
21299
  }, [tiptapEditor]);
21249
- const handleLineHeightInputChange = (0, import_react62.useCallback)((e) => {
21250
- setLineHeightInputValue(e.target.value);
21251
- }, []);
21252
- const applyLineHeight = (0, import_react62.useCallback)(() => {
21253
- if (!tiptapEditor) return;
21254
- const parsed = parseFloat(lineHeightInputValue);
21255
- if (isNaN(parsed) || lineHeightInputValue === "") {
21256
- setLineHeightInputValue(String(currentLineHeight));
21257
- tiptapEditor.chain().focus().run();
21258
- return;
21259
- }
21260
- const clampedValue = Math.max(MIN_LINE_HEIGHT, Math.min(parsed, MAX_LINE_HEIGHT));
21261
- setLineHeightInputValue(String(clampedValue));
21262
- tiptapEditor.chain().focus().setLineHeight(String(clampedValue)).run();
21263
- forceUpdate((n) => n + 1);
21264
- }, [tiptapEditor, lineHeightInputValue, currentLineHeight]);
21265
- const handleLineHeightInputBlur = (0, import_react62.useCallback)(() => {
21266
- setIsLineHeightInputFocused(false);
21267
- applyLineHeight();
21268
- }, [applyLineHeight]);
21269
- const handleLineHeightInputKeyDown = (0, import_react62.useCallback)((e) => {
21270
- if (e.key === "Enter") {
21271
- e.preventDefault();
21272
- applyLineHeight();
21273
- e.target.blur();
21274
- }
21275
- }, [applyLineHeight]);
21300
+ const letterSpacingInput = useEditableFloat({
21301
+ value: currentLetterSpacing,
21302
+ onChange: commitLetterSpacing,
21303
+ min: MIN_LETTER_SPACING,
21304
+ max: MAX_LETTER_SPACING
21305
+ });
21306
+ const lineHeightInput = useEditableFloat({
21307
+ value: currentLineHeight,
21308
+ onChange: commitLineHeight,
21309
+ min: MIN_LINE_HEIGHT,
21310
+ max: MAX_LINE_HEIGHT
21311
+ });
21312
+ const handleLetterSpacingSliderChange = (0, import_react63.useCallback)((values) => {
21313
+ commitLetterSpacing(values[0]);
21314
+ }, [commitLetterSpacing]);
21315
+ const handleLineHeightSliderChange = (0, import_react63.useCallback)((values) => {
21316
+ commitLineHeight(values[0]);
21317
+ }, [commitLineHeight]);
21276
21318
  return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(Tooltip, { children: [
21277
21319
  /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
21278
21320
  /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(
@@ -21309,11 +21351,11 @@ var ParagraphTextSettings = (0, import_react62.memo)(function ParagraphTextSetti
21309
21351
  Input,
21310
21352
  {
21311
21353
  type: "number",
21312
- value: letterSpacingInputValue,
21313
- onChange: handleLetterSpacingInputChange,
21314
- onFocus: () => setIsLetterSpacingInputFocused(true),
21315
- onBlur: handleLetterSpacingInputBlur,
21316
- onKeyDown: handleLetterSpacingInputKeyDown,
21354
+ value: letterSpacingInput.displayValue,
21355
+ onChange: (e) => letterSpacingInput.setLocalValue(e.target.value),
21356
+ onFocus: letterSpacingInput.handleFocus,
21357
+ onBlur: letterSpacingInput.handleBlur,
21358
+ onKeyDown: letterSpacingInput.handleKeyDown,
21317
21359
  className: "w-25 shadow-none rounded-[12px]",
21318
21360
  min: MIN_LETTER_SPACING,
21319
21361
  max: MAX_LETTER_SPACING,
@@ -21340,11 +21382,11 @@ var ParagraphTextSettings = (0, import_react62.memo)(function ParagraphTextSetti
21340
21382
  Input,
21341
21383
  {
21342
21384
  type: "number",
21343
- value: lineHeightInputValue,
21344
- onChange: handleLineHeightInputChange,
21345
- onFocus: () => setIsLineHeightInputFocused(true),
21346
- onBlur: handleLineHeightInputBlur,
21347
- onKeyDown: handleLineHeightInputKeyDown,
21385
+ value: lineHeightInput.displayValue,
21386
+ onChange: (e) => lineHeightInput.setLocalValue(e.target.value),
21387
+ onFocus: lineHeightInput.handleFocus,
21388
+ onBlur: lineHeightInput.handleBlur,
21389
+ onKeyDown: lineHeightInput.handleKeyDown,
21348
21390
  className: "w-25 shadow-none rounded-[12px]",
21349
21391
  min: MIN_LINE_HEIGHT,
21350
21392
  max: MAX_LINE_HEIGHT,
@@ -21412,7 +21454,7 @@ var FontFamilyDropdown = ({
21412
21454
  };
21413
21455
 
21414
21456
  // src/core/editor/components/font-size-control.tsx
21415
- var import_react63 = require("react");
21457
+ var import_react64 = require("react");
21416
21458
  init_button();
21417
21459
 
21418
21460
  // src/components/ui/button-group.tsx
@@ -21556,7 +21598,7 @@ var import_lucide_react56 = require("lucide-react");
21556
21598
  init_configuration();
21557
21599
  var import_jsx_runtime95 = require("react/jsx-runtime");
21558
21600
  var PRESET_FONT_SIZES = [6, 8, 10, 12, 14, 16, 18, 21, 24, 28, 32, 36, 48, 64, 72];
21559
- var FontSizeControl = (0, import_react63.memo)(function FontSizeControl2({
21601
+ var FontSizeControl = (0, import_react64.memo)(function FontSizeControl2({
21560
21602
  value,
21561
21603
  onChange,
21562
21604
  disabled = false,
@@ -21564,59 +21606,37 @@ var FontSizeControl = (0, import_react63.memo)(function FontSizeControl2({
21564
21606
  max = MAX_FONT_SIZE,
21565
21607
  step = FONT_SIZE_STEP
21566
21608
  }) {
21567
- const [inputValue, setInputValue] = (0, import_react63.useState)(String(value));
21568
- const [isFocused, setIsFocused] = (0, import_react63.useState)(false);
21569
- const [isPopoverOpen, setIsPopoverOpen] = (0, import_react63.useState)(false);
21570
- (0, import_react63.useEffect)(() => {
21571
- if (!isFocused) {
21572
- setInputValue(String(value));
21573
- }
21574
- }, [value, isFocused]);
21575
- const applySize = (0, import_react63.useCallback)(() => {
21576
- const parsed = parseInt(inputValue, 10);
21577
- if (isNaN(parsed) || inputValue === "") {
21578
- setInputValue(String(value));
21579
- return;
21580
- }
21581
- const clampedSize = Math.max(min, Math.min(parsed, max));
21582
- setInputValue(String(clampedSize));
21583
- onChange(clampedSize);
21584
- }, [inputValue, value, min, max, onChange]);
21585
- const handleIncrease = (0, import_react63.useCallback)(() => {
21609
+ const [isPopoverOpen, setIsPopoverOpen] = (0, import_react64.useState)(false);
21610
+ const input = useEditableNumber({ value, onChange, min, max });
21611
+ const handleIncrease = (0, import_react64.useCallback)(() => {
21586
21612
  const newSize = Math.min(value + step, max);
21587
21613
  onChange(newSize);
21588
21614
  }, [value, step, max, onChange]);
21589
- const handleDecrease = (0, import_react63.useCallback)(() => {
21615
+ const handleDecrease = (0, import_react64.useCallback)(() => {
21590
21616
  const newSize = Math.max(value - step, min);
21591
21617
  onChange(newSize);
21592
21618
  }, [value, step, min, onChange]);
21593
- const handleInputChange = (0, import_react63.useCallback)((e) => {
21594
- setInputValue(e.target.value);
21595
- }, []);
21596
- const handleFocus = (0, import_react63.useCallback)(() => {
21597
- setIsFocused(true);
21619
+ const handleFocus = (0, import_react64.useCallback)(() => {
21620
+ input.handleFocus();
21598
21621
  setIsPopoverOpen(true);
21599
- }, []);
21600
- const handleBlur = (0, import_react63.useCallback)(() => {
21601
- setIsFocused(false);
21602
- applySize();
21622
+ }, [input.handleFocus]);
21623
+ const handleBlur = (0, import_react64.useCallback)(() => {
21624
+ input.handleBlur();
21603
21625
  setTimeout(() => setIsPopoverOpen(false), 150);
21604
- }, [applySize]);
21605
- const handleKeyDown = (0, import_react63.useCallback)((e) => {
21626
+ }, [input.handleBlur]);
21627
+ const handleKeyDown = (0, import_react64.useCallback)((e) => {
21606
21628
  if (e.key === "Enter") {
21607
21629
  e.preventDefault();
21608
- applySize();
21609
21630
  setIsPopoverOpen(false);
21610
- e.target.blur();
21631
+ e.currentTarget.blur();
21611
21632
  }
21612
21633
  if (e.key === "Escape") {
21613
21634
  setIsPopoverOpen(false);
21614
- e.target.blur();
21635
+ e.currentTarget.blur();
21615
21636
  }
21616
- }, [applySize]);
21617
- const handlePresetSelect = (0, import_react63.useCallback)((size) => {
21637
+ }, []);
21638
+ const handlePresetSelect = (0, import_react64.useCallback)((size) => {
21618
21639
  onChange(size);
21619
- setInputValue(String(size));
21620
21640
  setIsPopoverOpen(false);
21621
21641
  }, [onChange]);
21622
21642
  return /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("div", { className: "grid w-full max-w-sm gap-6", children: /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(ButtonGroup, { children: [
@@ -21643,8 +21663,8 @@ var FontSizeControl = (0, import_react63.memo)(function FontSizeControl2({
21643
21663
  type: "number",
21644
21664
  className: "text-center w-12 border-0 shadow-none px-0",
21645
21665
  placeholder: "--",
21646
- value: inputValue,
21647
- onChange: handleInputChange,
21666
+ value: input.displayValue,
21667
+ onChange: (e) => input.setLocalValue(e.target.value),
21648
21668
  onFocus: handleFocus,
21649
21669
  onBlur: handleBlur,
21650
21670
  onKeyDown: handleKeyDown,
@@ -21699,12 +21719,12 @@ var FontSizeControl = (0, import_react63.memo)(function FontSizeControl2({
21699
21719
  });
21700
21720
 
21701
21721
  // src/core/editor/components/element-gear/column-styles.tsx
21702
- var import_react68 = require("react");
21722
+ var import_react69 = require("react");
21703
21723
  init_button();
21704
21724
  init_tooltip();
21705
21725
 
21706
21726
  // src/core/editor/components/border-radius.tsx
21707
- var import_react64 = require("react");
21727
+ var import_react65 = require("react");
21708
21728
  init_popover();
21709
21729
  init_button();
21710
21730
  init_input();
@@ -21718,32 +21738,10 @@ var BorderRadius = ({
21718
21738
  tooltipText = "Border Radius",
21719
21739
  max = 100
21720
21740
  }) => {
21721
- const [inputValue, setInputValue] = (0, import_react64.useState)(value.toString());
21722
- const [isOpen, setIsOpen] = (0, import_react64.useState)(false);
21723
- (0, import_react64.useEffect)(() => {
21724
- setInputValue(value.toString());
21725
- }, [value]);
21741
+ const [isOpen, setIsOpen] = (0, import_react65.useState)(false);
21742
+ const input = useEditableNumber({ value, onChange, min: 0, max });
21726
21743
  const handleSliderChange = (values) => {
21727
- const newValue = values[0];
21728
- onChange(newValue);
21729
- };
21730
- const handleInputChange = (e) => {
21731
- setInputValue(e.target.value);
21732
- };
21733
- const handleInputBlur = () => {
21734
- const parsed = parseInt(inputValue, 10);
21735
- if (isNaN(parsed)) {
21736
- setInputValue(value.toString());
21737
- } else {
21738
- const clamped = Math.max(0, Math.min(max, parsed));
21739
- onChange(clamped);
21740
- setInputValue(clamped.toString());
21741
- }
21742
- };
21743
- const handleInputKeyDown = (e) => {
21744
- if (e.key === "Enter") {
21745
- e.currentTarget.blur();
21746
- }
21744
+ onChange(values[0]);
21747
21745
  };
21748
21746
  return /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(Tooltip, { children: [
21749
21747
  /* @__PURE__ */ (0, import_jsx_runtime96.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
@@ -21773,10 +21771,11 @@ var BorderRadius = ({
21773
21771
  Input,
21774
21772
  {
21775
21773
  type: "number",
21776
- value: inputValue,
21777
- onChange: handleInputChange,
21778
- onBlur: handleInputBlur,
21779
- onKeyDown: handleInputKeyDown,
21774
+ value: input.displayValue,
21775
+ onChange: (e) => input.setLocalValue(e.target.value),
21776
+ onFocus: input.handleFocus,
21777
+ onBlur: input.handleBlur,
21778
+ onKeyDown: input.handleKeyDown,
21780
21779
  className: "w-25 shadow-none rounded-[12px]",
21781
21780
  min: 0,
21782
21781
  max
@@ -21794,7 +21793,7 @@ init_button();
21794
21793
  init_tooltip();
21795
21794
  init_popover();
21796
21795
  var import_lucide_react58 = require("lucide-react");
21797
- var import_react65 = require("react");
21796
+ var import_react66 = require("react");
21798
21797
  init_label();
21799
21798
  init_input();
21800
21799
  var import_jsx_runtime97 = require("react/jsx-runtime");
@@ -21806,32 +21805,10 @@ var StrokeWeight = ({
21806
21805
  tooltipText = "Stroke Weight",
21807
21806
  max = 50
21808
21807
  }) => {
21809
- const [isOpen, setIsOpen] = (0, import_react65.useState)(false);
21810
- const [inputValue, setInputValue] = (0, import_react65.useState)(width.toString());
21811
- (0, import_react65.useEffect)(() => {
21812
- setInputValue(width.toString());
21813
- }, [width]);
21808
+ const [isOpen, setIsOpen] = (0, import_react66.useState)(false);
21809
+ const input = useEditableNumber({ value: width, onChange: onWidthChange, min: 1, max });
21814
21810
  const handleSliderChange = (values) => {
21815
- const newWidth = values[0];
21816
- onWidthChange(newWidth);
21817
- };
21818
- const handleInputChange = (e) => {
21819
- setInputValue(e.target.value);
21820
- };
21821
- const handleInputBlur = () => {
21822
- const parsed = parseInt(inputValue, 10);
21823
- if (isNaN(parsed)) {
21824
- setInputValue(width.toString());
21825
- } else {
21826
- const clamped = Math.max(1, Math.min(max, parsed));
21827
- onWidthChange(clamped);
21828
- setInputValue(clamped.toString());
21829
- }
21830
- };
21831
- const handleInputKeyDown = (e) => {
21832
- if (e.key === "Enter") {
21833
- e.currentTarget.blur();
21834
- }
21811
+ onWidthChange(values[0]);
21835
21812
  };
21836
21813
  return /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(Tooltip, { children: [
21837
21814
  /* @__PURE__ */ (0, import_jsx_runtime97.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
@@ -21882,10 +21859,11 @@ var StrokeWeight = ({
21882
21859
  Input,
21883
21860
  {
21884
21861
  type: "number",
21885
- value: inputValue,
21886
- onChange: handleInputChange,
21887
- onBlur: handleInputBlur,
21888
- onKeyDown: handleInputKeyDown,
21862
+ value: input.displayValue,
21863
+ onChange: (e) => input.setLocalValue(e.target.value),
21864
+ onFocus: input.handleFocus,
21865
+ onBlur: input.handleBlur,
21866
+ onKeyDown: input.handleKeyDown,
21889
21867
  className: "w-25 shadow-none rounded-[12px]",
21890
21868
  min: 1,
21891
21869
  max
@@ -21937,11 +21915,11 @@ function CollapsibleContent2({
21937
21915
  var import_lucide_react59 = require("lucide-react");
21938
21916
  init_tooltip();
21939
21917
  init_popover();
21940
- var import_react67 = require("react");
21918
+ var import_react68 = require("react");
21941
21919
  init_input();
21942
21920
 
21943
21921
  // src/core/editor/hooks/use-padding.ts
21944
- var import_react66 = require("react");
21922
+ var import_react67 = require("react");
21945
21923
  init_editor();
21946
21924
  var import_lodash9 = require("lodash");
21947
21925
 
@@ -21996,7 +21974,7 @@ var usePadding = (options = {}) => {
21996
21974
  const { focusIdx, updateElement, template } = useEditorStore();
21997
21975
  const attributeName = options.attributeName || "padding";
21998
21976
  const effectiveIdx = options.targetIdx ?? focusIdx;
21999
- const { element, parsedPadding } = (0, import_react66.useMemo)(() => {
21977
+ const { element, parsedPadding } = (0, import_react67.useMemo)(() => {
22000
21978
  if (!effectiveIdx || !template) {
22001
21979
  return {
22002
21980
  element: null,
@@ -22008,10 +21986,10 @@ var usePadding = (options = {}) => {
22008
21986
  const rawValue = el?.attributes?.[attributeName];
22009
21987
  return { element: el, parsedPadding: parsePadding(rawValue) };
22010
21988
  }, [effectiveIdx, template, attributeName]);
22011
- const uniformValue = (0, import_react66.useMemo)(() => {
21989
+ const uniformValue = (0, import_react67.useMemo)(() => {
22012
21990
  return getUniformValue(parsedPadding);
22013
21991
  }, [parsedPadding]);
22014
- const updatePadding = (0, import_react66.useCallback)((updates) => {
21992
+ const updatePadding = (0, import_react67.useCallback)((updates) => {
22015
21993
  if (!effectiveIdx || !template || !element) return;
22016
21994
  const newPadding = {
22017
21995
  ...parsedPadding,
@@ -22024,19 +22002,19 @@ var usePadding = (options = {}) => {
22024
22002
  }
22025
22003
  });
22026
22004
  }, [effectiveIdx, template, element, parsedPadding, updateElement, attributeName]);
22027
- const setTop = (0, import_react66.useCallback)((value) => {
22005
+ const setTop = (0, import_react67.useCallback)((value) => {
22028
22006
  updatePadding({ top: value });
22029
22007
  }, [updatePadding]);
22030
- const setRight = (0, import_react66.useCallback)((value) => {
22008
+ const setRight = (0, import_react67.useCallback)((value) => {
22031
22009
  updatePadding({ right: value });
22032
22010
  }, [updatePadding]);
22033
- const setBottom = (0, import_react66.useCallback)((value) => {
22011
+ const setBottom = (0, import_react67.useCallback)((value) => {
22034
22012
  updatePadding({ bottom: value });
22035
22013
  }, [updatePadding]);
22036
- const setLeft = (0, import_react66.useCallback)((value) => {
22014
+ const setLeft = (0, import_react67.useCallback)((value) => {
22037
22015
  updatePadding({ left: value });
22038
22016
  }, [updatePadding]);
22039
- const setUniform = (0, import_react66.useCallback)((value) => {
22017
+ const setUniform = (0, import_react67.useCallback)((value) => {
22040
22018
  updatePadding({ top: value, right: value, bottom: value, left: value });
22041
22019
  }, [updatePadding]);
22042
22020
  return {
@@ -22066,19 +22044,19 @@ var BetterPadding = ({
22066
22044
  targetIdx,
22067
22045
  tooltipText = "Padding"
22068
22046
  }) => {
22069
- const [isOpen, setIsOpen] = (0, import_react67.useState)(false);
22070
- const [openSection, setOpenSection] = (0, import_react67.useState)(null);
22047
+ const [isOpen, setIsOpen] = (0, import_react68.useState)(false);
22048
+ const [openSection, setOpenSection] = (0, import_react68.useState)(null);
22071
22049
  const padding = usePadding({ targetIdx });
22072
22050
  const innerPadding = usePadding({ attributeName: "inner-padding", targetIdx });
22073
22051
  const iconPadding = usePadding({ attributeName: "icon-padding", targetIdx });
22074
22052
  const textPadding = usePadding({ attributeName: "text-padding", targetIdx });
22075
- const handleToggle = (0, import_react67.useCallback)((section) => {
22053
+ const handleToggle = (0, import_react68.useCallback)((section) => {
22076
22054
  setOpenSection((prev) => prev === section ? null : section);
22077
22055
  }, []);
22078
- const handleToggleNormal = (0, import_react67.useCallback)(() => handleToggle("normal"), [handleToggle]);
22079
- const handleToggleInner = (0, import_react67.useCallback)(() => handleToggle("inner"), [handleToggle]);
22080
- const handleToggleIcon = (0, import_react67.useCallback)(() => handleToggle("icon"), [handleToggle]);
22081
- const handleToggleText = (0, import_react67.useCallback)(() => handleToggle("text"), [handleToggle]);
22056
+ const handleToggleNormal = (0, import_react68.useCallback)(() => handleToggle("normal"), [handleToggle]);
22057
+ const handleToggleInner = (0, import_react68.useCallback)(() => handleToggle("inner"), [handleToggle]);
22058
+ const handleToggleIcon = (0, import_react68.useCallback)(() => handleToggle("icon"), [handleToggle]);
22059
+ const handleToggleText = (0, import_react68.useCallback)(() => handleToggle("text"), [handleToggle]);
22082
22060
  return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)(Tooltip, { children: [
22083
22061
  /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
22084
22062
  /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(
@@ -22133,105 +22111,14 @@ var BetterPadding = ({
22133
22111
  ] });
22134
22112
  };
22135
22113
  var PaddingSectionUI = ({ label, isOpen, onToggle, data }) => {
22136
- const [sliderValue, setSliderValue] = (0, import_react67.useState)(data.uniformValue ?? data.top);
22137
- const [sliderInputValue, setSliderInputValue] = (0, import_react67.useState)((data.uniformValue ?? data.top).toString());
22138
- const [topInput, setTopInput] = (0, import_react67.useState)(data.top.toString());
22139
- const [rightInput, setRightInput] = (0, import_react67.useState)(data.right.toString());
22140
- const [bottomInput, setBottomInput] = (0, import_react67.useState)(data.bottom.toString());
22141
- const [leftInput, setLeftInput] = (0, import_react67.useState)(data.left.toString());
22142
- (0, import_react67.useEffect)(() => {
22143
- setSliderValue(data.uniformValue ?? data.top);
22144
- setSliderInputValue((data.uniformValue ?? data.top).toString());
22145
- }, [data.uniformValue, data.top]);
22146
- (0, import_react67.useEffect)(() => {
22147
- setTopInput(data.top.toString());
22148
- }, [data.top]);
22149
- (0, import_react67.useEffect)(() => {
22150
- setRightInput(data.right.toString());
22151
- }, [data.right]);
22152
- (0, import_react67.useEffect)(() => {
22153
- setBottomInput(data.bottom.toString());
22154
- }, [data.bottom]);
22155
- (0, import_react67.useEffect)(() => {
22156
- setLeftInput(data.left.toString());
22157
- }, [data.left]);
22158
- const handleKeyDown = (0, import_react67.useCallback)((e) => {
22159
- if (e.key === "Enter") {
22160
- e.currentTarget.blur();
22161
- }
22162
- }, []);
22163
- const handleSliderChange = (0, import_react67.useCallback)((values) => {
22164
- const newValue = values[0];
22165
- setSliderValue(newValue);
22166
- setSliderInputValue(newValue.toString());
22167
- data.setUniform(newValue);
22114
+ const sliderInput = useEditableNumber({ value: data.uniformValue ?? data.top, onChange: data.setUniform, min: 0, max: PADDING_MAX });
22115
+ const topInput = useEditableNumber({ value: data.top, onChange: data.setTop, min: 0, max: PADDING_MAX });
22116
+ const rightInput = useEditableNumber({ value: data.right, onChange: data.setRight, min: 0, max: PADDING_MAX });
22117
+ const bottomInput = useEditableNumber({ value: data.bottom, onChange: data.setBottom, min: 0, max: PADDING_MAX });
22118
+ const leftInput = useEditableNumber({ value: data.left, onChange: data.setLeft, min: 0, max: PADDING_MAX });
22119
+ const handleSliderChange = (0, import_react68.useCallback)((values) => {
22120
+ data.setUniform(values[0]);
22168
22121
  }, [data]);
22169
- const handleSliderInputChange = (0, import_react67.useCallback)((e) => {
22170
- setSliderInputValue(e.target.value);
22171
- }, []);
22172
- const handleSliderInputBlur = (0, import_react67.useCallback)(() => {
22173
- const parsed = parseInt(sliderInputValue, 10);
22174
- if (isNaN(parsed) || sliderInputValue === "") {
22175
- setSliderInputValue(sliderValue.toString());
22176
- } else {
22177
- const clamped = Math.max(0, Math.min(PADDING_MAX, parsed));
22178
- setSliderValue(clamped);
22179
- setSliderInputValue(clamped.toString());
22180
- data.setUniform(clamped);
22181
- }
22182
- }, [sliderInputValue, sliderValue, data]);
22183
- const handleTopChange = (0, import_react67.useCallback)((e) => {
22184
- setTopInput(e.target.value);
22185
- }, []);
22186
- const handleTopBlur = (0, import_react67.useCallback)(() => {
22187
- const parsed = parseInt(topInput, 10);
22188
- if (isNaN(parsed)) {
22189
- setTopInput(data.top.toString());
22190
- } else {
22191
- const clamped = Math.max(0, Math.min(PADDING_MAX, parsed));
22192
- data.setTop(clamped);
22193
- setTopInput(clamped.toString());
22194
- }
22195
- }, [topInput, data]);
22196
- const handleRightChange = (0, import_react67.useCallback)((e) => {
22197
- setRightInput(e.target.value);
22198
- }, []);
22199
- const handleRightBlur = (0, import_react67.useCallback)(() => {
22200
- const parsed = parseInt(rightInput, 10);
22201
- if (isNaN(parsed)) {
22202
- setRightInput(data.right.toString());
22203
- } else {
22204
- const clamped = Math.max(0, Math.min(PADDING_MAX, parsed));
22205
- data.setRight(clamped);
22206
- setRightInput(clamped.toString());
22207
- }
22208
- }, [rightInput, data]);
22209
- const handleBottomChange = (0, import_react67.useCallback)((e) => {
22210
- setBottomInput(e.target.value);
22211
- }, []);
22212
- const handleBottomBlur = (0, import_react67.useCallback)(() => {
22213
- const parsed = parseInt(bottomInput, 10);
22214
- if (isNaN(parsed)) {
22215
- setBottomInput(data.bottom.toString());
22216
- } else {
22217
- const clamped = Math.max(0, Math.min(PADDING_MAX, parsed));
22218
- data.setBottom(clamped);
22219
- setBottomInput(clamped.toString());
22220
- }
22221
- }, [bottomInput, data]);
22222
- const handleLeftChange = (0, import_react67.useCallback)((e) => {
22223
- setLeftInput(e.target.value);
22224
- }, []);
22225
- const handleLeftBlur = (0, import_react67.useCallback)(() => {
22226
- const parsed = parseInt(leftInput, 10);
22227
- if (isNaN(parsed)) {
22228
- setLeftInput(data.left.toString());
22229
- } else {
22230
- const clamped = Math.max(0, Math.min(PADDING_MAX, parsed));
22231
- data.setLeft(clamped);
22232
- setLeftInput(clamped.toString());
22233
- }
22234
- }, [leftInput, data]);
22235
22122
  return /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)(Collapsible, { open: isOpen, onOpenChange: onToggle, children: [
22236
22123
  /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(Button, { variant: "outline", className: "w-full shadow-none rounded-[12px]", children: /* @__PURE__ */ (0, import_jsx_runtime99.jsxs)("div", { className: "w-full flex flex-row items-center justify-between gap-2", children: [
22237
22124
  /* @__PURE__ */ (0, import_jsx_runtime99.jsx)("p", { children: label }),
@@ -22242,7 +22129,7 @@ var PaddingSectionUI = ({ label, isOpen, onToggle, data }) => {
22242
22129
  /* @__PURE__ */ (0, import_jsx_runtime99.jsx)(
22243
22130
  Slider2,
22244
22131
  {
22245
- value: [sliderValue],
22132
+ value: [data.uniformValue ?? data.top],
22246
22133
  onValueChange: handleSliderChange,
22247
22134
  min: 0,
22248
22135
  max: PADDING_MAX,
@@ -22253,10 +22140,11 @@ var PaddingSectionUI = ({ label, isOpen, onToggle, data }) => {
22253
22140
  Input,
22254
22141
  {
22255
22142
  type: "number",
22256
- value: sliderInputValue,
22257
- onChange: handleSliderInputChange,
22258
- onBlur: handleSliderInputBlur,
22259
- onKeyDown: handleKeyDown,
22143
+ value: sliderInput.displayValue,
22144
+ onChange: (e) => sliderInput.setLocalValue(e.target.value),
22145
+ onFocus: sliderInput.handleFocus,
22146
+ onBlur: sliderInput.handleBlur,
22147
+ onKeyDown: sliderInput.handleKeyDown,
22260
22148
  className: "w-25 shadow-none rounded-[12px]",
22261
22149
  min: 0,
22262
22150
  max: PADDING_MAX
@@ -22271,10 +22159,11 @@ var PaddingSectionUI = ({ label, isOpen, onToggle, data }) => {
22271
22159
  Input,
22272
22160
  {
22273
22161
  type: "number",
22274
- value: topInput,
22275
- onChange: handleTopChange,
22276
- onBlur: handleTopBlur,
22277
- onKeyDown: handleKeyDown,
22162
+ value: topInput.displayValue,
22163
+ onChange: (e) => topInput.setLocalValue(e.target.value),
22164
+ onFocus: topInput.handleFocus,
22165
+ onBlur: topInput.handleBlur,
22166
+ onKeyDown: topInput.handleKeyDown,
22278
22167
  className: "w-20 shadow-none rounded-[12px]",
22279
22168
  min: 0,
22280
22169
  max: PADDING_MAX
@@ -22287,10 +22176,11 @@ var PaddingSectionUI = ({ label, isOpen, onToggle, data }) => {
22287
22176
  Input,
22288
22177
  {
22289
22178
  type: "number",
22290
- value: bottomInput,
22291
- onChange: handleBottomChange,
22292
- onBlur: handleBottomBlur,
22293
- onKeyDown: handleKeyDown,
22179
+ value: bottomInput.displayValue,
22180
+ onChange: (e) => bottomInput.setLocalValue(e.target.value),
22181
+ onFocus: bottomInput.handleFocus,
22182
+ onBlur: bottomInput.handleBlur,
22183
+ onKeyDown: bottomInput.handleKeyDown,
22294
22184
  className: "w-20 shadow-none rounded-[12px]",
22295
22185
  min: 0,
22296
22186
  max: PADDING_MAX
@@ -22305,10 +22195,11 @@ var PaddingSectionUI = ({ label, isOpen, onToggle, data }) => {
22305
22195
  Input,
22306
22196
  {
22307
22197
  type: "number",
22308
- value: leftInput,
22309
- onChange: handleLeftChange,
22310
- onBlur: handleLeftBlur,
22311
- onKeyDown: handleKeyDown,
22198
+ value: leftInput.displayValue,
22199
+ onChange: (e) => leftInput.setLocalValue(e.target.value),
22200
+ onFocus: leftInput.handleFocus,
22201
+ onBlur: leftInput.handleBlur,
22202
+ onKeyDown: leftInput.handleKeyDown,
22312
22203
  className: "w-20 shadow-none rounded-[12px]",
22313
22204
  min: 0,
22314
22205
  max: PADDING_MAX
@@ -22321,10 +22212,11 @@ var PaddingSectionUI = ({ label, isOpen, onToggle, data }) => {
22321
22212
  Input,
22322
22213
  {
22323
22214
  type: "number",
22324
- value: rightInput,
22325
- onChange: handleRightChange,
22326
- onBlur: handleRightBlur,
22327
- onKeyDown: handleKeyDown,
22215
+ value: rightInput.displayValue,
22216
+ onChange: (e) => rightInput.setLocalValue(e.target.value),
22217
+ onFocus: rightInput.handleFocus,
22218
+ onBlur: rightInput.handleBlur,
22219
+ onKeyDown: rightInput.handleKeyDown,
22328
22220
  className: "w-20 shadow-none rounded-[12px]",
22329
22221
  min: 0,
22330
22222
  max: PADDING_MAX
@@ -22395,45 +22287,45 @@ var import_jsx_runtime101 = require("react/jsx-runtime");
22395
22287
  var ColumnStyles = () => {
22396
22288
  const { focusIdx, template, updateElement } = useEditorStore();
22397
22289
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
22398
- const columnIdx = (0, import_react68.useMemo)(() => {
22290
+ const columnIdx = (0, import_react69.useMemo)(() => {
22399
22291
  if (!focusIdx) return void 0;
22400
22292
  return getParentIdx(focusIdx);
22401
22293
  }, [focusIdx]);
22402
- const column = (0, import_react68.useMemo)(() => {
22294
+ const column = (0, import_react69.useMemo)(() => {
22403
22295
  if (!columnIdx || !template) return void 0;
22404
22296
  return getValueByIdx(template, columnIdx);
22405
22297
  }, [columnIdx, template]);
22406
22298
  const currentBgColor = column?.attributes?.["background-color"];
22407
- const border = (0, import_react68.useMemo)(() => {
22299
+ const border = (0, import_react69.useMemo)(() => {
22408
22300
  return parseBorder(column?.attributes?.border);
22409
22301
  }, [column]);
22410
- const borderRadiusValue = (0, import_react68.useMemo)(() => {
22302
+ const borderRadiusValue = (0, import_react69.useMemo)(() => {
22411
22303
  return parseBorderRadius(column?.attributes?.["border-radius"]);
22412
22304
  }, [column]);
22413
- const padding = (0, import_react68.useMemo)(() => {
22305
+ const padding = (0, import_react69.useMemo)(() => {
22414
22306
  return parsePadding(column?.attributes?.padding);
22415
22307
  }, [column]);
22416
- const paddingUniformValue = (0, import_react68.useMemo)(() => {
22308
+ const paddingUniformValue = (0, import_react69.useMemo)(() => {
22417
22309
  return getUniformValue(padding);
22418
22310
  }, [padding]);
22419
- const handleOpenBgColorPicker = (0, import_react68.useCallback)(() => {
22311
+ const handleOpenBgColorPicker = (0, import_react69.useCallback)(() => {
22420
22312
  setColorType("Column color");
22421
22313
  setColorTarget("columnBgColor");
22422
22314
  setActiveView("color");
22423
22315
  }, [setColorType, setColorTarget, setActiveView]);
22424
- const handleOpenStrokeColorPicker = (0, import_react68.useCallback)(() => {
22316
+ const handleOpenStrokeColorPicker = (0, import_react69.useCallback)(() => {
22425
22317
  setColorType("Column Stroke");
22426
22318
  setColorTarget("columnStrokeColor");
22427
22319
  setActiveView("color");
22428
22320
  }, [setColorType, setColorTarget, setActiveView]);
22429
- const handleStrokeWidthChange = (0, import_react68.useCallback)((width) => {
22321
+ const handleStrokeWidthChange = (0, import_react69.useCallback)((width) => {
22430
22322
  if (!columnIdx || !column) return;
22431
22323
  const newBorder = formatBorder({ ...border, width });
22432
22324
  updateElement(columnIdx, {
22433
22325
  attributes: { ...column.attributes, border: newBorder }
22434
22326
  });
22435
22327
  }, [columnIdx, column, border, updateElement]);
22436
- const handleStrokeEnabledChange = (0, import_react68.useCallback)((enabled) => {
22328
+ const handleStrokeEnabledChange = (0, import_react69.useCallback)((enabled) => {
22437
22329
  if (!columnIdx || !column) return;
22438
22330
  const newBorder = formatBorder({
22439
22331
  ...border,
@@ -22443,32 +22335,32 @@ var ColumnStyles = () => {
22443
22335
  attributes: { ...column.attributes, border: newBorder }
22444
22336
  });
22445
22337
  }, [columnIdx, column, border, updateElement]);
22446
- const handleBorderRadiusChange = (0, import_react68.useCallback)((value) => {
22338
+ const handleBorderRadiusChange = (0, import_react69.useCallback)((value) => {
22447
22339
  if (!columnIdx || !column) return;
22448
22340
  updateElement(columnIdx, {
22449
22341
  attributes: { ...column.attributes, "border-radius": formatBorderRadius(value) }
22450
22342
  });
22451
22343
  }, [columnIdx, column, updateElement]);
22452
- const updatePadding = (0, import_react68.useCallback)((updates) => {
22344
+ const updatePadding = (0, import_react69.useCallback)((updates) => {
22453
22345
  if (!columnIdx || !column) return;
22454
22346
  const newPadding = { ...padding, ...updates };
22455
22347
  updateElement(columnIdx, {
22456
22348
  attributes: { ...column.attributes, padding: formatPadding(newPadding) }
22457
22349
  });
22458
22350
  }, [columnIdx, column, padding, updateElement]);
22459
- const handlePaddingTopChange = (0, import_react68.useCallback)((value) => {
22351
+ const handlePaddingTopChange = (0, import_react69.useCallback)((value) => {
22460
22352
  updatePadding({ top: value });
22461
22353
  }, [updatePadding]);
22462
- const handlePaddingRightChange = (0, import_react68.useCallback)((value) => {
22354
+ const handlePaddingRightChange = (0, import_react69.useCallback)((value) => {
22463
22355
  updatePadding({ right: value });
22464
22356
  }, [updatePadding]);
22465
- const handlePaddingBottomChange = (0, import_react68.useCallback)((value) => {
22357
+ const handlePaddingBottomChange = (0, import_react69.useCallback)((value) => {
22466
22358
  updatePadding({ bottom: value });
22467
22359
  }, [updatePadding]);
22468
- const handlePaddingLeftChange = (0, import_react68.useCallback)((value) => {
22360
+ const handlePaddingLeftChange = (0, import_react69.useCallback)((value) => {
22469
22361
  updatePadding({ left: value });
22470
22362
  }, [updatePadding]);
22471
- const handlePaddingUniformChange = (0, import_react68.useCallback)((value) => {
22363
+ const handlePaddingUniformChange = (0, import_react69.useCallback)((value) => {
22472
22364
  updatePadding({ top: value, right: value, bottom: value, left: value });
22473
22365
  }, [updatePadding]);
22474
22366
  return /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)(import_jsx_runtime101.Fragment, { children: [
@@ -22561,9 +22453,9 @@ var TextToolbar = () => {
22561
22453
  const template = useEditorStore((s) => s.template);
22562
22454
  const mergeFields = useEditorStore((s) => s.mergeFields);
22563
22455
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
22564
- const [updateCounter, forceUpdate] = (0, import_react69.useState)(0);
22565
- const [overflowOpen, setOverflowOpen] = (0, import_react69.useState)(false);
22566
- const isInSectionColumn = (0, import_react69.useMemo)(() => {
22456
+ const [updateCounter, forceUpdate] = (0, import_react70.useState)(0);
22457
+ const [overflowOpen, setOverflowOpen] = (0, import_react70.useState)(false);
22458
+ const isInSectionColumn = (0, import_react70.useMemo)(() => {
22567
22459
  if (!focusIdx || !template) return false;
22568
22460
  const columnIdx = getParentIdx(focusIdx);
22569
22461
  if (!columnIdx) return false;
@@ -22572,7 +22464,7 @@ var TextToolbar = () => {
22572
22464
  const section = getValueByIdx(template, sectionIdx);
22573
22465
  return section?.type === "section-column";
22574
22466
  }, [focusIdx, template]);
22575
- (0, import_react69.useEffect)(() => {
22467
+ (0, import_react70.useEffect)(() => {
22576
22468
  if (!tiptapEditor) return;
22577
22469
  const handler = () => forceUpdate((n) => n + 1);
22578
22470
  tiptapEditor.on("selectionUpdate", handler);
@@ -22582,7 +22474,7 @@ var TextToolbar = () => {
22582
22474
  window.removeEventListener("toolbar-refresh", handler);
22583
22475
  };
22584
22476
  }, [tiptapEditor]);
22585
- const activeType = (0, import_react69.useMemo)(() => {
22477
+ const activeType = (0, import_react70.useMemo)(() => {
22586
22478
  if (!tiptapEditor) return "paragraph";
22587
22479
  const paragraphAttrs = tiptapEditor.getAttributes("paragraph");
22588
22480
  const headingLevel = paragraphAttrs.headingLevel || 0;
@@ -22591,14 +22483,14 @@ var TextToolbar = () => {
22591
22483
  if (headingLevel === 3) return "h3";
22592
22484
  return "paragraph";
22593
22485
  }, [tiptapEditor, updateCounter]);
22594
- const currentTypeConfig = (0, import_react69.useMemo)(() => {
22486
+ const currentTypeConfig = (0, import_react70.useMemo)(() => {
22595
22487
  return TEXT_TYPE_OPTIONS.find((t) => t.type === activeType) || TEXT_TYPE_OPTIONS[0];
22596
22488
  }, [activeType]);
22597
- const baseFontSize = (0, import_react69.useMemo)(() => {
22489
+ const baseFontSize = (0, import_react70.useMemo)(() => {
22598
22490
  if (!textEditingStyles?.fontSize) return DEFAULT_FONT_SIZE;
22599
22491
  return parseFontSize(textEditingStyles.fontSize);
22600
22492
  }, [textEditingStyles?.fontSize]);
22601
- const currentFontSize = (0, import_react69.useMemo)(() => {
22493
+ const currentFontSize = (0, import_react70.useMemo)(() => {
22602
22494
  if (!tiptapEditor) return DEFAULT_FONT_SIZE;
22603
22495
  const textStyleAttrs = tiptapEditor.getAttributes("textStyle");
22604
22496
  if (textStyleAttrs.fontSize) {
@@ -22607,18 +22499,18 @@ var TextToolbar = () => {
22607
22499
  const multiplier = HEADING_MULTIPLIERS[activeType] || 1;
22608
22500
  return Math.round(baseFontSize * multiplier);
22609
22501
  }, [tiptapEditor, updateCounter, activeType, baseFontSize]);
22610
- const handleFontSizeChange = (0, import_react69.useCallback)((size) => {
22502
+ const handleFontSizeChange = (0, import_react70.useCallback)((size) => {
22611
22503
  if (!tiptapEditor) return;
22612
22504
  tiptapEditor.chain().focus().setFontSize(`${size}px`).run();
22613
22505
  forceUpdate((n) => n + 1);
22614
22506
  }, [tiptapEditor]);
22615
- const currentAlignment = (0, import_react69.useMemo)(() => {
22507
+ const currentAlignment = (0, import_react70.useMemo)(() => {
22616
22508
  if (!tiptapEditor) return "left";
22617
22509
  const paragraphAttrs = tiptapEditor.getAttributes("paragraph");
22618
22510
  if (paragraphAttrs.textAlign) return paragraphAttrs.textAlign;
22619
22511
  return "left";
22620
22512
  }, [tiptapEditor, updateCounter]);
22621
- const handleCycleAlignment = (0, import_react69.useCallback)(() => {
22513
+ const handleCycleAlignment = (0, import_react70.useCallback)(() => {
22622
22514
  if (!tiptapEditor) return;
22623
22515
  const currentIndex = ALIGNMENTS.indexOf(currentAlignment);
22624
22516
  const nextIndex = (currentIndex + 1) % ALIGNMENTS.length;
@@ -22626,52 +22518,52 @@ var TextToolbar = () => {
22626
22518
  tiptapEditor.chain().focus().setTextAlign(nextAlignment).run();
22627
22519
  forceUpdate((n) => n + 1);
22628
22520
  }, [tiptapEditor, currentAlignment]);
22629
- const handleCycleList = (0, import_react69.useCallback)(() => {
22521
+ const handleCycleList = (0, import_react70.useCallback)(() => {
22630
22522
  }, [tiptapEditor]);
22631
- const isInHeading = (0, import_react69.useMemo)(() => {
22523
+ const isInHeading = (0, import_react70.useMemo)(() => {
22632
22524
  if (!tiptapEditor) return false;
22633
22525
  const paragraphAttrs = tiptapEditor.getAttributes("paragraph");
22634
22526
  return (paragraphAttrs.headingLevel || 0) > 0;
22635
22527
  }, [tiptapEditor, updateCounter]);
22636
- const handleToggleBold = (0, import_react69.useCallback)(() => {
22528
+ const handleToggleBold = (0, import_react70.useCallback)(() => {
22637
22529
  if (!tiptapEditor) return;
22638
22530
  if (isInHeading) return;
22639
22531
  tiptapEditor.chain().focus().toggleBold().run();
22640
22532
  forceUpdate((n) => n + 1);
22641
22533
  }, [tiptapEditor, isInHeading]);
22642
- const handleToggleItalic = (0, import_react69.useCallback)(() => {
22534
+ const handleToggleItalic = (0, import_react70.useCallback)(() => {
22643
22535
  if (!tiptapEditor) return;
22644
22536
  tiptapEditor.chain().focus().toggleItalic().run();
22645
22537
  forceUpdate((n) => n + 1);
22646
22538
  }, [tiptapEditor]);
22647
- const handleToggleUnderline = (0, import_react69.useCallback)(() => {
22539
+ const handleToggleUnderline = (0, import_react70.useCallback)(() => {
22648
22540
  if (!tiptapEditor) return;
22649
22541
  tiptapEditor.chain().focus().toggleUnderline().run();
22650
22542
  forceUpdate((n) => n + 1);
22651
22543
  }, [tiptapEditor]);
22652
- const handleToggleStrike = (0, import_react69.useCallback)(() => {
22544
+ const handleToggleStrike = (0, import_react70.useCallback)(() => {
22653
22545
  if (!tiptapEditor) return;
22654
22546
  tiptapEditor.chain().focus().toggleStrike().run();
22655
22547
  forceUpdate((n) => n + 1);
22656
22548
  }, [tiptapEditor]);
22657
- const isBoldActive = (0, import_react69.useMemo)(() => {
22549
+ const isBoldActive = (0, import_react70.useMemo)(() => {
22658
22550
  if (!tiptapEditor) return false;
22659
22551
  if (isInHeading) return true;
22660
22552
  return tiptapEditor.isActive("bold");
22661
22553
  }, [tiptapEditor, updateCounter, isInHeading]);
22662
- const isItalicActive = (0, import_react69.useMemo)(() => {
22554
+ const isItalicActive = (0, import_react70.useMemo)(() => {
22663
22555
  if (!tiptapEditor) return false;
22664
22556
  return tiptapEditor.isActive("italic");
22665
22557
  }, [tiptapEditor, updateCounter]);
22666
- const isUnderlineActive = (0, import_react69.useMemo)(() => {
22558
+ const isUnderlineActive = (0, import_react70.useMemo)(() => {
22667
22559
  if (!tiptapEditor) return false;
22668
22560
  return tiptapEditor.isActive("underline");
22669
22561
  }, [tiptapEditor, updateCounter]);
22670
- const isStrikeActive = (0, import_react69.useMemo)(() => {
22562
+ const isStrikeActive = (0, import_react70.useMemo)(() => {
22671
22563
  if (!tiptapEditor) return false;
22672
22564
  return tiptapEditor.isActive("strike");
22673
22565
  }, [tiptapEditor, updateCounter]);
22674
- const handleSetType = (0, import_react69.useCallback)((type) => {
22566
+ const handleSetType = (0, import_react70.useCallback)((type) => {
22675
22567
  if (!tiptapEditor) return;
22676
22568
  const levelMap = {
22677
22569
  paragraph: 0,
@@ -22691,25 +22583,25 @@ var TextToolbar = () => {
22691
22583
  deleteElement(focusIdx);
22692
22584
  }
22693
22585
  };
22694
- const handleOpenTextColorPicker = (0, import_react69.useCallback)(() => {
22586
+ const handleOpenTextColorPicker = (0, import_react70.useCallback)(() => {
22695
22587
  setColorType("Text color");
22696
22588
  setColorTarget("textColor");
22697
22589
  setActiveView("color");
22698
22590
  }, [setColorType, setColorTarget, setActiveView]);
22699
- const handleOpenHighlightColorPicker = (0, import_react69.useCallback)(() => {
22591
+ const handleOpenHighlightColorPicker = (0, import_react70.useCallback)(() => {
22700
22592
  setColorType("Highlight color");
22701
22593
  setColorTarget("highlightColor");
22702
22594
  setActiveView("color");
22703
22595
  }, [setColorType, setColorTarget, setActiveView]);
22704
- const currentTextColor = (0, import_react69.useMemo)(() => {
22596
+ const currentTextColor = (0, import_react70.useMemo)(() => {
22705
22597
  if (!tiptapEditor) return "#000000";
22706
22598
  return tiptapEditor.getAttributes("textStyle").color || "#000000";
22707
22599
  }, [tiptapEditor, updateCounter]);
22708
- const currentHighlightColor = (0, import_react69.useMemo)(() => {
22600
+ const currentHighlightColor = (0, import_react70.useMemo)(() => {
22709
22601
  if (!tiptapEditor) return "transparent";
22710
22602
  return tiptapEditor.getAttributes("textStyle").backgroundColor || "transparent";
22711
22603
  }, [tiptapEditor, updateCounter]);
22712
- const extractKnownFont = (0, import_react69.useCallback)((fontStack) => {
22604
+ const extractKnownFont = (0, import_react70.useCallback)((fontStack) => {
22713
22605
  if (!fontStack) return "Arial";
22714
22606
  const fonts = fontStack.split(",").map((f) => f.trim().replace(/['"]/g, ""));
22715
22607
  for (const font of fonts) {
@@ -22718,7 +22610,7 @@ var TextToolbar = () => {
22718
22610
  }
22719
22611
  return "Arial";
22720
22612
  }, []);
22721
- const currentFontFamily = (0, import_react69.useMemo)(() => {
22613
+ const currentFontFamily = (0, import_react70.useMemo)(() => {
22722
22614
  if (!tiptapEditor) return "Arial";
22723
22615
  const fontFamily = tiptapEditor.getAttributes("textStyle").fontFamily;
22724
22616
  if (fontFamily) {
@@ -22726,7 +22618,7 @@ var TextToolbar = () => {
22726
22618
  }
22727
22619
  return extractKnownFont(textEditingStyles?.fontFamily);
22728
22620
  }, [tiptapEditor, updateCounter, textEditingStyles?.fontFamily, extractKnownFont]);
22729
- const handleSetFontFamily = (0, import_react69.useCallback)((font) => {
22621
+ const handleSetFontFamily = (0, import_react70.useCallback)((font) => {
22730
22622
  if (!tiptapEditor) return;
22731
22623
  tiptapEditor.chain().focus().setFontFamily(font).run();
22732
22624
  forceUpdate((n) => n + 1);
@@ -23266,7 +23158,7 @@ var MergeFieldItem = ({ isResponsive, isInSectionColumn, tiptapEditor, mergeFiel
23266
23158
  };
23267
23159
 
23268
23160
  // src/core/editor/components/element-gear/button/toolbar.tsx
23269
- var import_react74 = require("react");
23161
+ var import_react75 = require("react");
23270
23162
  init_editor();
23271
23163
  init_sidebar_context();
23272
23164
  var import_lodash13 = require("lodash");
@@ -23276,20 +23168,20 @@ var import_lucide_react62 = require("lucide-react");
23276
23168
  init_tooltip();
23277
23169
 
23278
23170
  // src/core/editor/hooks/use-border-radius.ts
23279
- var import_react70 = require("react");
23171
+ var import_react71 = require("react");
23280
23172
  init_editor();
23281
23173
  var import_lodash10 = require("lodash");
23282
23174
  var useBorderRadius = (options = {}) => {
23283
23175
  const { focusIdx, updateElement, template } = useEditorStore();
23284
23176
  const attributeName = options.attributeName || "border-radius";
23285
- const currentValue = (0, import_react70.useMemo)(() => {
23177
+ const currentValue = (0, import_react71.useMemo)(() => {
23286
23178
  if (!focusIdx || !template) return 0;
23287
23179
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
23288
23180
  const element = (0, import_lodash10.get)(template, path);
23289
23181
  const rawValue = element?.attributes?.[attributeName];
23290
23182
  return parseBorderRadius(rawValue);
23291
23183
  }, [focusIdx, template, attributeName]);
23292
- const handleChange = (0, import_react70.useCallback)((value) => {
23184
+ const handleChange = (0, import_react71.useCallback)((value) => {
23293
23185
  if (!focusIdx || !template) return;
23294
23186
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
23295
23187
  const element = (0, import_lodash10.get)(template, path);
@@ -23308,14 +23200,14 @@ var useBorderRadius = (options = {}) => {
23308
23200
  };
23309
23201
 
23310
23202
  // src/core/editor/hooks/use-border.ts
23311
- var import_react71 = require("react");
23203
+ var import_react72 = require("react");
23312
23204
  init_editor();
23313
23205
  var import_lodash11 = require("lodash");
23314
23206
  init_border();
23315
23207
  var useBorder = (options = {}) => {
23316
23208
  const { focusIdx, updateElement, template } = useEditorStore();
23317
23209
  const attributeName = options.attributeName || "border";
23318
- const { element, parsedBorder } = (0, import_react71.useMemo)(() => {
23210
+ const { element, parsedBorder } = (0, import_react72.useMemo)(() => {
23319
23211
  if (!focusIdx || !template) {
23320
23212
  return { element: null, parsedBorder: { width: 0, style: "solid", color: "#000000" } };
23321
23213
  }
@@ -23327,7 +23219,7 @@ var useBorder = (options = {}) => {
23327
23219
  const width = parsedBorder.width;
23328
23220
  const color = parsedBorder.color;
23329
23221
  const isEnabled = width > 0;
23330
- const updateBorder = (0, import_react71.useCallback)((updates) => {
23222
+ const updateBorder = (0, import_react72.useCallback)((updates) => {
23331
23223
  if (!focusIdx || !template || !element) return;
23332
23224
  const newBorder = {
23333
23225
  ...parsedBorder,
@@ -23340,13 +23232,13 @@ var useBorder = (options = {}) => {
23340
23232
  }
23341
23233
  });
23342
23234
  }, [focusIdx, template, element, parsedBorder, updateElement, attributeName]);
23343
- const setWidth = (0, import_react71.useCallback)((newWidth) => {
23235
+ const setWidth = (0, import_react72.useCallback)((newWidth) => {
23344
23236
  updateBorder({ width: newWidth });
23345
23237
  }, [updateBorder]);
23346
- const setColor = (0, import_react71.useCallback)((newColor) => {
23238
+ const setColor = (0, import_react72.useCallback)((newColor) => {
23347
23239
  updateBorder({ color: newColor });
23348
23240
  }, [updateBorder]);
23349
- const setEnabled = (0, import_react71.useCallback)((enabled) => {
23241
+ const setEnabled = (0, import_react72.useCallback)((enabled) => {
23350
23242
  if (enabled) {
23351
23243
  updateBorder({ width: parsedBorder.width === 0 ? 1 : parsedBorder.width });
23352
23244
  } else {
@@ -23364,7 +23256,7 @@ var useBorder = (options = {}) => {
23364
23256
  };
23365
23257
 
23366
23258
  // src/core/editor/hooks/use-size.ts
23367
- var import_react72 = require("react");
23259
+ var import_react73 = require("react");
23368
23260
  init_editor();
23369
23261
  var import_lodash12 = require("lodash");
23370
23262
  var parseSize = (value, defaultValue) => {
@@ -23381,7 +23273,7 @@ var useSize = (options = {}) => {
23381
23273
  const defaultHeight = options.defaultHeight ?? 40;
23382
23274
  const widthUnit = options.widthUnit || "%";
23383
23275
  const heightUnit = options.heightUnit || "px";
23384
- const { element, width, height } = (0, import_react72.useMemo)(() => {
23276
+ const { element, width, height } = (0, import_react73.useMemo)(() => {
23385
23277
  if (!focusIdx || !template) {
23386
23278
  return { element: null, width: defaultWidth, height: defaultHeight };
23387
23279
  }
@@ -23393,13 +23285,13 @@ var useSize = (options = {}) => {
23393
23285
  height: parseSize(el?.attributes?.[heightAttribute], defaultHeight)
23394
23286
  };
23395
23287
  }, [focusIdx, template, widthAttribute, heightAttribute, defaultWidth, defaultHeight]);
23396
- const setWidth = (0, import_react72.useCallback)((value) => {
23288
+ const setWidth = (0, import_react73.useCallback)((value) => {
23397
23289
  if (!focusIdx || !template || !element) return;
23398
23290
  updateElement(focusIdx, {
23399
23291
  attributes: { ...element.attributes, [widthAttribute]: formatSize(value, widthUnit) }
23400
23292
  });
23401
23293
  }, [focusIdx, template, element, updateElement, widthAttribute, widthUnit]);
23402
- const setHeight = (0, import_react72.useCallback)((value) => {
23294
+ const setHeight = (0, import_react73.useCallback)((value) => {
23403
23295
  if (!focusIdx || !template || !element) return;
23404
23296
  updateElement(focusIdx, {
23405
23297
  attributes: { ...element.attributes, [heightAttribute]: formatSize(value, heightUnit) }
@@ -23415,137 +23307,63 @@ init_button();
23415
23307
  var import_lucide_react61 = require("lucide-react");
23416
23308
  init_label();
23417
23309
  init_input();
23418
- var import_react73 = require("react");
23310
+ var import_react74 = require("react");
23419
23311
  init_editor();
23420
23312
  init_idx();
23421
23313
  init_configuration();
23422
23314
  var import_jsx_runtime103 = require("react/jsx-runtime");
23423
- var ButtonTextSettings = (0, import_react73.memo)(function ButtonTextSettings2() {
23424
- const [isOpen, setIsOpen] = (0, import_react73.useState)(false);
23315
+ var ButtonTextSettings = (0, import_react74.memo)(function ButtonTextSettings2() {
23316
+ const [isOpen, setIsOpen] = (0, import_react74.useState)(false);
23425
23317
  const focusIdx = useEditorStore((s) => s.focusIdx);
23426
23318
  const template = useEditorStore((s) => s.template);
23427
23319
  const updateElement = useEditorStore((s) => s.updateElement);
23428
- const buttonElement = (0, import_react73.useMemo)(() => {
23320
+ const buttonElement = (0, import_react74.useMemo)(() => {
23429
23321
  return focusIdx ? getValueByIdx(template, focusIdx) : null;
23430
23322
  }, [focusIdx, template]);
23431
- const currentLetterSpacing = (0, import_react73.useMemo)(() => {
23323
+ const currentLetterSpacing = (0, import_react74.useMemo)(() => {
23432
23324
  if (!buttonElement?.attributes?.["letter-spacing"]) return DEFAULT_LETTER_SPACING;
23433
23325
  const parsed = parseFloat(buttonElement.attributes["letter-spacing"]);
23434
23326
  return isNaN(parsed) ? DEFAULT_LETTER_SPACING : parsed;
23435
23327
  }, [buttonElement]);
23436
- const currentLineHeight = (0, import_react73.useMemo)(() => {
23328
+ const currentLineHeight = (0, import_react74.useMemo)(() => {
23437
23329
  if (!buttonElement?.attributes?.["line-height"]) return DEFAULT_LINE_HEIGHT;
23438
23330
  const parsed = parseFloat(buttonElement.attributes["line-height"]);
23439
23331
  return isNaN(parsed) ? DEFAULT_LINE_HEIGHT : parsed;
23440
23332
  }, [buttonElement]);
23441
- const [letterSpacingInputValue, setLetterSpacingInputValue] = (0, import_react73.useState)(
23442
- String(currentLetterSpacing)
23443
- );
23444
- const [isLetterSpacingInputFocused, setIsLetterSpacingInputFocused] = (0, import_react73.useState)(false);
23445
- const [lineHeightInputValue, setLineHeightInputValue] = (0, import_react73.useState)(
23446
- String(currentLineHeight)
23447
- );
23448
- const [isLineHeightInputFocused, setIsLineHeightInputFocused] = (0, import_react73.useState)(false);
23449
- (0, import_react73.useEffect)(() => {
23450
- if (!isLetterSpacingInputFocused) {
23451
- setLetterSpacingInputValue(String(currentLetterSpacing));
23452
- }
23453
- }, [currentLetterSpacing, isLetterSpacingInputFocused]);
23454
- (0, import_react73.useEffect)(() => {
23455
- if (!isLineHeightInputFocused) {
23456
- setLineHeightInputValue(String(currentLineHeight));
23457
- }
23458
- }, [currentLineHeight, isLineHeightInputFocused]);
23459
- const handleLetterSpacingSliderChange = (0, import_react73.useCallback)((values) => {
23333
+ const commitLetterSpacing = (0, import_react74.useCallback)((value) => {
23460
23334
  if (!focusIdx) return;
23461
- const value = values[0];
23462
- setLetterSpacingInputValue(String(value));
23463
23335
  const currentTemplate = useEditorStore.getState().template;
23464
23336
  const element = getValueByIdx(currentTemplate, focusIdx);
23465
23337
  updateElement(focusIdx, {
23466
- attributes: {
23467
- ...element?.attributes,
23468
- "letter-spacing": `${value}px`
23469
- }
23338
+ attributes: { ...element?.attributes, "letter-spacing": `${value}px` }
23470
23339
  });
23471
23340
  }, [focusIdx, updateElement]);
23472
- const handleLetterSpacingInputChange = (0, import_react73.useCallback)((e) => {
23473
- setLetterSpacingInputValue(e.target.value);
23474
- }, []);
23475
- const applyLetterSpacing = (0, import_react73.useCallback)(() => {
23341
+ const commitLineHeight = (0, import_react74.useCallback)((value) => {
23476
23342
  if (!focusIdx) return;
23477
- const parsed = parseFloat(letterSpacingInputValue);
23478
- if (isNaN(parsed) || letterSpacingInputValue === "") {
23479
- setLetterSpacingInputValue(String(currentLetterSpacing));
23480
- return;
23481
- }
23482
- const clampedValue = Math.max(MIN_LETTER_SPACING, Math.min(parsed, MAX_LETTER_SPACING));
23483
- setLetterSpacingInputValue(String(clampedValue));
23484
23343
  const currentTemplate = useEditorStore.getState().template;
23485
23344
  const element = getValueByIdx(currentTemplate, focusIdx);
23486
23345
  updateElement(focusIdx, {
23487
- attributes: {
23488
- ...element?.attributes,
23489
- "letter-spacing": `${clampedValue}px`
23490
- }
23491
- });
23492
- }, [focusIdx, letterSpacingInputValue, currentLetterSpacing, updateElement]);
23493
- const handleLetterSpacingInputBlur = (0, import_react73.useCallback)(() => {
23494
- setIsLetterSpacingInputFocused(false);
23495
- applyLetterSpacing();
23496
- }, [applyLetterSpacing]);
23497
- const handleLetterSpacingInputKeyDown = (0, import_react73.useCallback)((e) => {
23498
- if (e.key === "Enter") {
23499
- e.preventDefault();
23500
- applyLetterSpacing();
23501
- e.target.blur();
23502
- }
23503
- }, [applyLetterSpacing]);
23504
- const handleLineHeightSliderChange = (0, import_react73.useCallback)((values) => {
23505
- if (!focusIdx) return;
23506
- const value = values[0];
23507
- setLineHeightInputValue(String(value));
23508
- const currentTemplate = useEditorStore.getState().template;
23509
- const element = getValueByIdx(currentTemplate, focusIdx);
23510
- updateElement(focusIdx, {
23511
- attributes: {
23512
- ...element?.attributes,
23513
- "line-height": String(value)
23514
- }
23346
+ attributes: { ...element?.attributes, "line-height": String(value) }
23515
23347
  });
23516
23348
  }, [focusIdx, updateElement]);
23517
- const handleLineHeightInputChange = (0, import_react73.useCallback)((e) => {
23518
- setLineHeightInputValue(e.target.value);
23519
- }, []);
23520
- const applyLineHeight = (0, import_react73.useCallback)(() => {
23521
- if (!focusIdx) return;
23522
- const parsed = parseFloat(lineHeightInputValue);
23523
- if (isNaN(parsed) || lineHeightInputValue === "") {
23524
- setLineHeightInputValue(String(currentLineHeight));
23525
- return;
23526
- }
23527
- const clampedValue = Math.max(MIN_LINE_HEIGHT, Math.min(parsed, MAX_LINE_HEIGHT));
23528
- setLineHeightInputValue(String(clampedValue));
23529
- const currentTemplate = useEditorStore.getState().template;
23530
- const element = getValueByIdx(currentTemplate, focusIdx);
23531
- updateElement(focusIdx, {
23532
- attributes: {
23533
- ...element?.attributes,
23534
- "line-height": String(clampedValue)
23535
- }
23536
- });
23537
- }, [focusIdx, lineHeightInputValue, currentLineHeight, updateElement]);
23538
- const handleLineHeightInputBlur = (0, import_react73.useCallback)(() => {
23539
- setIsLineHeightInputFocused(false);
23540
- applyLineHeight();
23541
- }, [applyLineHeight]);
23542
- const handleLineHeightInputKeyDown = (0, import_react73.useCallback)((e) => {
23543
- if (e.key === "Enter") {
23544
- e.preventDefault();
23545
- applyLineHeight();
23546
- e.target.blur();
23547
- }
23548
- }, [applyLineHeight]);
23349
+ const letterSpacingInput = useEditableFloat({
23350
+ value: currentLetterSpacing,
23351
+ onChange: commitLetterSpacing,
23352
+ min: MIN_LETTER_SPACING,
23353
+ max: MAX_LETTER_SPACING
23354
+ });
23355
+ const lineHeightInput = useEditableFloat({
23356
+ value: currentLineHeight,
23357
+ onChange: commitLineHeight,
23358
+ min: MIN_LINE_HEIGHT,
23359
+ max: MAX_LINE_HEIGHT
23360
+ });
23361
+ const handleLetterSpacingSliderChange = (0, import_react74.useCallback)((values) => {
23362
+ commitLetterSpacing(values[0]);
23363
+ }, [commitLetterSpacing]);
23364
+ const handleLineHeightSliderChange = (0, import_react74.useCallback)((values) => {
23365
+ commitLineHeight(values[0]);
23366
+ }, [commitLineHeight]);
23549
23367
  return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(Tooltip, { children: [
23550
23368
  /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
23551
23369
  /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(
@@ -23582,11 +23400,11 @@ var ButtonTextSettings = (0, import_react73.memo)(function ButtonTextSettings2()
23582
23400
  Input,
23583
23401
  {
23584
23402
  type: "number",
23585
- value: letterSpacingInputValue,
23586
- onChange: handleLetterSpacingInputChange,
23587
- onFocus: () => setIsLetterSpacingInputFocused(true),
23588
- onBlur: handleLetterSpacingInputBlur,
23589
- onKeyDown: handleLetterSpacingInputKeyDown,
23403
+ value: letterSpacingInput.displayValue,
23404
+ onChange: (e) => letterSpacingInput.setLocalValue(e.target.value),
23405
+ onFocus: letterSpacingInput.handleFocus,
23406
+ onBlur: letterSpacingInput.handleBlur,
23407
+ onKeyDown: letterSpacingInput.handleKeyDown,
23590
23408
  className: "w-25 shadow-none rounded-[12px]",
23591
23409
  min: MIN_LETTER_SPACING,
23592
23410
  max: MAX_LETTER_SPACING,
@@ -23613,11 +23431,11 @@ var ButtonTextSettings = (0, import_react73.memo)(function ButtonTextSettings2()
23613
23431
  Input,
23614
23432
  {
23615
23433
  type: "number",
23616
- value: lineHeightInputValue,
23617
- onChange: handleLineHeightInputChange,
23618
- onFocus: () => setIsLineHeightInputFocused(true),
23619
- onBlur: handleLineHeightInputBlur,
23620
- onKeyDown: handleLineHeightInputKeyDown,
23434
+ value: lineHeightInput.displayValue,
23435
+ onChange: (e) => lineHeightInput.setLocalValue(e.target.value),
23436
+ onFocus: lineHeightInput.handleFocus,
23437
+ onBlur: lineHeightInput.handleBlur,
23438
+ onKeyDown: lineHeightInput.handleKeyDown,
23621
23439
  className: "w-25 shadow-none rounded-[12px]",
23622
23440
  min: MIN_LINE_HEIGHT,
23623
23441
  max: MAX_LINE_HEIGHT,
@@ -23644,41 +23462,41 @@ var ButtonToolbar = () => {
23644
23462
  const border = useBorder();
23645
23463
  const padding = usePadding();
23646
23464
  const size = useSize({ defaultWidth: 100, defaultHeight: 40, widthUnit: "%", heightUnit: "px" });
23647
- const currentElement = (0, import_react74.useMemo)(() => {
23465
+ const currentElement = (0, import_react75.useMemo)(() => {
23648
23466
  if (!focusIdx || !template) return null;
23649
23467
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
23650
23468
  return (0, import_lodash13.get)(template, path);
23651
23469
  }, [focusIdx, template]);
23652
- const currentBgColor = (0, import_react74.useMemo)(() => {
23470
+ const currentBgColor = (0, import_react75.useMemo)(() => {
23653
23471
  return currentElement?.attributes?.["background-color"];
23654
23472
  }, [currentElement]);
23655
- const currentTextColor = (0, import_react74.useMemo)(() => {
23473
+ const currentTextColor = (0, import_react75.useMemo)(() => {
23656
23474
  return currentElement?.attributes?.["color"] || "#ffffff";
23657
23475
  }, [currentElement]);
23658
- const isBold = (0, import_react74.useMemo)(() => {
23476
+ const isBold = (0, import_react75.useMemo)(() => {
23659
23477
  return currentElement?.attributes?.["font-weight"] === "bold";
23660
23478
  }, [currentElement]);
23661
- const isItalic = (0, import_react74.useMemo)(() => {
23479
+ const isItalic = (0, import_react75.useMemo)(() => {
23662
23480
  return currentElement?.attributes?.["font-style"] === "italic";
23663
23481
  }, [currentElement]);
23664
- const isUnderline = (0, import_react74.useMemo)(() => {
23482
+ const isUnderline = (0, import_react75.useMemo)(() => {
23665
23483
  const decoration = currentElement?.attributes?.["text-decoration"] || "";
23666
23484
  return decoration.includes("underline");
23667
23485
  }, [currentElement]);
23668
- const isStrikethrough = (0, import_react74.useMemo)(() => {
23486
+ const isStrikethrough = (0, import_react75.useMemo)(() => {
23669
23487
  const decoration = currentElement?.attributes?.["text-decoration"] || "";
23670
23488
  return decoration.includes("line-through");
23671
23489
  }, [currentElement]);
23672
- const currentAlignment = (0, import_react74.useMemo)(() => {
23490
+ const currentAlignment = (0, import_react75.useMemo)(() => {
23673
23491
  return currentElement?.attributes?.["text-align"] || "left";
23674
23492
  }, [currentElement]);
23675
- const currentButtonAlign = (0, import_react74.useMemo)(() => {
23493
+ const currentButtonAlign = (0, import_react75.useMemo)(() => {
23676
23494
  return currentElement?.attributes?.["align"] || "center";
23677
23495
  }, [currentElement]);
23678
- const currentFontFamily = (0, import_react74.useMemo)(() => {
23496
+ const currentFontFamily = (0, import_react75.useMemo)(() => {
23679
23497
  return currentElement?.attributes?.["font-family"] || "Arial";
23680
23498
  }, [currentElement]);
23681
- const currentFontSize = (0, import_react74.useMemo)(() => {
23499
+ const currentFontSize = (0, import_react75.useMemo)(() => {
23682
23500
  return parseFontSize(currentElement?.attributes?.["font-size"]);
23683
23501
  }, [currentElement]);
23684
23502
  const handleDelete = () => {
@@ -23686,36 +23504,36 @@ var ButtonToolbar = () => {
23686
23504
  deleteElement(focusIdx);
23687
23505
  }
23688
23506
  };
23689
- const handleOpenBgColorPicker = (0, import_react74.useCallback)(() => {
23507
+ const handleOpenBgColorPicker = (0, import_react75.useCallback)(() => {
23690
23508
  setColorType("Button Color");
23691
23509
  setColorTarget("buttonBgColor");
23692
23510
  setActiveView("color");
23693
23511
  }, [setColorType, setColorTarget, setActiveView]);
23694
- const handleOpenStrokeColorPicker = (0, import_react74.useCallback)(() => {
23512
+ const handleOpenStrokeColorPicker = (0, import_react75.useCallback)(() => {
23695
23513
  setColorType("Stroke Color");
23696
23514
  setColorTarget("buttonStrokeColor");
23697
23515
  setActiveView("color");
23698
23516
  }, [setColorType, setColorTarget, setActiveView]);
23699
- const handleOpenTextColorPicker = (0, import_react74.useCallback)(() => {
23517
+ const handleOpenTextColorPicker = (0, import_react75.useCallback)(() => {
23700
23518
  setColorType("Text Color");
23701
23519
  setColorTarget("buttonTextColor");
23702
23520
  setActiveView("color");
23703
23521
  }, [setColorType, setColorTarget, setActiveView]);
23704
- const handleToggleBold = (0, import_react74.useCallback)(() => {
23522
+ const handleToggleBold = (0, import_react75.useCallback)(() => {
23705
23523
  if (!focusIdx || !currentElement) return;
23706
23524
  const newWeight = isBold ? "normal" : "bold";
23707
23525
  updateElement(focusIdx, {
23708
23526
  attributes: { ...currentElement.attributes, "font-weight": newWeight }
23709
23527
  });
23710
23528
  }, [focusIdx, currentElement, isBold, updateElement]);
23711
- const handleToggleItalic = (0, import_react74.useCallback)(() => {
23529
+ const handleToggleItalic = (0, import_react75.useCallback)(() => {
23712
23530
  if (!focusIdx || !currentElement) return;
23713
23531
  const newStyle = isItalic ? "normal" : "italic";
23714
23532
  updateElement(focusIdx, {
23715
23533
  attributes: { ...currentElement.attributes, "font-style": newStyle }
23716
23534
  });
23717
23535
  }, [focusIdx, currentElement, isItalic, updateElement]);
23718
- const handleToggleUnderline = (0, import_react74.useCallback)(() => {
23536
+ const handleToggleUnderline = (0, import_react75.useCallback)(() => {
23719
23537
  if (!focusIdx || !currentElement) return;
23720
23538
  const currentDecoration = currentElement.attributes?.["text-decoration"] || "";
23721
23539
  let newDecoration;
@@ -23728,7 +23546,7 @@ var ButtonToolbar = () => {
23728
23546
  attributes: { ...currentElement.attributes, "text-decoration": newDecoration || "none" }
23729
23547
  });
23730
23548
  }, [focusIdx, currentElement, isUnderline, updateElement]);
23731
- const handleToggleStrike = (0, import_react74.useCallback)(() => {
23549
+ const handleToggleStrike = (0, import_react75.useCallback)(() => {
23732
23550
  if (!focusIdx || !currentElement) return;
23733
23551
  const currentDecoration = currentElement.attributes?.["text-decoration"] || "";
23734
23552
  let newDecoration;
@@ -23741,7 +23559,7 @@ var ButtonToolbar = () => {
23741
23559
  attributes: { ...currentElement.attributes, "text-decoration": newDecoration || "none" }
23742
23560
  });
23743
23561
  }, [focusIdx, currentElement, isStrikethrough, updateElement]);
23744
- const handleCycleAlignment = (0, import_react74.useCallback)(() => {
23562
+ const handleCycleAlignment = (0, import_react75.useCallback)(() => {
23745
23563
  if (!focusIdx || !currentElement) return;
23746
23564
  const currentIndex = BUTTON_ALIGNMENTS.indexOf(currentAlignment);
23747
23565
  const nextIndex = (currentIndex + 1) % BUTTON_ALIGNMENTS.length;
@@ -23750,7 +23568,7 @@ var ButtonToolbar = () => {
23750
23568
  attributes: { ...currentElement.attributes, "text-align": nextAlignment }
23751
23569
  });
23752
23570
  }, [focusIdx, currentElement, currentAlignment, updateElement]);
23753
- const handleCycleButtonAlign = (0, import_react74.useCallback)(() => {
23571
+ const handleCycleButtonAlign = (0, import_react75.useCallback)(() => {
23754
23572
  if (!focusIdx || !currentElement) return;
23755
23573
  const currentIndex = BUTTON_ALIGNMENTS.indexOf(currentButtonAlign);
23756
23574
  const nextIndex = (currentIndex + 1) % BUTTON_ALIGNMENTS.length;
@@ -23759,13 +23577,13 @@ var ButtonToolbar = () => {
23759
23577
  attributes: { ...currentElement.attributes, "align": nextAlign }
23760
23578
  });
23761
23579
  }, [focusIdx, currentElement, currentButtonAlign, updateElement]);
23762
- const handleSetFontFamily = (0, import_react74.useCallback)((font) => {
23580
+ const handleSetFontFamily = (0, import_react75.useCallback)((font) => {
23763
23581
  if (!focusIdx || !currentElement) return;
23764
23582
  updateElement(focusIdx, {
23765
23583
  attributes: { ...currentElement.attributes, "font-family": font }
23766
23584
  });
23767
23585
  }, [focusIdx, currentElement, updateElement]);
23768
- const handleFontSizeChange = (0, import_react74.useCallback)((size2) => {
23586
+ const handleFontSizeChange = (0, import_react75.useCallback)((size2) => {
23769
23587
  if (!focusIdx || !currentElement) return;
23770
23588
  updateElement(focusIdx, {
23771
23589
  attributes: { ...currentElement.attributes, "font-size": `${size2}px` }
@@ -23953,7 +23771,7 @@ var ButtonToolbar = () => {
23953
23771
  };
23954
23772
 
23955
23773
  // src/core/editor/components/element-gear/section/toolbar.tsx
23956
- var import_react77 = require("react");
23774
+ var import_react78 = require("react");
23957
23775
  init_button();
23958
23776
  init_tooltip();
23959
23777
  init_editor();
@@ -23965,11 +23783,11 @@ init_button();
23965
23783
  init_popover();
23966
23784
  init_tooltip();
23967
23785
  var import_lucide_react64 = require("lucide-react");
23968
- var import_react76 = require("react");
23786
+ var import_react77 = require("react");
23969
23787
  init_sidebar_context();
23970
23788
 
23971
23789
  // src/core/editor/hooks/use-image.ts
23972
- var import_react75 = require("react");
23790
+ var import_react76 = require("react");
23973
23791
  init_editor();
23974
23792
  var import_lodash14 = require("lodash");
23975
23793
  init_configuration();
@@ -23977,7 +23795,7 @@ var useImage = (options = {}) => {
23977
23795
  const { type = "background" } = options;
23978
23796
  const attributeName = type === "image" ? "src" : type === "property" ? "image-src" : "background-url";
23979
23797
  const { focusIdx, updateElement, template } = useEditorStore();
23980
- const { element, url, positionX, positionY, backgroundSize, backgroundRepeat, width, height } = (0, import_react75.useMemo)(() => {
23798
+ const { element, url, positionX, positionY, backgroundSize, backgroundRepeat, width, height } = (0, import_react76.useMemo)(() => {
23981
23799
  if (!focusIdx || !template) {
23982
23800
  return {
23983
23801
  element: null,
@@ -24003,13 +23821,13 @@ var useImage = (options = {}) => {
24003
23821
  height: el?.attributes?.["height"] || "auto"
24004
23822
  };
24005
23823
  }, [focusIdx, template, attributeName]);
24006
- const setUrl = (0, import_react75.useCallback)((newUrl) => {
23824
+ const setUrl = (0, import_react76.useCallback)((newUrl) => {
24007
23825
  if (!focusIdx || !element) return;
24008
23826
  updateElement(focusIdx, {
24009
23827
  attributes: { ...element.attributes, [attributeName]: newUrl }
24010
23828
  });
24011
23829
  }, [focusIdx, element, updateElement, attributeName]);
24012
- const removeUrl = (0, import_react75.useCallback)(() => {
23830
+ const removeUrl = (0, import_react76.useCallback)(() => {
24013
23831
  if (!focusIdx || !element) return;
24014
23832
  if (type === "background") {
24015
23833
  const newAttributes = { ...element.attributes };
@@ -24022,37 +23840,37 @@ var useImage = (options = {}) => {
24022
23840
  });
24023
23841
  }
24024
23842
  }, [focusIdx, element, updateElement, attributeName, type]);
24025
- const setPositionX = (0, import_react75.useCallback)((value) => {
23843
+ const setPositionX = (0, import_react76.useCallback)((value) => {
24026
23844
  if (!focusIdx || !element) return;
24027
23845
  updateElement(focusIdx, {
24028
23846
  attributes: { ...element.attributes, "background-position-x": value }
24029
23847
  });
24030
23848
  }, [focusIdx, element, updateElement]);
24031
- const setPositionY = (0, import_react75.useCallback)((value) => {
23849
+ const setPositionY = (0, import_react76.useCallback)((value) => {
24032
23850
  if (!focusIdx || !element) return;
24033
23851
  updateElement(focusIdx, {
24034
23852
  attributes: { ...element.attributes, "background-position-y": value }
24035
23853
  });
24036
23854
  }, [focusIdx, element, updateElement]);
24037
- const setBackgroundSize = (0, import_react75.useCallback)((value) => {
23855
+ const setBackgroundSize = (0, import_react76.useCallback)((value) => {
24038
23856
  if (!focusIdx || !element) return;
24039
23857
  updateElement(focusIdx, {
24040
23858
  attributes: { ...element.attributes, "background-size": value }
24041
23859
  });
24042
23860
  }, [focusIdx, element, updateElement]);
24043
- const setBackgroundRepeat = (0, import_react75.useCallback)((value) => {
23861
+ const setBackgroundRepeat = (0, import_react76.useCallback)((value) => {
24044
23862
  if (!focusIdx || !element) return;
24045
23863
  updateElement(focusIdx, {
24046
23864
  attributes: { ...element.attributes, "background-repeat": value }
24047
23865
  });
24048
23866
  }, [focusIdx, element, updateElement]);
24049
- const setWidth = (0, import_react75.useCallback)((value) => {
23867
+ const setWidth = (0, import_react76.useCallback)((value) => {
24050
23868
  if (!focusIdx || !element) return;
24051
23869
  updateElement(focusIdx, {
24052
23870
  attributes: { ...element.attributes, width: value }
24053
23871
  });
24054
23872
  }, [focusIdx, element, updateElement]);
24055
- const setHeight = (0, import_react75.useCallback)((value) => {
23873
+ const setHeight = (0, import_react76.useCallback)((value) => {
24056
23874
  if (!focusIdx || !element) return;
24057
23875
  updateElement(focusIdx, {
24058
23876
  attributes: { ...element.attributes, height: value }
@@ -24214,7 +24032,7 @@ init_separator();
24214
24032
  init_configuration();
24215
24033
  var import_jsx_runtime107 = require("react/jsx-runtime");
24216
24034
  var ImageMenu = ({ type }) => {
24217
- const [isOpen, setIsOpen] = (0, import_react76.useState)(false);
24035
+ const [isOpen, setIsOpen] = (0, import_react77.useState)(false);
24218
24036
  const { setActiveView, setImageTarget } = useSidebarContext();
24219
24037
  const { url, removeUrl } = useImage({ type });
24220
24038
  const handleSelectImage = () => {
@@ -24233,9 +24051,9 @@ var ImageMenu = ({ type }) => {
24233
24051
  Button,
24234
24052
  {
24235
24053
  variant: "outline",
24236
- className: "shadow-none transition-none cursor-pointer rounded-[12px]",
24054
+ className: "shadow-none transition-none cursor-pointer rounded-[12px] p-0.5 ",
24237
24055
  size: "icon",
24238
- children: url && !url.includes("placeholder_image.png") && url !== DEFAULT_PROPERTY_PLACEHOLDER_IMAGE ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("img", { src: url, alt: "Background Image", className: "w-full h-full object-cover rounded-[12px]" }) : /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(import_lucide_react64.ImageIcon, { className: "w-4 h-4" })
24056
+ children: url && !url.includes("placeholder_image.png") && url !== DEFAULT_PROPERTY_PLACEHOLDER_IMAGE ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("img", { src: url, alt: "Background Image", className: "w-full h-full object-cover rounded-[8px]" }) : /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(import_lucide_react64.ImageIcon, { className: "w-4 h-4" })
24239
24057
  }
24240
24058
  ) }) }),
24241
24059
  /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(PopoverContent, { className: "w-64 z-51 mt-1 rounded-[12px] p-3", children: [
@@ -24261,7 +24079,7 @@ var import_jsx_runtime108 = require("react/jsx-runtime");
24261
24079
  var SectionToolbar = () => {
24262
24080
  const { focusIdx, deleteElement, template } = useEditorStore();
24263
24081
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
24264
- const currentBgColor = (0, import_react77.useMemo)(() => {
24082
+ const currentBgColor = (0, import_react78.useMemo)(() => {
24265
24083
  if (!focusIdx || !template) return void 0;
24266
24084
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
24267
24085
  const element = (0, import_lodash15.get)(template, path);
@@ -24275,12 +24093,12 @@ var SectionToolbar = () => {
24275
24093
  deleteElement(focusIdx);
24276
24094
  }
24277
24095
  };
24278
- const handleOpenBgColorPicker = (0, import_react77.useCallback)(() => {
24096
+ const handleOpenBgColorPicker = (0, import_react78.useCallback)(() => {
24279
24097
  setColorType("Background Color");
24280
24098
  setColorTarget("sectionBgColor");
24281
24099
  setActiveView("color");
24282
24100
  }, [setColorType, setColorTarget, setActiveView]);
24283
- const handleOpenStrokeColorPicker = (0, import_react77.useCallback)(() => {
24101
+ const handleOpenStrokeColorPicker = (0, import_react78.useCallback)(() => {
24284
24102
  setColorType("Stroke Color");
24285
24103
  setColorTarget("strokeColor");
24286
24104
  setActiveView("color");
@@ -24343,7 +24161,7 @@ var SectionToolbar = () => {
24343
24161
  };
24344
24162
 
24345
24163
  // src/core/editor/components/element-gear/section-column/toolbar.tsx
24346
- var import_react78 = require("react");
24164
+ var import_react79 = require("react");
24347
24165
  init_dropdown_menu();
24348
24166
  init_button();
24349
24167
  var import_lucide_react65 = require("lucide-react");
@@ -24356,15 +24174,15 @@ var VERTICAL_ALIGNMENTS = ["top", "middle", "bottom"];
24356
24174
  var SectionColumnToolbar = () => {
24357
24175
  const { focusIdx, deleteElement, template, setColumnCount, updateElement } = useEditorStore();
24358
24176
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
24359
- const [columnCountOpen, setColumnCountOpen] = (0, import_react78.useState)(false);
24360
- const [verticalAlignOpen, setVerticalAlignOpen] = (0, import_react78.useState)(false);
24361
- const element = (0, import_react78.useMemo)(() => {
24177
+ const [columnCountOpen, setColumnCountOpen] = (0, import_react79.useState)(false);
24178
+ const [verticalAlignOpen, setVerticalAlignOpen] = (0, import_react79.useState)(false);
24179
+ const element = (0, import_react79.useMemo)(() => {
24362
24180
  if (!focusIdx || !template) return null;
24363
24181
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
24364
24182
  return (0, import_lodash16.get)(template, path);
24365
24183
  }, [focusIdx, template]);
24366
24184
  const columnCount = element?.children?.length || 2;
24367
- const currentVerticalAlign = (0, import_react78.useMemo)(() => {
24185
+ const currentVerticalAlign = (0, import_react79.useMemo)(() => {
24368
24186
  const firstChild = element?.children?.[0];
24369
24187
  return firstChild?.attributes?.["vertical-align"] || "top";
24370
24188
  }, [element]);
@@ -24377,17 +24195,17 @@ var SectionColumnToolbar = () => {
24377
24195
  deleteElement(focusIdx);
24378
24196
  }
24379
24197
  };
24380
- const handleOpenBgColorPicker = (0, import_react78.useCallback)(() => {
24198
+ const handleOpenBgColorPicker = (0, import_react79.useCallback)(() => {
24381
24199
  setColorType("Background Color");
24382
24200
  setColorTarget("sectionBgColor");
24383
24201
  setActiveView("color");
24384
24202
  }, [setColorType, setColorTarget, setActiveView]);
24385
- const handleOpenStrokeColorPicker = (0, import_react78.useCallback)(() => {
24203
+ const handleOpenStrokeColorPicker = (0, import_react79.useCallback)(() => {
24386
24204
  setColorType("Stroke Color");
24387
24205
  setColorTarget("strokeColor");
24388
24206
  setActiveView("color");
24389
24207
  }, [setColorType, setColorTarget, setActiveView]);
24390
- const handleVerticalAlignChange = (0, import_react78.useCallback)((align) => {
24208
+ const handleVerticalAlignChange = (0, import_react79.useCallback)((align) => {
24391
24209
  if (!focusIdx || !element?.children) return;
24392
24210
  const updatedChildren = element.children.map((child) => ({
24393
24211
  ...child,
@@ -24502,19 +24320,19 @@ var SectionColumnToolbar = () => {
24502
24320
  };
24503
24321
 
24504
24322
  // src/core/editor/components/element-gear/page/toolbar.tsx
24505
- var import_react79 = require("react");
24323
+ var import_react80 = require("react");
24506
24324
  init_sidebar_context();
24507
24325
  init_editor();
24508
24326
  var import_jsx_runtime110 = require("react/jsx-runtime");
24509
24327
  var PageToolbar = () => {
24510
24328
  const { focusIdx, template } = useEditorStore();
24511
24329
  const { activeView, colorTarget, setColorType, setColorTarget, setActiveView } = useSidebarContext();
24512
- const currentBgColor = (0, import_react79.useMemo)(() => {
24330
+ const currentBgColor = (0, import_react80.useMemo)(() => {
24513
24331
  if (!focusIdx || !template || focusIdx !== "content") return void 0;
24514
24332
  const page = template.content?.[0];
24515
24333
  return page?.attributes?.["background-color"];
24516
24334
  }, [focusIdx, template]);
24517
- const handleOpenBgColorPicker = (0, import_react79.useCallback)(() => {
24335
+ const handleOpenBgColorPicker = (0, import_react80.useCallback)(() => {
24518
24336
  setColorType("Background Color");
24519
24337
  setColorTarget("sectionBgColor");
24520
24338
  setActiveView("color");
@@ -24535,17 +24353,17 @@ var PageToolbar = () => {
24535
24353
  };
24536
24354
 
24537
24355
  // src/core/editor/components/element-gear/spacer/toolbar.tsx
24538
- var import_react81 = require("react");
24356
+ var import_react82 = require("react");
24539
24357
  init_editor();
24540
24358
  init_sidebar_context();
24541
24359
 
24542
24360
  // src/core/editor/hooks/use-height.ts
24543
- var import_react80 = require("react");
24361
+ var import_react81 = require("react");
24544
24362
  init_editor();
24545
24363
  var import_lodash17 = require("lodash");
24546
24364
  var useHeight = () => {
24547
24365
  const { focusIdx, updateElement, template } = useEditorStore();
24548
- const currentValue = (0, import_react80.useMemo)(() => {
24366
+ const currentValue = (0, import_react81.useMemo)(() => {
24549
24367
  if (!focusIdx || !template) return 12;
24550
24368
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
24551
24369
  const element = (0, import_lodash17.get)(template, path);
@@ -24554,7 +24372,7 @@ var useHeight = () => {
24554
24372
  const parsed = parseInt(rawValue.replace("px", ""), 10);
24555
24373
  return isNaN(parsed) ? 12 : Math.max(4, parsed);
24556
24374
  }, [focusIdx, template]);
24557
- const handleChange = (0, import_react80.useCallback)((value) => {
24375
+ const handleChange = (0, import_react81.useCallback)((value) => {
24558
24376
  if (!focusIdx || !template) return;
24559
24377
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
24560
24378
  const element = (0, import_lodash17.get)(template, path);
@@ -24580,13 +24398,13 @@ var SpacerToolbar = () => {
24580
24398
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
24581
24399
  const height = useHeight();
24582
24400
  const padding = usePadding();
24583
- const currentBgColor = (0, import_react81.useMemo)(() => {
24401
+ const currentBgColor = (0, import_react82.useMemo)(() => {
24584
24402
  if (!focusIdx || !template) return void 0;
24585
24403
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
24586
24404
  const element = (0, import_lodash18.get)(template, path);
24587
24405
  return element?.attributes?.["container-background-color"];
24588
24406
  }, [focusIdx, template]);
24589
- const handleOpenBgColorPicker = (0, import_react81.useCallback)(() => {
24407
+ const handleOpenBgColorPicker = (0, import_react82.useCallback)(() => {
24590
24408
  setColorType("Background Color");
24591
24409
  setColorTarget("spacerBgColor");
24592
24410
  setActiveView("color");
@@ -24616,7 +24434,7 @@ var import_lucide_react67 = require("lucide-react");
24616
24434
  init_popover();
24617
24435
  init_editor();
24618
24436
  init_idx();
24619
- var import_react83 = require("react");
24437
+ var import_react84 = require("react");
24620
24438
  init_sidebar_context();
24621
24439
  init_configuration();
24622
24440
 
@@ -24627,78 +24445,41 @@ init_button();
24627
24445
  var import_lucide_react66 = require("lucide-react");
24628
24446
  init_label();
24629
24447
  init_input();
24630
- var import_react82 = require("react");
24448
+ var import_react83 = require("react");
24631
24449
  init_editor();
24632
24450
  init_idx();
24633
24451
  init_configuration();
24634
24452
  var import_jsx_runtime112 = require("react/jsx-runtime");
24635
- var SocialLineSpacing = (0, import_react82.memo)(function SocialLineSpacing2() {
24636
- const [isOpen, setIsOpen] = (0, import_react82.useState)(false);
24453
+ var SocialLineSpacing = (0, import_react83.memo)(function SocialLineSpacing2() {
24454
+ const [isOpen, setIsOpen] = (0, import_react83.useState)(false);
24637
24455
  const focusIdx = useEditorStore((s) => s.focusIdx);
24638
24456
  const template = useEditorStore((s) => s.template);
24639
24457
  const updateElement = useEditorStore((s) => s.updateElement);
24640
- const socialElement = (0, import_react82.useMemo)(() => {
24458
+ const socialElement = (0, import_react83.useMemo)(() => {
24641
24459
  return focusIdx ? getValueByIdx(template, focusIdx) : null;
24642
24460
  }, [focusIdx, template]);
24643
- const currentLineHeight = (0, import_react82.useMemo)(() => {
24461
+ const currentLineHeight = (0, import_react83.useMemo)(() => {
24644
24462
  if (!socialElement?.attributes?.["line-height"]) return DEFAULT_LINE_HEIGHT;
24645
24463
  const parsed = parseFloat(socialElement.attributes["line-height"]);
24646
24464
  return isNaN(parsed) ? DEFAULT_LINE_HEIGHT : parsed;
24647
24465
  }, [socialElement]);
24648
- const [lineHeightInputValue, setLineHeightInputValue] = (0, import_react82.useState)(
24649
- String(currentLineHeight)
24650
- );
24651
- const [isLineHeightInputFocused, setIsLineHeightInputFocused] = (0, import_react82.useState)(false);
24652
- (0, import_react82.useEffect)(() => {
24653
- if (!isLineHeightInputFocused) {
24654
- setLineHeightInputValue(String(currentLineHeight));
24655
- }
24656
- }, [currentLineHeight, isLineHeightInputFocused]);
24657
- const handleLineHeightSliderChange = (0, import_react82.useCallback)((values) => {
24466
+ const commitLineHeight = (0, import_react83.useCallback)((value) => {
24658
24467
  if (!focusIdx) return;
24659
- const value = values[0];
24660
- setLineHeightInputValue(String(value));
24661
24468
  const currentTemplate = useEditorStore.getState().template;
24662
24469
  const element = getValueByIdx(currentTemplate, focusIdx);
24663
24470
  updateElement(focusIdx, {
24664
- attributes: {
24665
- ...element?.attributes,
24666
- "line-height": String(value)
24667
- }
24471
+ attributes: { ...element?.attributes, "line-height": String(value) }
24668
24472
  });
24669
24473
  }, [focusIdx, updateElement]);
24670
- const handleLineHeightInputChange = (0, import_react82.useCallback)((e) => {
24671
- setLineHeightInputValue(e.target.value);
24672
- }, []);
24673
- const applyLineHeight = (0, import_react82.useCallback)(() => {
24674
- if (!focusIdx) return;
24675
- const parsed = parseFloat(lineHeightInputValue);
24676
- if (isNaN(parsed) || lineHeightInputValue === "") {
24677
- setLineHeightInputValue(String(currentLineHeight));
24678
- return;
24679
- }
24680
- const clampedValue = Math.max(MIN_LINE_HEIGHT, Math.min(parsed, MAX_LINE_HEIGHT));
24681
- setLineHeightInputValue(String(clampedValue));
24682
- const currentTemplate = useEditorStore.getState().template;
24683
- const element = getValueByIdx(currentTemplate, focusIdx);
24684
- updateElement(focusIdx, {
24685
- attributes: {
24686
- ...element?.attributes,
24687
- "line-height": String(clampedValue)
24688
- }
24689
- });
24690
- }, [focusIdx, lineHeightInputValue, currentLineHeight, updateElement]);
24691
- const handleLineHeightInputBlur = (0, import_react82.useCallback)(() => {
24692
- setIsLineHeightInputFocused(false);
24693
- applyLineHeight();
24694
- }, [applyLineHeight]);
24695
- const handleLineHeightInputKeyDown = (0, import_react82.useCallback)((e) => {
24696
- if (e.key === "Enter") {
24697
- e.preventDefault();
24698
- applyLineHeight();
24699
- e.target.blur();
24700
- }
24701
- }, [applyLineHeight]);
24474
+ const lineHeightInput = useEditableFloat({
24475
+ value: currentLineHeight,
24476
+ onChange: commitLineHeight,
24477
+ min: MIN_LINE_HEIGHT,
24478
+ max: MAX_LINE_HEIGHT
24479
+ });
24480
+ const handleLineHeightSliderChange = (0, import_react83.useCallback)((values) => {
24481
+ commitLineHeight(values[0]);
24482
+ }, [commitLineHeight]);
24702
24483
  return /* @__PURE__ */ (0, import_jsx_runtime112.jsxs)(Tooltip, { children: [
24703
24484
  /* @__PURE__ */ (0, import_jsx_runtime112.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
24704
24485
  /* @__PURE__ */ (0, import_jsx_runtime112.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime112.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime112.jsx)(
@@ -24734,11 +24515,11 @@ var SocialLineSpacing = (0, import_react82.memo)(function SocialLineSpacing2() {
24734
24515
  Input,
24735
24516
  {
24736
24517
  type: "number",
24737
- value: lineHeightInputValue,
24738
- onChange: handleLineHeightInputChange,
24739
- onFocus: () => setIsLineHeightInputFocused(true),
24740
- onBlur: handleLineHeightInputBlur,
24741
- onKeyDown: handleLineHeightInputKeyDown,
24518
+ value: lineHeightInput.displayValue,
24519
+ onChange: (e) => lineHeightInput.setLocalValue(e.target.value),
24520
+ onFocus: lineHeightInput.handleFocus,
24521
+ onBlur: lineHeightInput.handleBlur,
24522
+ onKeyDown: lineHeightInput.handleKeyDown,
24742
24523
  className: "w-25 shadow-none rounded-[12px]",
24743
24524
  min: MIN_LINE_HEIGHT,
24744
24525
  max: MAX_LINE_HEIGHT,
@@ -24774,48 +24555,48 @@ var SocialToolbar = () => {
24774
24555
  const currentIconStyle = socialElement?.data?.value?.iconStyle || "Regular";
24775
24556
  const currentIconColor = socialElement?.data?.value?.iconColor || "Colored";
24776
24557
  const { setActiveView, setColorTarget, setColorType, activeView, colorTarget } = useSidebarContext();
24777
- const currentBgColor = (0, import_react83.useMemo)(() => {
24558
+ const currentBgColor = (0, import_react84.useMemo)(() => {
24778
24559
  return socialElement?.attributes?.["container-background-color"] || "transparent";
24779
24560
  }, [socialElement]);
24780
- const currentFontFamily = (0, import_react83.useMemo)(() => {
24561
+ const currentFontFamily = (0, import_react84.useMemo)(() => {
24781
24562
  return socialElement?.attributes?.["font-family"] || "Arial";
24782
24563
  }, [socialElement]);
24783
- const currentFontSize = (0, import_react83.useMemo)(() => {
24564
+ const currentFontSize = (0, import_react84.useMemo)(() => {
24784
24565
  return parseFontSize(socialElement?.attributes?.["font-size"]);
24785
24566
  }, [socialElement]);
24786
- const currentTextColor = (0, import_react83.useMemo)(() => {
24567
+ const currentTextColor = (0, import_react84.useMemo)(() => {
24787
24568
  return socialElement?.attributes?.["color"] || "#000000";
24788
24569
  }, [socialElement]);
24789
- const isBold = (0, import_react83.useMemo)(() => {
24570
+ const isBold = (0, import_react84.useMemo)(() => {
24790
24571
  return socialElement?.attributes?.["font-weight"] === "bold";
24791
24572
  }, [socialElement]);
24792
- const isItalic = (0, import_react83.useMemo)(() => {
24573
+ const isItalic = (0, import_react84.useMemo)(() => {
24793
24574
  return socialElement?.attributes?.["font-style"] === "italic";
24794
24575
  }, [socialElement]);
24795
- const isUnderline = (0, import_react83.useMemo)(() => {
24576
+ const isUnderline = (0, import_react84.useMemo)(() => {
24796
24577
  const decoration = socialElement?.attributes?.["text-decoration"] || "";
24797
24578
  return decoration.includes("underline");
24798
24579
  }, [socialElement]);
24799
- const isStrikethrough = (0, import_react83.useMemo)(() => {
24580
+ const isStrikethrough = (0, import_react84.useMemo)(() => {
24800
24581
  const decoration = socialElement?.attributes?.["text-decoration"] || "";
24801
24582
  return decoration.includes("line-through");
24802
24583
  }, [socialElement]);
24803
- const currentMode = (0, import_react83.useMemo)(() => {
24584
+ const currentMode = (0, import_react84.useMemo)(() => {
24804
24585
  return socialElement?.attributes?.["mode"] || "horizontal";
24805
24586
  }, [socialElement]);
24806
- const currentAlign = (0, import_react83.useMemo)(() => {
24587
+ const currentAlign = (0, import_react84.useMemo)(() => {
24807
24588
  return socialElement?.attributes?.["align"] || "center";
24808
24589
  }, [socialElement]);
24809
- const currentSocialItemAlign = (0, import_react83.useMemo)(() => {
24590
+ const currentSocialItemAlign = (0, import_react84.useMemo)(() => {
24810
24591
  const firstChild = socialElement?.children?.[0];
24811
24592
  return firstChild?.attributes?.["align"] || "center";
24812
24593
  }, [socialElement]);
24813
- const handleOpenBgColorPicker = (0, import_react83.useCallback)(() => {
24594
+ const handleOpenBgColorPicker = (0, import_react84.useCallback)(() => {
24814
24595
  setColorType("Background Color");
24815
24596
  setColorTarget("socialBgColor");
24816
24597
  setActiveView("color");
24817
24598
  }, [setColorType, setColorTarget, setActiveView]);
24818
- const handleSocialStyleChange = (0, import_react83.useCallback)((value) => {
24599
+ const handleSocialStyleChange = (0, import_react84.useCallback)((value) => {
24819
24600
  if (!focusIdx) return;
24820
24601
  const currentTemplate = useEditorStore.getState().template;
24821
24602
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24830,7 +24611,7 @@ var SocialToolbar = () => {
24830
24611
  }
24831
24612
  });
24832
24613
  }, [focusIdx, updateElement]);
24833
- const handleIconSizeChange = (0, import_react83.useCallback)((value) => {
24614
+ const handleIconSizeChange = (0, import_react84.useCallback)((value) => {
24834
24615
  if (!focusIdx) return;
24835
24616
  const currentTemplate = useEditorStore.getState().template;
24836
24617
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24845,7 +24626,7 @@ var SocialToolbar = () => {
24845
24626
  }
24846
24627
  });
24847
24628
  }, [focusIdx, updateElement]);
24848
- const handleIconStyleChange = (0, import_react83.useCallback)((value) => {
24629
+ const handleIconStyleChange = (0, import_react84.useCallback)((value) => {
24849
24630
  if (!focusIdx) return;
24850
24631
  const currentTemplate = useEditorStore.getState().template;
24851
24632
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24860,7 +24641,7 @@ var SocialToolbar = () => {
24860
24641
  }
24861
24642
  });
24862
24643
  }, [focusIdx, updateElement]);
24863
- const handleIconColorChange = (0, import_react83.useCallback)((value) => {
24644
+ const handleIconColorChange = (0, import_react84.useCallback)((value) => {
24864
24645
  if (!focusIdx) return;
24865
24646
  const currentTemplate = useEditorStore.getState().template;
24866
24647
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24875,7 +24656,7 @@ var SocialToolbar = () => {
24875
24656
  }
24876
24657
  });
24877
24658
  }, [focusIdx, updateElement]);
24878
- const handleSetFontFamily = (0, import_react83.useCallback)((font) => {
24659
+ const handleSetFontFamily = (0, import_react84.useCallback)((font) => {
24879
24660
  if (!focusIdx) return;
24880
24661
  const currentTemplate = useEditorStore.getState().template;
24881
24662
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24886,7 +24667,7 @@ var SocialToolbar = () => {
24886
24667
  }
24887
24668
  });
24888
24669
  }, [focusIdx, updateElement]);
24889
- const handleFontSizeChange = (0, import_react83.useCallback)((size) => {
24670
+ const handleFontSizeChange = (0, import_react84.useCallback)((size) => {
24890
24671
  if (!focusIdx) return;
24891
24672
  const currentTemplate = useEditorStore.getState().template;
24892
24673
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24897,12 +24678,12 @@ var SocialToolbar = () => {
24897
24678
  }
24898
24679
  });
24899
24680
  }, [focusIdx, updateElement]);
24900
- const handleOpenTextColorPicker = (0, import_react83.useCallback)(() => {
24681
+ const handleOpenTextColorPicker = (0, import_react84.useCallback)(() => {
24901
24682
  setColorType("Text Color");
24902
24683
  setColorTarget("socialTextColor");
24903
24684
  setActiveView("color");
24904
24685
  }, [setColorType, setColorTarget, setActiveView]);
24905
- const handleToggleBold = (0, import_react83.useCallback)(() => {
24686
+ const handleToggleBold = (0, import_react84.useCallback)(() => {
24906
24687
  if (!focusIdx) return;
24907
24688
  const currentTemplate = useEditorStore.getState().template;
24908
24689
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24914,7 +24695,7 @@ var SocialToolbar = () => {
24914
24695
  }
24915
24696
  });
24916
24697
  }, [focusIdx, isBold, updateElement]);
24917
- const handleToggleItalic = (0, import_react83.useCallback)(() => {
24698
+ const handleToggleItalic = (0, import_react84.useCallback)(() => {
24918
24699
  if (!focusIdx) return;
24919
24700
  const currentTemplate = useEditorStore.getState().template;
24920
24701
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24926,7 +24707,7 @@ var SocialToolbar = () => {
24926
24707
  }
24927
24708
  });
24928
24709
  }, [focusIdx, isItalic, updateElement]);
24929
- const handleToggleUnderline = (0, import_react83.useCallback)(() => {
24710
+ const handleToggleUnderline = (0, import_react84.useCallback)(() => {
24930
24711
  if (!focusIdx) return;
24931
24712
  const currentTemplate = useEditorStore.getState().template;
24932
24713
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24944,7 +24725,7 @@ var SocialToolbar = () => {
24944
24725
  }
24945
24726
  });
24946
24727
  }, [focusIdx, isUnderline, updateElement]);
24947
- const handleToggleStrike = (0, import_react83.useCallback)(() => {
24728
+ const handleToggleStrike = (0, import_react84.useCallback)(() => {
24948
24729
  if (!focusIdx) return;
24949
24730
  const currentTemplate = useEditorStore.getState().template;
24950
24731
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24962,7 +24743,7 @@ var SocialToolbar = () => {
24962
24743
  }
24963
24744
  });
24964
24745
  }, [focusIdx, isStrikethrough, updateElement]);
24965
- const handleModeChange = (0, import_react83.useCallback)((mode) => {
24746
+ const handleModeChange = (0, import_react84.useCallback)((mode) => {
24966
24747
  if (!focusIdx) return;
24967
24748
  const currentTemplate = useEditorStore.getState().template;
24968
24749
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24973,7 +24754,7 @@ var SocialToolbar = () => {
24973
24754
  }
24974
24755
  });
24975
24756
  }, [focusIdx, updateElement]);
24976
- const handleCycleAlign = (0, import_react83.useCallback)(() => {
24757
+ const handleCycleAlign = (0, import_react84.useCallback)(() => {
24977
24758
  if (!focusIdx) return;
24978
24759
  const currentTemplate = useEditorStore.getState().template;
24979
24760
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -24992,7 +24773,7 @@ var SocialToolbar = () => {
24992
24773
  children: updatedChildren
24993
24774
  });
24994
24775
  }, [focusIdx, currentAlign, updateElement]);
24995
- const handleCycleSocialItemAlign = (0, import_react83.useCallback)(() => {
24776
+ const handleCycleSocialItemAlign = (0, import_react84.useCallback)(() => {
24996
24777
  if (!focusIdx) return;
24997
24778
  const currentTemplate = useEditorStore.getState().template;
24998
24779
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25240,7 +25021,7 @@ init_tooltip();
25240
25021
  var import_lucide_react68 = require("lucide-react");
25241
25022
  init_editor();
25242
25023
  init_idx();
25243
- var import_react84 = require("react");
25024
+ var import_react85 = require("react");
25244
25025
  init_sidebar_context();
25245
25026
  var import_jsx_runtime114 = require("react/jsx-runtime");
25246
25027
  var ALIGNMENTS3 = ["left", "center", "right"];
@@ -25257,33 +25038,33 @@ var SocialItemToolbar = () => {
25257
25038
  const socialItemElement = focusIdx ? getValueByIdx(template, focusIdx) : null;
25258
25039
  const parentSocialElement = focusIdx ? getParentByIdx(template, focusIdx) : null;
25259
25040
  const parentSocialStyle = parentSocialElement?.data?.value?.socialStyle || "Icon + Text";
25260
- const currentFontFamily = (0, import_react84.useMemo)(() => {
25041
+ const currentFontFamily = (0, import_react85.useMemo)(() => {
25261
25042
  return socialItemElement?.attributes?.["font-family"] || "Arial";
25262
25043
  }, [socialItemElement]);
25263
- const currentFontSize = (0, import_react84.useMemo)(() => {
25044
+ const currentFontSize = (0, import_react85.useMemo)(() => {
25264
25045
  return parseFontSize(socialItemElement?.attributes?.["font-size"]);
25265
25046
  }, [socialItemElement]);
25266
- const currentTextColor = (0, import_react84.useMemo)(() => {
25047
+ const currentTextColor = (0, import_react85.useMemo)(() => {
25267
25048
  return socialItemElement?.attributes?.["color"] || "#000000";
25268
25049
  }, [socialItemElement]);
25269
- const isBold = (0, import_react84.useMemo)(() => {
25050
+ const isBold = (0, import_react85.useMemo)(() => {
25270
25051
  return socialItemElement?.attributes?.["font-weight"] === "bold";
25271
25052
  }, [socialItemElement]);
25272
- const isItalic = (0, import_react84.useMemo)(() => {
25053
+ const isItalic = (0, import_react85.useMemo)(() => {
25273
25054
  return socialItemElement?.attributes?.["font-style"] === "italic";
25274
25055
  }, [socialItemElement]);
25275
- const isUnderline = (0, import_react84.useMemo)(() => {
25056
+ const isUnderline = (0, import_react85.useMemo)(() => {
25276
25057
  const decoration = socialItemElement?.attributes?.["text-decoration"] || "";
25277
25058
  return decoration.includes("underline");
25278
25059
  }, [socialItemElement]);
25279
- const isStrikethrough = (0, import_react84.useMemo)(() => {
25060
+ const isStrikethrough = (0, import_react85.useMemo)(() => {
25280
25061
  const decoration = socialItemElement?.attributes?.["text-decoration"] || "";
25281
25062
  return decoration.includes("line-through");
25282
25063
  }, [socialItemElement]);
25283
- const currentAlign = (0, import_react84.useMemo)(() => {
25064
+ const currentAlign = (0, import_react85.useMemo)(() => {
25284
25065
  return socialItemElement?.attributes?.["align"] || "center";
25285
25066
  }, [socialItemElement]);
25286
- const handleSetFontFamily = (0, import_react84.useCallback)((font) => {
25067
+ const handleSetFontFamily = (0, import_react85.useCallback)((font) => {
25287
25068
  if (!focusIdx) return;
25288
25069
  const currentTemplate = useEditorStore.getState().template;
25289
25070
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25294,7 +25075,7 @@ var SocialItemToolbar = () => {
25294
25075
  }
25295
25076
  });
25296
25077
  }, [focusIdx, updateElement]);
25297
- const handleFontSizeChange = (0, import_react84.useCallback)((size) => {
25078
+ const handleFontSizeChange = (0, import_react85.useCallback)((size) => {
25298
25079
  if (!focusIdx) return;
25299
25080
  const currentTemplate = useEditorStore.getState().template;
25300
25081
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25305,12 +25086,12 @@ var SocialItemToolbar = () => {
25305
25086
  }
25306
25087
  });
25307
25088
  }, [focusIdx, updateElement]);
25308
- const handleOpenTextColorPicker = (0, import_react84.useCallback)(() => {
25089
+ const handleOpenTextColorPicker = (0, import_react85.useCallback)(() => {
25309
25090
  setColorType("Text Color");
25310
25091
  setColorTarget("socialItemTextColor");
25311
25092
  setActiveView("color");
25312
25093
  }, [setColorType, setColorTarget, setActiveView]);
25313
- const handleToggleBold = (0, import_react84.useCallback)(() => {
25094
+ const handleToggleBold = (0, import_react85.useCallback)(() => {
25314
25095
  if (!focusIdx) return;
25315
25096
  const currentTemplate = useEditorStore.getState().template;
25316
25097
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25322,7 +25103,7 @@ var SocialItemToolbar = () => {
25322
25103
  }
25323
25104
  });
25324
25105
  }, [focusIdx, isBold, updateElement]);
25325
- const handleToggleItalic = (0, import_react84.useCallback)(() => {
25106
+ const handleToggleItalic = (0, import_react85.useCallback)(() => {
25326
25107
  if (!focusIdx) return;
25327
25108
  const currentTemplate = useEditorStore.getState().template;
25328
25109
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25334,7 +25115,7 @@ var SocialItemToolbar = () => {
25334
25115
  }
25335
25116
  });
25336
25117
  }, [focusIdx, isItalic, updateElement]);
25337
- const handleToggleUnderline = (0, import_react84.useCallback)(() => {
25118
+ const handleToggleUnderline = (0, import_react85.useCallback)(() => {
25338
25119
  if (!focusIdx) return;
25339
25120
  const currentTemplate = useEditorStore.getState().template;
25340
25121
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25352,7 +25133,7 @@ var SocialItemToolbar = () => {
25352
25133
  }
25353
25134
  });
25354
25135
  }, [focusIdx, isUnderline, updateElement]);
25355
- const handleToggleStrike = (0, import_react84.useCallback)(() => {
25136
+ const handleToggleStrike = (0, import_react85.useCallback)(() => {
25356
25137
  if (!focusIdx) return;
25357
25138
  const currentTemplate = useEditorStore.getState().template;
25358
25139
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25370,7 +25151,7 @@ var SocialItemToolbar = () => {
25370
25151
  }
25371
25152
  });
25372
25153
  }, [focusIdx, isStrikethrough, updateElement]);
25373
- const handleRemoveFormatting = (0, import_react84.useCallback)(() => {
25154
+ const handleRemoveFormatting = (0, import_react85.useCallback)(() => {
25374
25155
  if (!focusIdx) return;
25375
25156
  const currentTemplate = useEditorStore.getState().template;
25376
25157
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25388,7 +25169,7 @@ var SocialItemToolbar = () => {
25388
25169
  attributes: restAttributes
25389
25170
  });
25390
25171
  }, [focusIdx, updateElement]);
25391
- const handleCycleAlign = (0, import_react84.useCallback)(() => {
25172
+ const handleCycleAlign = (0, import_react85.useCallback)(() => {
25392
25173
  if (!focusIdx) return;
25393
25174
  const currentTemplate = useEditorStore.getState().template;
25394
25175
  const element = getValueByIdx(currentTemplate, focusIdx);
@@ -25544,7 +25325,7 @@ init_label();
25544
25325
  init_popover();
25545
25326
  init_tooltip();
25546
25327
  var import_lucide_react69 = require("lucide-react");
25547
- var import_react85 = require("react");
25328
+ var import_react86 = require("react");
25548
25329
  var import_jsx_runtime115 = require("react/jsx-runtime");
25549
25330
  var StrokeWeight2 = ({
25550
25331
  width,
@@ -25553,34 +25334,11 @@ var StrokeWeight2 = ({
25553
25334
  onStyleChange,
25554
25335
  tooltipText = "Stroke Weight"
25555
25336
  }) => {
25556
- const [isOpen, setIsOpen] = (0, import_react85.useState)(false);
25557
- const [inputValue, setInputValue] = (0, import_react85.useState)(width.toString());
25558
- (0, import_react85.useEffect)(() => {
25559
- setInputValue(width.toString());
25560
- }, [width]);
25561
- const handleSliderChange = (0, import_react85.useCallback)((values) => {
25562
- const newWidth = values[0];
25563
- setInputValue(newWidth.toString());
25564
- onWidthChange(newWidth);
25337
+ const [isOpen, setIsOpen] = (0, import_react86.useState)(false);
25338
+ const input = useEditableNumber({ value: width, onChange: onWidthChange, min: 1, max: 50 });
25339
+ const handleSliderChange = (0, import_react86.useCallback)((values) => {
25340
+ onWidthChange(values[0]);
25565
25341
  }, [onWidthChange]);
25566
- const handleInputChange = (0, import_react85.useCallback)((e) => {
25567
- setInputValue(e.target.value);
25568
- }, []);
25569
- const handleInputBlur = (0, import_react85.useCallback)(() => {
25570
- const parsed = parseInt(inputValue, 10);
25571
- if (isNaN(parsed)) {
25572
- setInputValue(width.toString());
25573
- return;
25574
- }
25575
- const clamped = Math.max(1, Math.min(50, parsed));
25576
- setInputValue(clamped.toString());
25577
- onWidthChange(clamped);
25578
- }, [inputValue, width, onWidthChange]);
25579
- const handleInputKeyDown = (0, import_react85.useCallback)((e) => {
25580
- if (e.key === "Enter") {
25581
- handleInputBlur();
25582
- }
25583
- }, [handleInputBlur]);
25584
25342
  return /* @__PURE__ */ (0, import_jsx_runtime115.jsxs)(Tooltip, { children: [
25585
25343
  /* @__PURE__ */ (0, import_jsx_runtime115.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
25586
25344
  /* @__PURE__ */ (0, import_jsx_runtime115.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime115.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime115.jsx)(
@@ -25646,10 +25404,11 @@ var StrokeWeight2 = ({
25646
25404
  Input,
25647
25405
  {
25648
25406
  type: "number",
25649
- value: inputValue,
25650
- onChange: handleInputChange,
25651
- onBlur: handleInputBlur,
25652
- onKeyDown: handleInputKeyDown,
25407
+ value: input.displayValue,
25408
+ onChange: (e) => input.setLocalValue(e.target.value),
25409
+ onFocus: input.handleFocus,
25410
+ onBlur: input.handleBlur,
25411
+ onKeyDown: input.handleKeyDown,
25653
25412
  className: "w-25 shadow-none rounded-[12px]",
25654
25413
  min: 1,
25655
25414
  max: 50
@@ -25664,12 +25423,12 @@ var StrokeWeight2 = ({
25664
25423
  };
25665
25424
 
25666
25425
  // src/core/editor/hooks/use-divider-border.ts
25667
- var import_react86 = require("react");
25426
+ var import_react87 = require("react");
25668
25427
  init_editor();
25669
25428
  init_idx();
25670
25429
  var useDividerBorder = () => {
25671
25430
  const { focusIdx, updateElement, template } = useEditorStore();
25672
- const { element, width, style, color } = (0, import_react86.useMemo)(() => {
25431
+ const { element, width, style, color } = (0, import_react87.useMemo)(() => {
25673
25432
  if (!focusIdx || !template) {
25674
25433
  return { element: null, width: 1, style: "solid", color: "#000000" };
25675
25434
  }
@@ -25687,7 +25446,7 @@ var useDividerBorder = () => {
25687
25446
  color: rawColor
25688
25447
  };
25689
25448
  }, [focusIdx, template]);
25690
- const setWidth = (0, import_react86.useCallback)((newWidth) => {
25449
+ const setWidth = (0, import_react87.useCallback)((newWidth) => {
25691
25450
  if (!focusIdx || !template || !element) return;
25692
25451
  const clampedWidth = Math.max(1, Math.min(50, newWidth));
25693
25452
  updateElement(focusIdx, {
@@ -25697,7 +25456,7 @@ var useDividerBorder = () => {
25697
25456
  }
25698
25457
  });
25699
25458
  }, [focusIdx, template, element, updateElement]);
25700
- const setStyle = (0, import_react86.useCallback)((newStyle) => {
25459
+ const setStyle = (0, import_react87.useCallback)((newStyle) => {
25701
25460
  if (!focusIdx || !template || !element) return;
25702
25461
  updateElement(focusIdx, {
25703
25462
  attributes: {
@@ -25716,12 +25475,12 @@ var useDividerBorder = () => {
25716
25475
  };
25717
25476
 
25718
25477
  // src/core/editor/hooks/use-width.ts
25719
- var import_react87 = require("react");
25478
+ var import_react88 = require("react");
25720
25479
  init_editor();
25721
25480
  init_idx();
25722
25481
  var useWidth = () => {
25723
25482
  const { focusIdx, updateElement, template } = useEditorStore();
25724
- const currentValue = (0, import_react87.useMemo)(() => {
25483
+ const currentValue = (0, import_react88.useMemo)(() => {
25725
25484
  if (!focusIdx || !template) return 100;
25726
25485
  const element = getValueByIdx(template, focusIdx);
25727
25486
  const rawValue = element?.attributes?.width;
@@ -25729,7 +25488,7 @@ var useWidth = () => {
25729
25488
  const parsed = parseFloat(rawValue.replace("%", ""));
25730
25489
  return isNaN(parsed) ? 100 : Math.max(10, Math.min(100, parsed));
25731
25490
  }, [focusIdx, template]);
25732
- const handleChange = (0, import_react87.useCallback)((value) => {
25491
+ const handleChange = (0, import_react88.useCallback)((value) => {
25733
25492
  if (!focusIdx || !template) return;
25734
25493
  const element = getValueByIdx(template, focusIdx);
25735
25494
  if (!element) return;
@@ -25750,7 +25509,7 @@ var useWidth = () => {
25750
25509
  // src/core/editor/components/element-gear/divider/toolbar.tsx
25751
25510
  init_editor();
25752
25511
  init_sidebar_context();
25753
- var import_react88 = require("react");
25512
+ var import_react89 = require("react");
25754
25513
  var import_get4 = __toESM(require("lodash/get"));
25755
25514
  init_configuration();
25756
25515
  var import_jsx_runtime116 = require("react/jsx-runtime");
@@ -25761,24 +25520,24 @@ var DividerToolbar = () => {
25761
25520
  const border = useDividerBorder();
25762
25521
  const padding = usePadding();
25763
25522
  const width = useWidth();
25764
- const currentElement = (0, import_react88.useMemo)(() => {
25523
+ const currentElement = (0, import_react89.useMemo)(() => {
25765
25524
  if (!focusIdx || !template) return null;
25766
25525
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
25767
25526
  return (0, import_get4.default)(template, path);
25768
25527
  }, [focusIdx, template]);
25769
25528
  const currentAlign = currentElement?.attributes?.align || "center";
25770
25529
  const currentBgColor = currentElement?.attributes?.["container-background-color"];
25771
- const handleOpenBgColorPicker = (0, import_react88.useCallback)(() => {
25530
+ const handleOpenBgColorPicker = (0, import_react89.useCallback)(() => {
25772
25531
  setColorType("Background Color");
25773
25532
  setColorTarget("dividerBgColor");
25774
25533
  setActiveView("color");
25775
25534
  }, [setColorType, setColorTarget, setActiveView]);
25776
- const handleOpenStrokeColorPicker = (0, import_react88.useCallback)(() => {
25535
+ const handleOpenStrokeColorPicker = (0, import_react89.useCallback)(() => {
25777
25536
  setColorType("Stroke Color");
25778
25537
  setColorTarget("dividerBorderColor");
25779
25538
  setActiveView("color");
25780
25539
  }, [setColorType, setColorTarget, setActiveView]);
25781
- const handleCycleAlign = (0, import_react88.useCallback)(() => {
25540
+ const handleCycleAlign = (0, import_react89.useCallback)(() => {
25782
25541
  if (!focusIdx || !currentElement) return;
25783
25542
  const currentIndex = DIVIDER_ALIGNMENTS.indexOf(currentAlign);
25784
25543
  const nextIndex = (currentIndex + 1) % DIVIDER_ALIGNMENTS.length;
@@ -25851,7 +25610,7 @@ var DividerToolbar = () => {
25851
25610
  };
25852
25611
 
25853
25612
  // src/core/editor/components/element-gear/image/toolbar.tsx
25854
- var import_react89 = require("react");
25613
+ var import_react90 = require("react");
25855
25614
  init_button();
25856
25615
  init_tooltip();
25857
25616
  init_editor();
@@ -25862,31 +25621,31 @@ var import_jsx_runtime117 = require("react/jsx-runtime");
25862
25621
  var ImageToolbar = () => {
25863
25622
  const { focusIdx, template, updateElement } = useEditorStore();
25864
25623
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
25865
- const currentElement = (0, import_react89.useMemo)(() => {
25624
+ const currentElement = (0, import_react90.useMemo)(() => {
25866
25625
  if (!focusIdx || !template) return null;
25867
25626
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
25868
25627
  return (0, import_lodash19.get)(template, path);
25869
25628
  }, [focusIdx, template]);
25870
- const currentBgColor = (0, import_react89.useMemo)(() => {
25629
+ const currentBgColor = (0, import_react90.useMemo)(() => {
25871
25630
  return currentElement?.attributes?.["container-background-color"];
25872
25631
  }, [currentElement]);
25873
- const currentAlign = (0, import_react89.useMemo)(() => {
25632
+ const currentAlign = (0, import_react90.useMemo)(() => {
25874
25633
  return currentElement?.attributes?.["align"] || "center";
25875
25634
  }, [currentElement]);
25876
25635
  const border = useBorder();
25877
25636
  const borderRadius = useBorderRadius();
25878
25637
  const padding = usePadding();
25879
- const handleOpenBgColorPicker = (0, import_react89.useCallback)(() => {
25638
+ const handleOpenBgColorPicker = (0, import_react90.useCallback)(() => {
25880
25639
  setColorType("Background Color");
25881
25640
  setColorTarget("imageBgColor");
25882
25641
  setActiveView("color");
25883
25642
  }, [setColorType, setColorTarget, setActiveView]);
25884
- const handleOpenStrokeColorPicker = (0, import_react89.useCallback)(() => {
25643
+ const handleOpenStrokeColorPicker = (0, import_react90.useCallback)(() => {
25885
25644
  setColorType("Stroke Color");
25886
25645
  setColorTarget("strokeColor");
25887
25646
  setActiveView("color");
25888
25647
  }, [setColorType, setColorTarget, setActiveView]);
25889
- const handleCycleAlign = (0, import_react89.useCallback)(() => {
25648
+ const handleCycleAlign = (0, import_react90.useCallback)(() => {
25890
25649
  if (!focusIdx || !currentElement) return;
25891
25650
  const currentIndex = BUTTON_ALIGNMENTS.indexOf(currentAlign);
25892
25651
  const nextIndex = (currentIndex + 1) % BUTTON_ALIGNMENTS.length;
@@ -25969,7 +25728,7 @@ var ImageToolbar = () => {
25969
25728
  };
25970
25729
 
25971
25730
  // src/core/editor/components/element-gear/property/toolbar.tsx
25972
- var import_react91 = require("react");
25731
+ var import_react92 = require("react");
25973
25732
  init_sidebar_context();
25974
25733
  init_editor();
25975
25734
  init_idx();
@@ -25982,7 +25741,7 @@ init_button();
25982
25741
  var import_lucide_react71 = require("lucide-react");
25983
25742
  init_popover();
25984
25743
  init_tooltip();
25985
- var import_react90 = require("react");
25744
+ var import_react91 = require("react");
25986
25745
  init_input();
25987
25746
  init_textarea();
25988
25747
 
@@ -26071,247 +25830,94 @@ var CARD_FEATURES = {
26071
25830
  var PropertyEditMenu = () => {
26072
25831
  const { focusIdx, template, updateElement } = useEditorStore();
26073
25832
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
26074
- const [isOpen, setIsOpen] = (0, import_react90.useState)(false);
26075
- const [openSection, setOpenSection] = (0, import_react90.useState)(null);
26076
- const [openhouseEnabled, setOpenhouseEnabled] = (0, import_react90.useState)(true);
26077
- const [openhouseDate, setOpenhouseDate] = (0, import_react90.useState)(/* @__PURE__ */ new Date());
26078
- const [openhouseStartTime, setOpenhouseStartTime] = (0, import_react90.useState)("12:00");
26079
- const [openhouseEndTime, setOpenhouseEndTime] = (0, import_react90.useState)("13:00");
26080
- const propertyElement = (0, import_react90.useMemo)(() => {
25833
+ const [isOpen, setIsOpen] = (0, import_react91.useState)(false);
25834
+ const [openSection, setOpenSection] = (0, import_react91.useState)(null);
25835
+ const [openhouseDate, setOpenhouseDate] = (0, import_react91.useState)(/* @__PURE__ */ new Date());
25836
+ const [openhouseStartTime, setOpenhouseStartTime] = (0, import_react91.useState)("12:00");
25837
+ const [openhouseEndTime, setOpenhouseEndTime] = (0, import_react91.useState)("13:00");
25838
+ const [addressLine1Input, setAddressLine1Input] = (0, import_react91.useState)("");
25839
+ const [addressLine2Input, setAddressLine2Input] = (0, import_react91.useState)("");
25840
+ const [cityInput, setCityInput] = (0, import_react91.useState)("");
25841
+ const [stateInput, setStateInput] = (0, import_react91.useState)("");
25842
+ const [zipInput, setZipInput] = (0, import_react91.useState)("");
25843
+ const propertyElement = (0, import_react91.useMemo)(() => {
26081
25844
  if (!focusIdx || !template) return null;
26082
25845
  return getValueByIdx(template, focusIdx);
26083
25846
  }, [focusIdx, template]);
26084
25847
  const cardType = propertyElement?.type;
26085
25848
  const features = cardType ? CARD_FEATURES[cardType] : null;
26086
- const currentPrice = (0, import_react90.useMemo)(() => {
25849
+ const currentPrice = (0, import_react91.useMemo)(() => {
26087
25850
  const rawPrice = propertyElement?.attributes?.["price"] || "";
26088
25851
  return parsePrice(rawPrice);
26089
25852
  }, [propertyElement]);
26090
- const [priceInput, setPriceInput] = (0, import_react90.useState)(currentPrice);
26091
- (0, import_react90.useEffect)(() => {
26092
- setPriceInput(currentPrice);
26093
- }, [currentPrice]);
26094
- const handlePriceBlur = (0, import_react90.useCallback)(() => {
26095
- if (!focusIdx || !propertyElement) return;
26096
- if (priceInput === currentPrice) return;
26097
- updateElement(focusIdx, {
26098
- attributes: {
26099
- ...propertyElement.attributes,
26100
- "price": priceInput
26101
- }
26102
- });
26103
- }, [focusIdx, propertyElement, priceInput, currentPrice, updateElement]);
26104
- const currentBeds = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["beds"] || "", [propertyElement]);
26105
- const currentBaths = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["baths"] || "", [propertyElement]);
26106
- const currentSqft = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["sqft"] || "", [propertyElement]);
26107
- const currentDescription = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["description"] || "", [propertyElement]);
26108
- const currentIsDescription = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["is-description"] || "", [propertyElement]);
26109
- const currentBrokerage = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["brokerage"] || "", [propertyElement]);
26110
- const currentIsBrokerage = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["is-brokerage"] || "", [propertyElement]);
26111
- const currentStatus = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["status"] || "", [propertyElement]);
26112
- const currentIsStatus = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["is-status"] || "", [propertyElement]);
26113
- const currentIsNew = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["is-new"] || "", [propertyElement]);
26114
- const currentStatusColor = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["status-color"] || "#B8B8B8", [propertyElement]);
26115
- const currentIsOpenHouse = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["is-open-house"] || "", [propertyElement]);
26116
- const currentOpenHouseDate = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["open-house-date"] || "", [propertyElement]);
26117
- const currentOpenHouseTime = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["open-house-time"] || "", [propertyElement]);
26118
- const currentAddress = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["address"] || "", [propertyElement]);
26119
- const currentCity = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["city"] || "", [propertyElement]);
26120
- const currentCountry = (0, import_react90.useMemo)(() => propertyElement?.attributes?.["country"] || "USA", [propertyElement]);
26121
- const [bedsInput, setBedsInput] = (0, import_react90.useState)(currentBeds);
26122
- const [bathsInput, setBathsInput] = (0, import_react90.useState)(currentBaths);
26123
- const [sqftInput, setSqftInput] = (0, import_react90.useState)(currentSqft);
26124
- const [descriptionInput, setDescriptionInput] = (0, import_react90.useState)(currentDescription);
26125
- const [isDescriptionEnabled, setIsDescriptionEnabled] = (0, import_react90.useState)(!!currentIsDescription);
26126
- const [brokerageInput, setBrokerageInput] = (0, import_react90.useState)(currentBrokerage);
26127
- const [isBrokerageEnabled, setIsBrokerageEnabled] = (0, import_react90.useState)(!!currentIsBrokerage);
26128
- const [statusInput, setStatusInput] = (0, import_react90.useState)(currentStatus);
26129
- const [isStatusEnabled, setIsStatusEnabled] = (0, import_react90.useState)(!!currentIsStatus);
26130
- const [isNewEnabled, setIsNewEnabled] = (0, import_react90.useState)(!!currentIsNew);
26131
- const [addressLine1Input, setAddressLine1Input] = (0, import_react90.useState)("");
26132
- const [addressLine2Input, setAddressLine2Input] = (0, import_react90.useState)("");
26133
- const [cityInput, setCityInput] = (0, import_react90.useState)("");
26134
- const [stateInput, setStateInput] = (0, import_react90.useState)("");
26135
- const [zipInput, setZipInput] = (0, import_react90.useState)("");
26136
- const [countryInput, setCountryInput] = (0, import_react90.useState)("USA");
26137
- (0, import_react90.useEffect)(() => {
26138
- setBedsInput(currentBeds);
26139
- }, [currentBeds]);
26140
- (0, import_react90.useEffect)(() => {
26141
- setBathsInput(currentBaths);
26142
- }, [currentBaths]);
26143
- (0, import_react90.useEffect)(() => {
26144
- setSqftInput(currentSqft);
26145
- }, [currentSqft]);
26146
- (0, import_react90.useEffect)(() => {
26147
- setDescriptionInput(currentDescription);
26148
- }, [currentDescription]);
26149
- (0, import_react90.useEffect)(() => {
26150
- setIsDescriptionEnabled(!!currentIsDescription);
26151
- }, [currentIsDescription]);
26152
- (0, import_react90.useEffect)(() => {
26153
- setBrokerageInput(currentBrokerage);
26154
- }, [currentBrokerage]);
26155
- (0, import_react90.useEffect)(() => {
26156
- setIsBrokerageEnabled(!!currentIsBrokerage);
26157
- }, [currentIsBrokerage]);
26158
- (0, import_react90.useEffect)(() => {
26159
- setStatusInput(currentStatus);
26160
- }, [currentStatus]);
26161
- (0, import_react90.useEffect)(() => {
26162
- setIsStatusEnabled(!!currentIsStatus);
26163
- }, [currentIsStatus]);
26164
- (0, import_react90.useEffect)(() => {
26165
- setIsNewEnabled(!!currentIsNew);
26166
- }, [currentIsNew]);
26167
- (0, import_react90.useEffect)(() => {
26168
- setOpenhouseEnabled(!!currentIsOpenHouse);
26169
- }, [currentIsOpenHouse]);
26170
- (0, import_react90.useEffect)(() => {
26171
- if (currentOpenHouseDate) {
26172
- const parsed = new Date(currentOpenHouseDate);
26173
- if (!isNaN(parsed.getTime())) {
26174
- setOpenhouseDate(parsed);
26175
- }
26176
- }
26177
- }, [currentOpenHouseDate]);
26178
- (0, import_react90.useEffect)(() => {
26179
- if (currentOpenHouseTime) {
26180
- const [start, end] = currentOpenHouseTime.split("-");
26181
- if (start) setOpenhouseStartTime(start);
26182
- if (end) setOpenhouseEndTime(end);
26183
- }
26184
- }, [currentOpenHouseTime]);
26185
- (0, import_react90.useEffect)(() => {
26186
- setAddressLine1Input(currentAddress);
26187
- setAddressLine2Input("");
26188
- }, [currentAddress]);
26189
- (0, import_react90.useEffect)(() => {
26190
- const match = currentCity.match(/^(.+),\s*(\w{2})\s*(\d{5})?$/);
26191
- if (match) {
26192
- setCityInput(match[1] || "");
26193
- setStateInput(match[2] || "");
26194
- setZipInput(match[3] || "");
26195
- } else {
26196
- setCityInput(currentCity);
26197
- setStateInput("");
26198
- setZipInput("");
26199
- }
26200
- }, [currentCity]);
26201
- (0, import_react90.useEffect)(() => {
26202
- setCountryInput(currentCountry);
26203
- }, [currentCountry]);
26204
- const handleBedsBlur = (0, import_react90.useCallback)(() => {
26205
- if (!focusIdx || !propertyElement) return;
26206
- if (bedsInput === currentBeds) return;
26207
- updateElement(focusIdx, {
26208
- attributes: {
26209
- ...propertyElement.attributes,
26210
- "beds": bedsInput
26211
- }
26212
- });
26213
- }, [focusIdx, propertyElement, bedsInput, currentBeds, updateElement]);
26214
- const handleBathsBlur = (0, import_react90.useCallback)(() => {
25853
+ const currentBeds = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["beds"] || "", [propertyElement]);
25854
+ const currentBaths = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["baths"] || "", [propertyElement]);
25855
+ const currentSqft = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["sqft"] || "", [propertyElement]);
25856
+ const currentDescription = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["description"] || "", [propertyElement]);
25857
+ const currentIsDescription = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["is-description"] || "", [propertyElement]);
25858
+ const currentBrokerage = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["brokerage"] || "", [propertyElement]);
25859
+ const currentIsBrokerage = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["is-brokerage"] || "", [propertyElement]);
25860
+ const currentStatus = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["status"] || "", [propertyElement]);
25861
+ const currentIsStatus = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["is-status"] || "", [propertyElement]);
25862
+ const currentIsNew = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["is-new"] || "", [propertyElement]);
25863
+ const currentStatusColor = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["status-color"] || "#B8B8B8", [propertyElement]);
25864
+ const currentIsOpenHouse = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["is-open-house"] || "", [propertyElement]);
25865
+ const currentOpenHouseDate = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["open-house-date"] || "", [propertyElement]);
25866
+ const currentOpenHouseTime = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["open-house-time"] || "", [propertyElement]);
25867
+ const currentAddress = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["address"] || "", [propertyElement]);
25868
+ const currentCity = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["city"] || "", [propertyElement]);
25869
+ const currentCountry = (0, import_react91.useMemo)(() => propertyElement?.attributes?.["country"] || "USA", [propertyElement]);
25870
+ const commitAttribute = (0, import_react91.useCallback)((key, value) => {
26215
25871
  if (!focusIdx || !propertyElement) return;
26216
- if (bathsInput === currentBaths) return;
26217
25872
  updateElement(focusIdx, {
26218
- attributes: {
26219
- ...propertyElement.attributes,
26220
- "baths": bathsInput
26221
- }
26222
- });
26223
- }, [focusIdx, propertyElement, bathsInput, currentBaths, updateElement]);
26224
- const handleSqftBlur = (0, import_react90.useCallback)(() => {
26225
- if (!focusIdx || !propertyElement) return;
26226
- if (sqftInput === currentSqft) return;
26227
- updateElement(focusIdx, {
26228
- attributes: {
26229
- ...propertyElement.attributes,
26230
- "sqft": sqftInput
26231
- }
26232
- });
26233
- }, [focusIdx, propertyElement, sqftInput, currentSqft, updateElement]);
26234
- const handleDescriptionBlur = (0, import_react90.useCallback)(() => {
26235
- if (!focusIdx || !propertyElement) return;
26236
- if (descriptionInput === currentDescription) return;
26237
- updateElement(focusIdx, {
26238
- attributes: {
26239
- ...propertyElement.attributes,
26240
- "description": descriptionInput
26241
- }
26242
- });
26243
- }, [focusIdx, propertyElement, descriptionInput, currentDescription, updateElement]);
26244
- const handleIsDescriptionChange = (0, import_react90.useCallback)((checked) => {
26245
- setIsDescriptionEnabled(checked);
26246
- if (!focusIdx || !propertyElement) return;
26247
- updateElement(focusIdx, {
26248
- attributes: {
26249
- ...propertyElement.attributes,
26250
- "is-description": checked ? "show" : ""
26251
- }
25873
+ attributes: { ...propertyElement.attributes, [key]: value }
26252
25874
  });
26253
25875
  }, [focusIdx, propertyElement, updateElement]);
26254
- const handleBrokerageBlur = (0, import_react90.useCallback)(() => {
25876
+ const commitPrice = (0, import_react91.useCallback)((v) => commitAttribute("price", v), [commitAttribute]);
25877
+ const commitBeds = (0, import_react91.useCallback)((v) => commitAttribute("beds", v), [commitAttribute]);
25878
+ const commitBaths = (0, import_react91.useCallback)((v) => commitAttribute("baths", v), [commitAttribute]);
25879
+ const commitSqft = (0, import_react91.useCallback)((v) => commitAttribute("sqft", v), [commitAttribute]);
25880
+ const commitDescription = (0, import_react91.useCallback)((v) => commitAttribute("description", v), [commitAttribute]);
25881
+ const commitBrokerage = (0, import_react91.useCallback)((v) => commitAttribute("brokerage", v), [commitAttribute]);
25882
+ const commitStatus = (0, import_react91.useCallback)((v) => commitAttribute("status", v), [commitAttribute]);
25883
+ const priceInput = useEditableValue({ externalValue: currentPrice, onChange: commitPrice });
25884
+ const bedsInput = useEditableValue({ externalValue: currentBeds, onChange: commitBeds });
25885
+ const bathsInput = useEditableValue({ externalValue: currentBaths, onChange: commitBaths });
25886
+ const sqftInput = useEditableValue({ externalValue: currentSqft, onChange: commitSqft });
25887
+ const descriptionInput = useEditableValue({ externalValue: currentDescription, onChange: commitDescription });
25888
+ const brokerageInput = useEditableValue({ externalValue: currentBrokerage, onChange: commitBrokerage });
25889
+ const statusInput = useEditableValue({ externalValue: currentStatus, onChange: commitStatus });
25890
+ const handleIsDescriptionChange = (0, import_react91.useCallback)((checked) => {
26255
25891
  if (!focusIdx || !propertyElement) return;
26256
- if (brokerageInput === currentBrokerage) return;
26257
25892
  updateElement(focusIdx, {
26258
- attributes: {
26259
- ...propertyElement.attributes,
26260
- "brokerage": brokerageInput
26261
- }
26262
- });
26263
- }, [focusIdx, propertyElement, brokerageInput, currentBrokerage, updateElement]);
26264
- const handleIsBrokerageChange = (0, import_react90.useCallback)((checked) => {
26265
- setIsBrokerageEnabled(checked);
26266
- if (!focusIdx || !propertyElement) return;
26267
- updateElement(focusIdx, {
26268
- attributes: {
26269
- ...propertyElement.attributes,
26270
- "is-brokerage": checked ? "show" : ""
26271
- }
25893
+ attributes: { ...propertyElement.attributes, "is-description": checked ? "show" : "" }
26272
25894
  });
26273
25895
  }, [focusIdx, propertyElement, updateElement]);
26274
- const handleStatusBlur = (0, import_react90.useCallback)(() => {
25896
+ const handleIsBrokerageChange = (0, import_react91.useCallback)((checked) => {
26275
25897
  if (!focusIdx || !propertyElement) return;
26276
- if (statusInput === currentStatus) return;
26277
25898
  updateElement(focusIdx, {
26278
- attributes: {
26279
- ...propertyElement.attributes,
26280
- "status": statusInput
26281
- }
25899
+ attributes: { ...propertyElement.attributes, "is-brokerage": checked ? "show" : "" }
26282
25900
  });
26283
- }, [focusIdx, propertyElement, statusInput, currentStatus, updateElement]);
26284
- const handleIsStatusChange = (0, import_react90.useCallback)((checked) => {
26285
- setIsStatusEnabled(checked);
25901
+ }, [focusIdx, propertyElement, updateElement]);
25902
+ const handleIsStatusChange = (0, import_react91.useCallback)((checked) => {
26286
25903
  if (!focusIdx || !propertyElement) return;
26287
25904
  updateElement(focusIdx, {
26288
- attributes: {
26289
- ...propertyElement.attributes,
26290
- "is-status": checked ? "show" : ""
26291
- }
25905
+ attributes: { ...propertyElement.attributes, "is-status": checked ? "show" : "" }
26292
25906
  });
26293
25907
  }, [focusIdx, propertyElement, updateElement]);
26294
- const handleIsNewChange = (0, import_react90.useCallback)((checked) => {
26295
- setIsNewEnabled(checked);
25908
+ const handleIsNewChange = (0, import_react91.useCallback)((checked) => {
26296
25909
  if (!focusIdx || !propertyElement) return;
26297
25910
  updateElement(focusIdx, {
26298
- attributes: {
26299
- ...propertyElement.attributes,
26300
- "is-new": checked ? "show" : ""
26301
- }
25911
+ attributes: { ...propertyElement.attributes, "is-new": checked ? "show" : "" }
26302
25912
  });
26303
25913
  }, [focusIdx, propertyElement, updateElement]);
26304
- const handleIsOpenHouseChange = (0, import_react90.useCallback)((checked) => {
26305
- setOpenhouseEnabled(checked);
25914
+ const handleIsOpenHouseChange = (0, import_react91.useCallback)((checked) => {
26306
25915
  if (!focusIdx || !propertyElement) return;
26307
25916
  updateElement(focusIdx, {
26308
- attributes: {
26309
- ...propertyElement.attributes,
26310
- "is-open-house": checked ? "show" : ""
26311
- }
25917
+ attributes: { ...propertyElement.attributes, "is-open-house": checked ? "show" : "" }
26312
25918
  });
26313
25919
  }, [focusIdx, propertyElement, updateElement]);
26314
- const handleOpenHouseDateBlur = (0, import_react90.useCallback)(() => {
25920
+ const handleOpenHouseDateBlur = (0, import_react91.useCallback)(() => {
26315
25921
  if (!focusIdx || !propertyElement) return;
26316
25922
  const newDate = openhouseDate ? openhouseDate.toISOString().split("T")[0] : "";
26317
25923
  if (newDate === currentOpenHouseDate) return;
@@ -26322,7 +25928,7 @@ var PropertyEditMenu = () => {
26322
25928
  }
26323
25929
  });
26324
25930
  }, [focusIdx, propertyElement, openhouseDate, currentOpenHouseDate, updateElement]);
26325
- const handleOpenHouseTimeBlur = (0, import_react90.useCallback)(() => {
25931
+ const handleOpenHouseTimeBlur = (0, import_react91.useCallback)(() => {
26326
25932
  if (!focusIdx || !propertyElement) return;
26327
25933
  const newTime = `${openhouseStartTime}-${openhouseEndTime}`;
26328
25934
  if (newTime === currentOpenHouseTime) return;
@@ -26333,7 +25939,7 @@ var PropertyEditMenu = () => {
26333
25939
  }
26334
25940
  });
26335
25941
  }, [focusIdx, propertyElement, openhouseStartTime, openhouseEndTime, currentOpenHouseTime, updateElement]);
26336
- const handleAddressBlur = (0, import_react90.useCallback)(() => {
25942
+ const handleAddressBlur = (0, import_react91.useCallback)(() => {
26337
25943
  if (!focusIdx || !propertyElement) return;
26338
25944
  const newAddress = addressLine2Input ? `${addressLine1Input}, ${addressLine2Input}` : addressLine1Input;
26339
25945
  if (newAddress === currentAddress) return;
@@ -26344,7 +25950,7 @@ var PropertyEditMenu = () => {
26344
25950
  }
26345
25951
  });
26346
25952
  }, [focusIdx, propertyElement, addressLine1Input, addressLine2Input, currentAddress, updateElement]);
26347
- const handleCityBlur = (0, import_react90.useCallback)(() => {
25953
+ const handleCityBlur = (0, import_react91.useCallback)(() => {
26348
25954
  if (!focusIdx || !propertyElement) return;
26349
25955
  const newCity = zipInput ? `${cityInput}, ${stateInput} ${zipInput}` : stateInput ? `${cityInput}, ${stateInput}` : cityInput;
26350
25956
  if (newCity === currentCity) return;
@@ -26355,41 +25961,68 @@ var PropertyEditMenu = () => {
26355
25961
  }
26356
25962
  });
26357
25963
  }, [focusIdx, propertyElement, cityInput, stateInput, zipInput, currentCity, updateElement]);
26358
- const handleCountryChange = (0, import_react90.useCallback)((value) => {
26359
- setCountryInput(value);
25964
+ const handleCountryChange = (0, import_react91.useCallback)((value) => {
26360
25965
  if (!focusIdx || !propertyElement) return;
26361
25966
  updateElement(focusIdx, {
26362
- attributes: {
26363
- ...propertyElement.attributes,
26364
- "country": value
26365
- }
25967
+ attributes: { ...propertyElement.attributes, "country": value }
26366
25968
  });
26367
25969
  }, [focusIdx, propertyElement, updateElement]);
26368
- const handleOpenStatusColorPicker = (0, import_react90.useCallback)(() => {
25970
+ const handleOpenStatusColorPicker = (0, import_react91.useCallback)(() => {
26369
25971
  setColorType("Status Color");
26370
25972
  setColorTarget("statusColor");
26371
25973
  setActiveView("color");
26372
25974
  }, [setColorType, setColorTarget, setActiveView]);
26373
- const handleToggle = (0, import_react90.useCallback)((section) => {
25975
+ const handleToggle = (0, import_react91.useCallback)((section) => {
26374
25976
  setOpenSection((prev) => prev === section ? null : section);
26375
25977
  }, []);
26376
- const handleTogglePrice = (0, import_react90.useCallback)(() => handleToggle("price"), [handleToggle]);
26377
- const handleToggleDetails = (0, import_react90.useCallback)(() => handleToggle("details"), [handleToggle]);
26378
- const handleToggleAddress = (0, import_react90.useCallback)(() => handleToggle("address"), [handleToggle]);
26379
- const handleToggleStatus = (0, import_react90.useCallback)(() => handleToggle("status"), [handleToggle]);
26380
- const handleToggleOpenhouse = (0, import_react90.useCallback)(() => handleToggle("openhouse"), [handleToggle]);
26381
- const handleToggleBrokerage = (0, import_react90.useCallback)(() => handleToggle("brokerage"), [handleToggle]);
26382
- const handleToggleDescription = (0, import_react90.useCallback)(() => handleToggle("description"), [handleToggle]);
26383
- const handleToggleMLS = (0, import_react90.useCallback)(() => handleToggle("mls"), [handleToggle]);
25978
+ const handleTogglePrice = (0, import_react91.useCallback)(() => handleToggle("price"), [handleToggle]);
25979
+ const handleToggleDetails = (0, import_react91.useCallback)(() => handleToggle("details"), [handleToggle]);
25980
+ const handleToggleAddress = (0, import_react91.useCallback)(() => {
25981
+ const isOpening = openSection !== "address";
25982
+ handleToggle("address");
25983
+ if (isOpening) {
25984
+ setAddressLine1Input(currentAddress);
25985
+ setAddressLine2Input("");
25986
+ const match = currentCity.match(/^(.+),\s*(\w{2})\s*(\d{5})?$/);
25987
+ if (match) {
25988
+ setCityInput(match[1] || "");
25989
+ setStateInput(match[2] || "");
25990
+ setZipInput(match[3] || "");
25991
+ } else {
25992
+ setCityInput(currentCity);
25993
+ setStateInput("");
25994
+ setZipInput("");
25995
+ }
25996
+ }
25997
+ }, [handleToggle, openSection, currentAddress, currentCity]);
25998
+ const handleToggleStatus = (0, import_react91.useCallback)(() => handleToggle("status"), [handleToggle]);
25999
+ const handleToggleOpenhouse = (0, import_react91.useCallback)(() => {
26000
+ const isOpening = openSection !== "openhouse";
26001
+ handleToggle("openhouse");
26002
+ if (isOpening) {
26003
+ if (currentOpenHouseDate) {
26004
+ const parsed = new Date(currentOpenHouseDate);
26005
+ if (!isNaN(parsed.getTime())) setOpenhouseDate(parsed);
26006
+ }
26007
+ if (currentOpenHouseTime) {
26008
+ const [start, end] = currentOpenHouseTime.split("-");
26009
+ if (start) setOpenhouseStartTime(start);
26010
+ if (end) setOpenhouseEndTime(end);
26011
+ }
26012
+ }
26013
+ }, [handleToggle, openSection, currentOpenHouseDate, currentOpenHouseTime]);
26014
+ const handleToggleBrokerage = (0, import_react91.useCallback)(() => handleToggle("brokerage"), [handleToggle]);
26015
+ const handleToggleDescription = (0, import_react91.useCallback)(() => handleToggle("description"), [handleToggle]);
26016
+ const handleToggleMLS = (0, import_react91.useCallback)(() => handleToggle("mls"), [handleToggle]);
26384
26017
  return /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(Tooltip, { children: [
26385
26018
  /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
26386
26019
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
26387
26020
  Button,
26388
26021
  {
26389
- variant: "outline",
26022
+ variant: "ghost",
26390
26023
  className: "shadow-none transition-none cursor-pointer rounded-[12px]",
26391
26024
  size: "icon",
26392
- children: /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(import_lucide_react71.HouseIcon, { className: "w-4 h-4" })
26025
+ children: /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(import_lucide_react71.SquarePen, { className: "w-4 h-4" })
26393
26026
  }
26394
26027
  ) }) }),
26395
26028
  /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(PopoverContent, { className: "w-84 z-51 mt-1 rounded-[12px] p-2 gap-2 flex flex-col z-50001", children: [
@@ -26407,9 +26040,11 @@ var PropertyEditMenu = () => {
26407
26040
  type: "number",
26408
26041
  placeholder: "Price",
26409
26042
  className: "w-full shadow-none rounded-[12px]",
26410
- value: priceInput,
26411
- onChange: (e) => setPriceInput(e.target.value),
26412
- onBlur: handlePriceBlur
26043
+ value: priceInput.displayValue,
26044
+ onChange: (e) => priceInput.setLocalValue(e.target.value),
26045
+ onFocus: priceInput.handleFocus,
26046
+ onBlur: priceInput.handleBlur,
26047
+ onKeyDown: priceInput.handleKeyDown
26413
26048
  }
26414
26049
  ) }) })
26415
26050
  ] }),
@@ -26428,9 +26063,11 @@ var PropertyEditMenu = () => {
26428
26063
  type: "number",
26429
26064
  placeholder: "Bd",
26430
26065
  className: "w-1/3 shadow-none rounded-[12px]",
26431
- value: bedsInput,
26432
- onChange: (e) => setBedsInput(e.target.value),
26433
- onBlur: handleBedsBlur
26066
+ value: bedsInput.displayValue,
26067
+ onChange: (e) => bedsInput.setLocalValue(e.target.value),
26068
+ onFocus: bedsInput.handleFocus,
26069
+ onBlur: bedsInput.handleBlur,
26070
+ onKeyDown: bedsInput.handleKeyDown
26434
26071
  }
26435
26072
  ),
26436
26073
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
@@ -26439,9 +26076,11 @@ var PropertyEditMenu = () => {
26439
26076
  type: "number",
26440
26077
  placeholder: "Ba",
26441
26078
  className: "w-1/3 shadow-none rounded-[12px]",
26442
- value: bathsInput,
26443
- onChange: (e) => setBathsInput(e.target.value),
26444
- onBlur: handleBathsBlur
26079
+ value: bathsInput.displayValue,
26080
+ onChange: (e) => bathsInput.setLocalValue(e.target.value),
26081
+ onFocus: bathsInput.handleFocus,
26082
+ onBlur: bathsInput.handleBlur,
26083
+ onKeyDown: bathsInput.handleKeyDown
26445
26084
  }
26446
26085
  ),
26447
26086
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
@@ -26450,9 +26089,11 @@ var PropertyEditMenu = () => {
26450
26089
  type: "number",
26451
26090
  placeholder: "Sqft",
26452
26091
  className: "w-2/4 shadow-none rounded-[12px]",
26453
- value: sqftInput,
26454
- onChange: (e) => setSqftInput(e.target.value),
26455
- onBlur: handleSqftBlur
26092
+ value: sqftInput.displayValue,
26093
+ onChange: (e) => sqftInput.setLocalValue(e.target.value),
26094
+ onFocus: sqftInput.handleFocus,
26095
+ onBlur: sqftInput.handleBlur,
26096
+ onKeyDown: sqftInput.handleKeyDown
26456
26097
  }
26457
26098
  )
26458
26099
  ] }) })
@@ -26513,7 +26154,7 @@ var PropertyEditMenu = () => {
26513
26154
  )
26514
26155
  ] }),
26515
26156
  /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)("div", { className: "flex flex-row items-start justify-start gap-2", children: [
26516
- /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(Select, { value: countryInput, onValueChange: handleCountryChange, children: [
26157
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)(Select, { value: currentCountry, onValueChange: handleCountryChange, children: [
26517
26158
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(SelectTrigger, { className: "w-3/4 shadow-none rounded-[12px]", children: /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(SelectValue, { placeholder: "Country" }) }),
26518
26159
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(SelectContent, { className: "w-full shadow-none rounded-[12px] z-50001", children: /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(SelectItem, { value: "USA", children: "United States" }) })
26519
26160
  ] }),
@@ -26543,11 +26184,11 @@ var PropertyEditMenu = () => {
26543
26184
  Checkbox,
26544
26185
  {
26545
26186
  className: " shadow-none rounded-[12px] w-9 h-9",
26546
- checked: isStatusEnabled,
26187
+ checked: !!currentIsStatus,
26547
26188
  onCheckedChange: (checked) => handleIsStatusChange(checked === "indeterminate" ? false : checked)
26548
26189
  }
26549
26190
  ) }),
26550
- /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: isStatusEnabled ? "Hide Status" : "Show Status" })
26191
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: !!currentIsStatus ? "Hide Status" : "Show Status" })
26551
26192
  ] }),
26552
26193
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
26553
26194
  BackgroundColorBtn,
@@ -26561,13 +26202,15 @@ var PropertyEditMenu = () => {
26561
26202
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
26562
26203
  Input,
26563
26204
  {
26564
- disabled: !isStatusEnabled,
26205
+ disabled: !currentIsStatus,
26565
26206
  type: "text",
26566
26207
  placeholder: "Just Listed",
26567
26208
  className: "w-full shadow-none rounded-[12px]",
26568
- value: statusInput,
26569
- onChange: (e) => setStatusInput(e.target.value),
26570
- onBlur: handleStatusBlur
26209
+ value: statusInput.displayValue,
26210
+ onChange: (e) => statusInput.setLocalValue(e.target.value),
26211
+ onFocus: statusInput.handleFocus,
26212
+ onBlur: statusInput.handleBlur,
26213
+ onKeyDown: statusInput.handleKeyDown
26571
26214
  }
26572
26215
  )
26573
26216
  ] }),
@@ -26578,7 +26221,7 @@ var PropertyEditMenu = () => {
26578
26221
  "aria-label": "Toggle new label",
26579
26222
  size: "sm",
26580
26223
  variant: "outline",
26581
- pressed: isNewEnabled,
26224
+ pressed: !!currentIsNew,
26582
26225
  onPressedChange: handleIsNewChange,
26583
26226
  children: [
26584
26227
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(import_lucide_react71.CircleCheckIcon, { className: "group-aria-pressed/toggle:fill-foreground" }),
@@ -26600,16 +26243,16 @@ var PropertyEditMenu = () => {
26600
26243
  Checkbox,
26601
26244
  {
26602
26245
  className: "shadow-none rounded-[12px] w-9 h-9",
26603
- checked: openhouseEnabled,
26246
+ checked: !!currentIsOpenHouse,
26604
26247
  onCheckedChange: (checked) => handleIsOpenHouseChange(checked === "indeterminate" ? false : checked)
26605
26248
  }
26606
26249
  ) }),
26607
- /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: openhouseEnabled ? "Disable Open House" : "Enable Open House" })
26250
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: !!currentIsOpenHouse ? "Disable Open House" : "Enable Open House" })
26608
26251
  ] }),
26609
26252
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
26610
26253
  Input,
26611
26254
  {
26612
- disabled: !openhouseEnabled,
26255
+ disabled: !currentIsOpenHouse,
26613
26256
  type: "date",
26614
26257
  value: openhouseDate ? openhouseDate.toISOString().split("T")[0] : "",
26615
26258
  onChange: (e) => setOpenhouseDate(e.target.value ? new Date(e.target.value) : void 0),
@@ -26622,7 +26265,7 @@ var PropertyEditMenu = () => {
26622
26265
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
26623
26266
  Input,
26624
26267
  {
26625
- disabled: !openhouseEnabled,
26268
+ disabled: !currentIsOpenHouse,
26626
26269
  type: "time",
26627
26270
  value: openhouseStartTime,
26628
26271
  onChange: (e) => setOpenhouseStartTime(e.target.value),
@@ -26633,7 +26276,7 @@ var PropertyEditMenu = () => {
26633
26276
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
26634
26277
  Input,
26635
26278
  {
26636
- disabled: !openhouseEnabled,
26279
+ disabled: !currentIsOpenHouse,
26637
26280
  type: "time",
26638
26281
  value: openhouseEndTime,
26639
26282
  onChange: (e) => setOpenhouseEndTime(e.target.value),
@@ -26656,22 +26299,24 @@ var PropertyEditMenu = () => {
26656
26299
  Checkbox,
26657
26300
  {
26658
26301
  className: "shadow-none rounded-[12px] w-9 h-9",
26659
- checked: isBrokerageEnabled,
26302
+ checked: !!currentIsBrokerage,
26660
26303
  onCheckedChange: (checked) => handleIsBrokerageChange(checked === "indeterminate" ? false : checked)
26661
26304
  }
26662
26305
  ) }),
26663
- /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: isBrokerageEnabled ? "Hide Brokerage" : "Show Brokerage" })
26306
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: !!currentIsBrokerage ? "Hide Brokerage" : "Show Brokerage" })
26664
26307
  ] }),
26665
26308
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
26666
26309
  Input,
26667
26310
  {
26668
- disabled: !isBrokerageEnabled,
26311
+ disabled: !currentIsBrokerage,
26669
26312
  type: "text",
26670
26313
  placeholder: "New Era Real Estate",
26671
26314
  className: "w-full shadow-none rounded-[12px]",
26672
- value: brokerageInput,
26673
- onChange: (e) => setBrokerageInput(e.target.value),
26674
- onBlur: handleBrokerageBlur
26315
+ value: brokerageInput.displayValue,
26316
+ onChange: (e) => brokerageInput.setLocalValue(e.target.value),
26317
+ onFocus: brokerageInput.handleFocus,
26318
+ onBlur: brokerageInput.handleBlur,
26319
+ onKeyDown: brokerageInput.handleKeyDown
26675
26320
  }
26676
26321
  )
26677
26322
  ] }),
@@ -26689,28 +26334,29 @@ var PropertyEditMenu = () => {
26689
26334
  Checkbox,
26690
26335
  {
26691
26336
  className: "shadow-none rounded-[12px] w-9 h-9",
26692
- checked: isDescriptionEnabled,
26337
+ checked: !!currentIsDescription,
26693
26338
  onCheckedChange: (checked) => handleIsDescriptionChange(checked === "indeterminate" ? false : checked)
26694
26339
  }
26695
26340
  ) }),
26696
- /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: isDescriptionEnabled ? "Hide Description" : "Show Description" })
26341
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: !!currentIsDescription ? "Hide Description" : "Show Description" })
26697
26342
  ] }),
26698
26343
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(
26699
26344
  Textarea,
26700
26345
  {
26701
- disabled: !isDescriptionEnabled,
26346
+ disabled: !currentIsDescription,
26702
26347
  placeholder: "Beautiful home in the heart of the New Jersey Shore",
26703
26348
  className: "w-full shadow-none rounded-[12px] min-h-fit max-h-34",
26704
- value: descriptionInput,
26705
- onChange: (e) => setDescriptionInput(e.target.value),
26706
- onBlur: handleDescriptionBlur
26349
+ value: descriptionInput.displayValue,
26350
+ onChange: (e) => descriptionInput.setLocalValue(e.target.value),
26351
+ onFocus: descriptionInput.handleFocus,
26352
+ onBlur: descriptionInput.handleBlur
26707
26353
  }
26708
26354
  )
26709
26355
  ] }) })
26710
26356
  ] })
26711
26357
  ] })
26712
26358
  ] }),
26713
- /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: "Edit" })
26359
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: "Information" })
26714
26360
  ] });
26715
26361
  };
26716
26362
 
@@ -26720,51 +26366,51 @@ var import_jsx_runtime121 = require("react/jsx-runtime");
26720
26366
  function PropertyToolbar() {
26721
26367
  const { focusIdx, template, updateElement } = useEditorStore();
26722
26368
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
26723
- const columnIdx = (0, import_react91.useMemo)(() => {
26369
+ const columnIdx = (0, import_react92.useMemo)(() => {
26724
26370
  if (!focusIdx) return null;
26725
26371
  return getParentIdx(focusIdx);
26726
26372
  }, [focusIdx]);
26727
- const columnElement = (0, import_react91.useMemo)(() => {
26373
+ const columnElement = (0, import_react92.useMemo)(() => {
26728
26374
  if (!columnIdx || !template) return null;
26729
26375
  return getValueByIdx(template, columnIdx);
26730
26376
  }, [columnIdx, template]);
26731
- const propertyElement = (0, import_react91.useMemo)(() => {
26377
+ const propertyElement = (0, import_react92.useMemo)(() => {
26732
26378
  if (!focusIdx || !template) return null;
26733
26379
  return getValueByIdx(template, focusIdx);
26734
26380
  }, [focusIdx, template]);
26735
- const currentBgColor = (0, import_react91.useMemo)(() => {
26381
+ const currentBgColor = (0, import_react92.useMemo)(() => {
26736
26382
  return columnElement?.attributes?.["background-color"] || "transparent";
26737
26383
  }, [columnElement]);
26738
- const border = (0, import_react91.useMemo)(() => {
26384
+ const border = (0, import_react92.useMemo)(() => {
26739
26385
  const rawBorder = columnElement?.attributes?.["border"];
26740
26386
  return parseBorder(rawBorder);
26741
26387
  }, [columnElement]);
26742
- const borderRadiusValue = (0, import_react91.useMemo)(() => {
26388
+ const borderRadiusValue = (0, import_react92.useMemo)(() => {
26743
26389
  const rawRadius = columnElement?.attributes?.["border-radius"];
26744
26390
  return parseBorderRadius(rawRadius);
26745
26391
  }, [columnElement]);
26746
- const currentFontFamily = (0, import_react91.useMemo)(() => {
26392
+ const currentFontFamily = (0, import_react92.useMemo)(() => {
26747
26393
  return propertyElement?.attributes?.["font-family"] || "Arial, sans-serif";
26748
26394
  }, [propertyElement]);
26749
- const currentTextColor = (0, import_react91.useMemo)(() => {
26395
+ const currentTextColor = (0, import_react92.useMemo)(() => {
26750
26396
  return propertyElement?.attributes?.["text-color"] || "#111116";
26751
26397
  }, [propertyElement]);
26752
- const handleOpenBgColorPicker = (0, import_react91.useCallback)(() => {
26398
+ const handleOpenBgColorPicker = (0, import_react92.useCallback)(() => {
26753
26399
  setColorType("Background Color");
26754
26400
  setColorTarget("propertyBgColor");
26755
26401
  setActiveView("color");
26756
26402
  }, [setColorType, setColorTarget, setActiveView]);
26757
- const handleOpenStrokeColorPicker = (0, import_react91.useCallback)(() => {
26403
+ const handleOpenStrokeColorPicker = (0, import_react92.useCallback)(() => {
26758
26404
  setColorType("Stroke Color");
26759
26405
  setColorTarget("propertyStrokeColor");
26760
26406
  setActiveView("color");
26761
26407
  }, [setColorType, setColorTarget, setActiveView]);
26762
- const handleOpenTextColorPicker = (0, import_react91.useCallback)(() => {
26408
+ const handleOpenTextColorPicker = (0, import_react92.useCallback)(() => {
26763
26409
  setColorType("Text Color");
26764
26410
  setColorTarget("propertyTextColor");
26765
26411
  setActiveView("color");
26766
26412
  }, [setColorType, setColorTarget, setActiveView]);
26767
- const handleFontChange = (0, import_react91.useCallback)((font) => {
26413
+ const handleFontChange = (0, import_react92.useCallback)((font) => {
26768
26414
  if (!focusIdx || !propertyElement) return;
26769
26415
  updateElement(focusIdx, {
26770
26416
  attributes: {
@@ -26773,7 +26419,7 @@ function PropertyToolbar() {
26773
26419
  }
26774
26420
  });
26775
26421
  }, [focusIdx, propertyElement, updateElement]);
26776
- const handleBorderWidthChange = (0, import_react91.useCallback)((width) => {
26422
+ const handleBorderWidthChange = (0, import_react92.useCallback)((width) => {
26777
26423
  if (!columnIdx || !columnElement || !focusIdx || !propertyElement) return;
26778
26424
  const newBorder = { ...border, width };
26779
26425
  const formattedBorder = formatBorder(newBorder);
@@ -26790,7 +26436,7 @@ function PropertyToolbar() {
26790
26436
  }
26791
26437
  });
26792
26438
  }, [columnIdx, columnElement, focusIdx, propertyElement, border, updateElement]);
26793
- const handleBorderEnabledChange = (0, import_react91.useCallback)((enabled) => {
26439
+ const handleBorderEnabledChange = (0, import_react92.useCallback)((enabled) => {
26794
26440
  if (!columnIdx || !columnElement || !focusIdx || !propertyElement) return;
26795
26441
  const newWidth = enabled ? border.width === 0 ? 1 : border.width : 0;
26796
26442
  const newBorder = { ...border, width: newWidth };
@@ -26808,7 +26454,7 @@ function PropertyToolbar() {
26808
26454
  }
26809
26455
  });
26810
26456
  }, [columnIdx, columnElement, focusIdx, propertyElement, border, updateElement]);
26811
- const handleBorderRadiusChange = (0, import_react91.useCallback)((value) => {
26457
+ const handleBorderRadiusChange = (0, import_react92.useCallback)((value) => {
26812
26458
  if (!columnIdx || !columnElement || !focusIdx || !propertyElement) return;
26813
26459
  const formattedRadius = formatBorderRadius(value);
26814
26460
  updateElement(columnIdx, {
@@ -26838,6 +26484,7 @@ function PropertyToolbar() {
26838
26484
  }
26839
26485
  ),
26840
26486
  /* @__PURE__ */ (0, import_jsx_runtime121.jsx)(ImageMenu, { type: "property" }),
26487
+ /* @__PURE__ */ (0, import_jsx_runtime121.jsx)(PropertyEditMenu, {}),
26841
26488
  /* @__PURE__ */ (0, import_jsx_runtime121.jsx)(ToolbarSeparator, {}),
26842
26489
  /* @__PURE__ */ (0, import_jsx_runtime121.jsx)(ToolbarContent, { children: /* @__PURE__ */ (0, import_jsx_runtime121.jsx)(
26843
26490
  FontFamilyDropdown,
@@ -26908,15 +26555,13 @@ function PropertyToolbar() {
26908
26555
  tooltipText: "Corner Rounding",
26909
26556
  max: 18
26910
26557
  }
26911
- ),
26912
- /* @__PURE__ */ (0, import_jsx_runtime121.jsx)(ToolbarSeparator, {}),
26913
- /* @__PURE__ */ (0, import_jsx_runtime121.jsx)(PropertyEditMenu, {})
26558
+ )
26914
26559
  ] })
26915
26560
  ] });
26916
26561
  }
26917
26562
 
26918
26563
  // src/core/editor/components/element-gear/property/triple/toolbar.tsx
26919
- var import_react93 = require("react");
26564
+ var import_react94 = require("react");
26920
26565
  init_sidebar_context();
26921
26566
  init_editor();
26922
26567
  init_idx();
@@ -26927,7 +26572,7 @@ init_button();
26927
26572
  var import_lucide_react73 = require("lucide-react");
26928
26573
  init_popover();
26929
26574
  init_tooltip();
26930
- var import_react92 = require("react");
26575
+ var import_react93 = require("react");
26931
26576
  init_input();
26932
26577
  init_editor();
26933
26578
  init_idx();
@@ -26935,105 +26580,51 @@ init_format();
26935
26580
  var import_jsx_runtime122 = require("react/jsx-runtime");
26936
26581
  var PropertyTripleEditMenu = () => {
26937
26582
  const { focusIdx, template, updateElement } = useEditorStore();
26938
- const [isOpen, setIsOpen] = (0, import_react92.useState)(false);
26939
- const [openSection, setOpenSection] = (0, import_react92.useState)(null);
26940
- const propertyElement = (0, import_react92.useMemo)(() => {
26583
+ const [isOpen, setIsOpen] = (0, import_react93.useState)(false);
26584
+ const [openSection, setOpenSection] = (0, import_react93.useState)(null);
26585
+ const propertyElement = (0, import_react93.useMemo)(() => {
26941
26586
  if (!focusIdx || !template) return null;
26942
26587
  return getValueByIdx(template, focusIdx);
26943
26588
  }, [focusIdx, template]);
26944
- const currentPrice = (0, import_react92.useMemo)(() => {
26589
+ const currentPrice = (0, import_react93.useMemo)(() => {
26945
26590
  const rawPrice = propertyElement?.attributes?.["price"] || "";
26946
26591
  return parsePrice(rawPrice);
26947
26592
  }, [propertyElement]);
26948
- const [priceInput, setPriceInput] = (0, import_react92.useState)(currentPrice);
26949
- (0, import_react92.useEffect)(() => {
26950
- setPriceInput(currentPrice);
26951
- }, [currentPrice]);
26952
- const handlePriceBlur = (0, import_react92.useCallback)(() => {
26953
- if (!focusIdx || !propertyElement) return;
26954
- if (priceInput === currentPrice) return;
26955
- updateElement(focusIdx, {
26956
- attributes: {
26957
- ...propertyElement.attributes,
26958
- "price": priceInput
26959
- }
26960
- });
26961
- }, [focusIdx, propertyElement, priceInput, currentPrice, updateElement]);
26962
- const currentBeds = (0, import_react92.useMemo)(() => propertyElement?.attributes?.["beds"] || "", [propertyElement]);
26963
- const currentBaths = (0, import_react92.useMemo)(() => propertyElement?.attributes?.["baths"] || "", [propertyElement]);
26964
- const currentSqft = (0, import_react92.useMemo)(() => propertyElement?.attributes?.["sqft"] || "", [propertyElement]);
26965
- const currentCity = (0, import_react92.useMemo)(() => propertyElement?.attributes?.["city"] || "", [propertyElement]);
26966
- const [bedsInput, setBedsInput] = (0, import_react92.useState)(currentBeds);
26967
- const [bathsInput, setBathsInput] = (0, import_react92.useState)(currentBaths);
26968
- const [sqftInput, setSqftInput] = (0, import_react92.useState)(currentSqft);
26969
- const [cityInput, setCityInput] = (0, import_react92.useState)(currentCity);
26970
- (0, import_react92.useEffect)(() => {
26971
- setBedsInput(currentBeds);
26972
- }, [currentBeds]);
26973
- (0, import_react92.useEffect)(() => {
26974
- setBathsInput(currentBaths);
26975
- }, [currentBaths]);
26976
- (0, import_react92.useEffect)(() => {
26977
- setSqftInput(currentSqft);
26978
- }, [currentSqft]);
26979
- (0, import_react92.useEffect)(() => {
26980
- setCityInput(currentCity);
26981
- }, [currentCity]);
26982
- const handleBedsBlur = (0, import_react92.useCallback)(() => {
26983
- if (!focusIdx || !propertyElement) return;
26984
- if (bedsInput === currentBeds) return;
26985
- updateElement(focusIdx, {
26986
- attributes: {
26987
- ...propertyElement.attributes,
26988
- "beds": bedsInput
26989
- }
26990
- });
26991
- }, [focusIdx, propertyElement, bedsInput, currentBeds, updateElement]);
26992
- const handleBathsBlur = (0, import_react92.useCallback)(() => {
26593
+ const currentBeds = (0, import_react93.useMemo)(() => propertyElement?.attributes?.["beds"] || "", [propertyElement]);
26594
+ const currentBaths = (0, import_react93.useMemo)(() => propertyElement?.attributes?.["baths"] || "", [propertyElement]);
26595
+ const currentSqft = (0, import_react93.useMemo)(() => propertyElement?.attributes?.["sqft"] || "", [propertyElement]);
26596
+ const currentCity = (0, import_react93.useMemo)(() => propertyElement?.attributes?.["city"] || "", [propertyElement]);
26597
+ const commitAttribute = (0, import_react93.useCallback)((key, value) => {
26993
26598
  if (!focusIdx || !propertyElement) return;
26994
- if (bathsInput === currentBaths) return;
26995
26599
  updateElement(focusIdx, {
26996
- attributes: {
26997
- ...propertyElement.attributes,
26998
- "baths": bathsInput
26999
- }
27000
- });
27001
- }, [focusIdx, propertyElement, bathsInput, currentBaths, updateElement]);
27002
- const handleSqftBlur = (0, import_react92.useCallback)(() => {
27003
- if (!focusIdx || !propertyElement) return;
27004
- if (sqftInput === currentSqft) return;
27005
- updateElement(focusIdx, {
27006
- attributes: {
27007
- ...propertyElement.attributes,
27008
- "sqft": sqftInput
27009
- }
27010
- });
27011
- }, [focusIdx, propertyElement, sqftInput, currentSqft, updateElement]);
27012
- const handleCityBlur = (0, import_react92.useCallback)(() => {
27013
- if (!focusIdx || !propertyElement) return;
27014
- if (cityInput === currentCity) return;
27015
- updateElement(focusIdx, {
27016
- attributes: {
27017
- ...propertyElement.attributes,
27018
- "city": cityInput
27019
- }
26600
+ attributes: { ...propertyElement.attributes, [key]: value }
27020
26601
  });
27021
- }, [focusIdx, propertyElement, cityInput, currentCity, updateElement]);
27022
- const handleToggle = (0, import_react92.useCallback)((section) => {
26602
+ }, [focusIdx, propertyElement, updateElement]);
26603
+ const commitPrice = (0, import_react93.useCallback)((v) => commitAttribute("price", v), [commitAttribute]);
26604
+ const commitBeds = (0, import_react93.useCallback)((v) => commitAttribute("beds", v), [commitAttribute]);
26605
+ const commitBaths = (0, import_react93.useCallback)((v) => commitAttribute("baths", v), [commitAttribute]);
26606
+ const commitSqft = (0, import_react93.useCallback)((v) => commitAttribute("sqft", v), [commitAttribute]);
26607
+ const commitCity = (0, import_react93.useCallback)((v) => commitAttribute("city", v), [commitAttribute]);
26608
+ const priceInput = useEditableValue({ externalValue: currentPrice, onChange: commitPrice });
26609
+ const bedsInput = useEditableValue({ externalValue: currentBeds, onChange: commitBeds });
26610
+ const bathsInput = useEditableValue({ externalValue: currentBaths, onChange: commitBaths });
26611
+ const sqftInput = useEditableValue({ externalValue: currentSqft, onChange: commitSqft });
26612
+ const cityInput = useEditableValue({ externalValue: currentCity, onChange: commitCity });
26613
+ const handleToggle = (0, import_react93.useCallback)((section) => {
27023
26614
  setOpenSection((prev) => prev === section ? null : section);
27024
26615
  }, []);
27025
- const handleTogglePrice = (0, import_react92.useCallback)(() => handleToggle("price"), [handleToggle]);
27026
- const handleToggleDetails = (0, import_react92.useCallback)(() => handleToggle("details"), [handleToggle]);
27027
- const handleToggleAddress = (0, import_react92.useCallback)(() => handleToggle("address"), [handleToggle]);
26616
+ const handleTogglePrice = (0, import_react93.useCallback)(() => handleToggle("price"), [handleToggle]);
26617
+ const handleToggleDetails = (0, import_react93.useCallback)(() => handleToggle("details"), [handleToggle]);
26618
+ const handleToggleAddress = (0, import_react93.useCallback)(() => handleToggle("address"), [handleToggle]);
27028
26619
  return /* @__PURE__ */ (0, import_jsx_runtime122.jsxs)(Tooltip, { children: [
27029
26620
  /* @__PURE__ */ (0, import_jsx_runtime122.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
27030
26621
  /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(
27031
26622
  Button,
27032
26623
  {
27033
- variant: "outline",
26624
+ variant: "ghost",
27034
26625
  className: "shadow-none transition-none cursor-pointer rounded-[12px]",
27035
26626
  size: "icon",
27036
- children: /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(import_lucide_react73.HouseIcon, { className: "w-4 h-4" })
26627
+ children: /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(import_lucide_react73.SquarePen, { className: "w-4 h-4" })
27037
26628
  }
27038
26629
  ) }) }),
27039
26630
  /* @__PURE__ */ (0, import_jsx_runtime122.jsxs)(PopoverContent, { className: "w-84 z-51 mt-1 rounded-[12px] p-2 gap-2 flex flex-col z-50001", children: [
@@ -27051,9 +26642,11 @@ var PropertyTripleEditMenu = () => {
27051
26642
  type: "number",
27052
26643
  placeholder: "Price",
27053
26644
  className: "w-full shadow-none rounded-[12px]",
27054
- value: priceInput,
27055
- onChange: (e) => setPriceInput(e.target.value),
27056
- onBlur: handlePriceBlur
26645
+ value: priceInput.displayValue,
26646
+ onChange: (e) => priceInput.setLocalValue(e.target.value),
26647
+ onFocus: priceInput.handleFocus,
26648
+ onBlur: priceInput.handleBlur,
26649
+ onKeyDown: priceInput.handleKeyDown
27057
26650
  }
27058
26651
  ) }) })
27059
26652
  ] }),
@@ -27072,9 +26665,11 @@ var PropertyTripleEditMenu = () => {
27072
26665
  type: "number",
27073
26666
  placeholder: "Bd",
27074
26667
  className: "w-1/3 shadow-none rounded-[12px]",
27075
- value: bedsInput,
27076
- onChange: (e) => setBedsInput(e.target.value),
27077
- onBlur: handleBedsBlur
26668
+ value: bedsInput.displayValue,
26669
+ onChange: (e) => bedsInput.setLocalValue(e.target.value),
26670
+ onFocus: bedsInput.handleFocus,
26671
+ onBlur: bedsInput.handleBlur,
26672
+ onKeyDown: bedsInput.handleKeyDown
27078
26673
  }
27079
26674
  ),
27080
26675
  /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(
@@ -27083,9 +26678,11 @@ var PropertyTripleEditMenu = () => {
27083
26678
  type: "number",
27084
26679
  placeholder: "Ba",
27085
26680
  className: "w-1/3 shadow-none rounded-[12px]",
27086
- value: bathsInput,
27087
- onChange: (e) => setBathsInput(e.target.value),
27088
- onBlur: handleBathsBlur
26681
+ value: bathsInput.displayValue,
26682
+ onChange: (e) => bathsInput.setLocalValue(e.target.value),
26683
+ onFocus: bathsInput.handleFocus,
26684
+ onBlur: bathsInput.handleBlur,
26685
+ onKeyDown: bathsInput.handleKeyDown
27089
26686
  }
27090
26687
  ),
27091
26688
  /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(
@@ -27094,9 +26691,11 @@ var PropertyTripleEditMenu = () => {
27094
26691
  type: "number",
27095
26692
  placeholder: "Sqft",
27096
26693
  className: "w-2/4 shadow-none rounded-[12px]",
27097
- value: sqftInput,
27098
- onChange: (e) => setSqftInput(e.target.value),
27099
- onBlur: handleSqftBlur
26694
+ value: sqftInput.displayValue,
26695
+ onChange: (e) => sqftInput.setLocalValue(e.target.value),
26696
+ onFocus: sqftInput.handleFocus,
26697
+ onBlur: sqftInput.handleBlur,
26698
+ onKeyDown: sqftInput.handleKeyDown
27100
26699
  }
27101
26700
  )
27102
26701
  ] }) })
@@ -27115,15 +26714,17 @@ var PropertyTripleEditMenu = () => {
27115
26714
  type: "text",
27116
26715
  placeholder: "Egg Harbor City",
27117
26716
  className: "w-full shadow-none rounded-[12px]",
27118
- value: cityInput,
27119
- onChange: (e) => setCityInput(e.target.value),
27120
- onBlur: handleCityBlur
26717
+ value: cityInput.displayValue,
26718
+ onChange: (e) => cityInput.setLocalValue(e.target.value),
26719
+ onFocus: cityInput.handleFocus,
26720
+ onBlur: cityInput.handleBlur,
26721
+ onKeyDown: cityInput.handleKeyDown
27121
26722
  }
27122
26723
  ) }) })
27123
26724
  ] })
27124
26725
  ] })
27125
26726
  ] }),
27126
- /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: "Edit" })
26727
+ /* @__PURE__ */ (0, import_jsx_runtime122.jsx)(TooltipContent, { side: "bottom", className: "z-50001", children: "Information" })
27127
26728
  ] });
27128
26729
  };
27129
26730
 
@@ -27137,47 +26738,47 @@ var PropertyTripleItemToolbar = () => {
27137
26738
  const template = useEditorStore((state) => state.template);
27138
26739
  const updateElement = useEditorStore((state) => state.updateElement);
27139
26740
  const { activeView, colorTarget, setActiveView, setColorType, setColorTarget } = useSidebarContext();
27140
- const parentIdx = (0, import_react93.useMemo)(() => {
26741
+ const parentIdx = (0, import_react94.useMemo)(() => {
27141
26742
  if (!focusIdx) return null;
27142
26743
  return getParentIdx(focusIdx);
27143
26744
  }, [focusIdx]);
27144
- const parentElement = (0, import_react93.useMemo)(() => {
26745
+ const parentElement = (0, import_react94.useMemo)(() => {
27145
26746
  if (!parentIdx || !template) return null;
27146
26747
  return getValueByIdx(template, parentIdx);
27147
26748
  }, [parentIdx, template]);
27148
- const currentBgColor = (0, import_react93.useMemo)(() => {
26749
+ const currentBgColor = (0, import_react94.useMemo)(() => {
27149
26750
  return parentElement?.attributes?.["background-color"] || "transparent";
27150
26751
  }, [parentElement]);
27151
- const border = (0, import_react93.useMemo)(() => {
26752
+ const border = (0, import_react94.useMemo)(() => {
27152
26753
  const rawBorder = parentElement?.attributes?.["border"];
27153
26754
  return parseBorder(rawBorder);
27154
26755
  }, [parentElement]);
27155
- const borderRadiusValue = (0, import_react93.useMemo)(() => {
26756
+ const borderRadiusValue = (0, import_react94.useMemo)(() => {
27156
26757
  const rawRadius = parentElement?.attributes?.["border-radius"];
27157
26758
  return parseBorderRadius(rawRadius);
27158
26759
  }, [parentElement]);
27159
- const currentTextColor = (0, import_react93.useMemo)(() => {
26760
+ const currentTextColor = (0, import_react94.useMemo)(() => {
27160
26761
  return parentElement?.attributes?.["text-color"] || "#111116";
27161
26762
  }, [parentElement]);
27162
- const currentFontFamily = (0, import_react93.useMemo)(() => {
26763
+ const currentFontFamily = (0, import_react94.useMemo)(() => {
27163
26764
  return parentElement?.attributes?.["font-family"] || "Arial, sans-serif";
27164
26765
  }, [parentElement]);
27165
- const handleOpenBgColorPicker = (0, import_react93.useCallback)(() => {
26766
+ const handleOpenBgColorPicker = (0, import_react94.useCallback)(() => {
27166
26767
  setColorType("Background Color");
27167
26768
  setColorTarget("propertyBgColor");
27168
26769
  setActiveView("color");
27169
26770
  }, [setColorType, setColorTarget, setActiveView]);
27170
- const handleOpenStrokeColorPicker = (0, import_react93.useCallback)(() => {
26771
+ const handleOpenStrokeColorPicker = (0, import_react94.useCallback)(() => {
27171
26772
  setColorType("Stroke Color");
27172
26773
  setColorTarget("propertyStrokeColor");
27173
26774
  setActiveView("color");
27174
26775
  }, [setColorType, setColorTarget, setActiveView]);
27175
- const handleOpenTextColorPicker = (0, import_react93.useCallback)(() => {
26776
+ const handleOpenTextColorPicker = (0, import_react94.useCallback)(() => {
27176
26777
  setColorType("Text Color");
27177
26778
  setColorTarget("propertyTextColor");
27178
26779
  setActiveView("color");
27179
26780
  }, [setColorType, setColorTarget, setActiveView]);
27180
- const handleFontChange = (0, import_react93.useCallback)((font) => {
26781
+ const handleFontChange = (0, import_react94.useCallback)((font) => {
27181
26782
  if (!parentIdx || !parentElement) return;
27182
26783
  updateElement(parentIdx, {
27183
26784
  attributes: {
@@ -27186,7 +26787,7 @@ var PropertyTripleItemToolbar = () => {
27186
26787
  }
27187
26788
  });
27188
26789
  }, [parentIdx, parentElement, updateElement]);
27189
- const handleBorderWidthChange = (0, import_react93.useCallback)((width) => {
26790
+ const handleBorderWidthChange = (0, import_react94.useCallback)((width) => {
27190
26791
  if (!parentIdx || !parentElement) return;
27191
26792
  const newBorder = { ...border, width };
27192
26793
  const formattedBorder = formatBorder(newBorder);
@@ -27197,7 +26798,7 @@ var PropertyTripleItemToolbar = () => {
27197
26798
  }
27198
26799
  });
27199
26800
  }, [parentIdx, parentElement, border, updateElement]);
27200
- const handleBorderEnabledChange = (0, import_react93.useCallback)((enabled) => {
26801
+ const handleBorderEnabledChange = (0, import_react94.useCallback)((enabled) => {
27201
26802
  if (!parentIdx || !parentElement) return;
27202
26803
  const newWidth = enabled ? border.width === 0 ? 1 : border.width : 0;
27203
26804
  const newBorder = { ...border, width: newWidth };
@@ -27209,7 +26810,7 @@ var PropertyTripleItemToolbar = () => {
27209
26810
  }
27210
26811
  });
27211
26812
  }, [parentIdx, parentElement, border, updateElement]);
27212
- const handleBorderRadiusChange = (0, import_react93.useCallback)((value) => {
26813
+ const handleBorderRadiusChange = (0, import_react94.useCallback)((value) => {
27213
26814
  if (!parentIdx || !parentElement) return;
27214
26815
  const formattedRadius = formatBorderRadius(value);
27215
26816
  updateElement(parentIdx, {
@@ -27233,6 +26834,7 @@ var PropertyTripleItemToolbar = () => {
27233
26834
  }
27234
26835
  ),
27235
26836
  /* @__PURE__ */ (0, import_jsx_runtime123.jsx)(ImageMenu, { type: "property" }),
26837
+ /* @__PURE__ */ (0, import_jsx_runtime123.jsx)(PropertyTripleEditMenu, {}),
27236
26838
  /* @__PURE__ */ (0, import_jsx_runtime123.jsx)(ToolbarSeparator, {}),
27237
26839
  /* @__PURE__ */ (0, import_jsx_runtime123.jsx)(
27238
26840
  FontFamilyDropdown,
@@ -27303,9 +26905,7 @@ var PropertyTripleItemToolbar = () => {
27303
26905
  tooltipText: "Corner Rounding",
27304
26906
  max: 18
27305
26907
  }
27306
- ),
27307
- /* @__PURE__ */ (0, import_jsx_runtime123.jsx)(ToolbarSeparator, {}),
27308
- /* @__PURE__ */ (0, import_jsx_runtime123.jsx)(PropertyTripleEditMenu, {})
26908
+ )
27309
26909
  ] })
27310
26910
  ] });
27311
26911
  };
@@ -27387,17 +26987,17 @@ function Skeleton({ className, ...props }) {
27387
26987
  }
27388
26988
 
27389
26989
  // src/core/editor/components/email-template-v2/template-page.tsx
27390
- var import_react95 = require("react");
26990
+ var import_react96 = require("react");
27391
26991
  init_sidebar_context();
27392
26992
  init_editor();
27393
26993
 
27394
26994
  // src/core/editor/hooks/use-auto-save.ts
27395
- var import_react94 = require("react");
26995
+ var import_react95 = require("react");
27396
26996
  init_editor();
27397
26997
  var AUTO_SAVE_INTERVAL = 30 * 1e3;
27398
26998
  function useAutoSave() {
27399
- const intervalRef = (0, import_react94.useRef)(null);
27400
- (0, import_react94.useEffect)(() => {
26999
+ const intervalRef = (0, import_react95.useRef)(null);
27000
+ (0, import_react95.useEffect)(() => {
27401
27001
  intervalRef.current = setInterval(async () => {
27402
27002
  const { template, templateId, onSave, hasUnsavedChanges, markAsSaved, isSaving, setIsSaving } = useEditorStore.getState();
27403
27003
  if (isSaving || !templateId || !onSave || !hasUnsavedChanges()) {
@@ -27426,7 +27026,7 @@ function useAutoSave() {
27426
27026
  init_utils();
27427
27027
  var import_dist = require("react-json-view-lite/dist/index.css");
27428
27028
  var import_jsx_runtime126 = require("react/jsx-runtime");
27429
- var Editor2 = (0, import_react95.lazy)(() => Promise.resolve().then(() => (init_core(), core_exports)).then((module2) => ({
27029
+ var Editor2 = (0, import_react96.lazy)(() => Promise.resolve().then(() => (init_core(), core_exports)).then((module2) => ({
27430
27030
  default: module2.Editor
27431
27031
  })));
27432
27032
  function TemplatePage({
@@ -27438,12 +27038,12 @@ function TemplatePage({
27438
27038
  onImageUpload,
27439
27039
  data
27440
27040
  }) {
27441
- (0, import_react95.useState)(() => {
27041
+ (0, import_react96.useState)(() => {
27442
27042
  useEditorStore.getState().initializeWithTemplate(templateId, initialTemplate, onSave, onToast, data, onExit, onImageUpload);
27443
27043
  });
27444
27044
  useAutoSave();
27445
- const [editorLoading, setEditorLoading] = (0, import_react95.useState)(false);
27446
- const [isPageHovered, setIsPageHovered] = (0, import_react95.useState)(false);
27045
+ const [editorLoading, setEditorLoading] = (0, import_react96.useState)(false);
27046
+ const [isPageHovered, setIsPageHovered] = (0, import_react96.useState)(false);
27447
27047
  const previewMode = useEditorStore((state) => state.previewMode);
27448
27048
  const focusIdx = useEditorStore((state) => state.focusIdx);
27449
27049
  const setFocusIdx = useEditorStore((state) => state.setFocusIdx);
@@ -27487,7 +27087,7 @@ function TemplatePage({
27487
27087
  onClick: handlePageClick,
27488
27088
  onMouseMove: handlePageMouseMove,
27489
27089
  onMouseLeave: handlePageMouseLeave,
27490
- children: /* @__PURE__ */ (0, import_jsx_runtime126.jsx)(import_react95.Suspense, { children: /* @__PURE__ */ (0, import_jsx_runtime126.jsx)(
27090
+ children: /* @__PURE__ */ (0, import_jsx_runtime126.jsx)(import_react96.Suspense, { children: /* @__PURE__ */ (0, import_jsx_runtime126.jsx)(
27491
27091
  Editor2,
27492
27092
  {
27493
27093
  setEditorLoading,