@kgalexander/mcreate 0.0.13 → 0.0.14

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
@@ -2017,7 +2017,7 @@ function setValueAtPath(template, path, value) {
2017
2017
  (0, import_set.default)(template, lodashPath, value);
2018
2018
  }
2019
2019
  }
2020
- var import_zustand, import_immer, import_middleware, import_get2, import_set, import_cloneDeep, import_immer2, SECTION_INDEX_REGEX, MAX_TEMPLATE_SIZE, defaultTemplate, MAX_PAID_LEVEL, useEditorStore;
2020
+ var import_zustand, import_immer, import_middleware, import_get2, import_set, import_cloneDeep, import_immer2, SECTION_INDEX_REGEX, MAX_TEMPLATE_SIZE, defaultTemplate, useEditorStore;
2021
2021
  var init_editor = __esm({
2022
2022
  "src/core/editor/state/editor.ts"() {
2023
2023
  "use strict";
@@ -2041,7 +2041,6 @@ var init_editor = __esm({
2041
2041
  id: page.id || generateId()
2042
2042
  }))
2043
2043
  };
2044
- MAX_PAID_LEVEL = 3;
2045
2044
  useEditorStore = (0, import_zustand.create)()(
2046
2045
  (0, import_middleware.devtools)(
2047
2046
  (0, import_immer.immer)((set) => ({
@@ -2050,6 +2049,7 @@ var init_editor = __esm({
2050
2049
  templateId: null,
2051
2050
  onSave: null,
2052
2051
  onToast: null,
2052
+ onExit: null,
2053
2053
  previewMode: false,
2054
2054
  focusIdx: null,
2055
2055
  hoverIdx: null,
@@ -2073,14 +2073,20 @@ var init_editor = __esm({
2073
2073
  isSaving: false,
2074
2074
  // Subscription level (0 = free, 1-3 = paid tiers)
2075
2075
  isPaidLevel: 0,
2076
+ // User data
2077
+ images: [],
2078
+ userData: null,
2076
2079
  // Initialize store with external template (for npm package usage)
2077
- initializeWithTemplate: (templateId, template, onSave, onToast, isPaidLevel) => {
2080
+ initializeWithTemplate: (templateId, template, onSave, onToast, data, onExit) => {
2078
2081
  set((state) => {
2079
2082
  state.templateId = templateId;
2080
2083
  state.template = template;
2081
2084
  state.onSave = onSave ?? null;
2082
2085
  state.onToast = onToast ?? null;
2083
- state.isPaidLevel = isPaidLevel ?? 0;
2086
+ state.onExit = onExit ?? null;
2087
+ state.isPaidLevel = data?.isPaidLevel ?? 0;
2088
+ state.images = data?.images ?? [];
2089
+ state.userData = data?.userData ?? null;
2084
2090
  state.templateSize = calculateTemplateSize(template);
2085
2091
  state.isAtSizeLimit = false;
2086
2092
  state.history = [(0, import_cloneDeep.default)(template)];
@@ -3196,7 +3202,7 @@ var init_editor = __esm({
3196
3202
  });
3197
3203
 
3198
3204
  // src/core/editor/constant/configuration.ts
3199
- var import_lucide_react, BUTTON_ALIGNMENTS, ALIGNMENT_ICONS, FONTS, TEXT_ALIGNMENT_ICONS, TEXT_TYPE_OPTIONS, DEFAULT_FONT_SIZE, MIN_FONT_SIZE, MAX_FONT_SIZE, FONT_SIZE_STEP, LINK_TYPES, detectLinkType, stripPrefix, normalizeWebsiteUrl, DEFAULT_LETTER_SPACING, MIN_LETTER_SPACING, MAX_LETTER_SPACING, LETTER_SPACING_STEP, DEFAULT_LINE_HEIGHT, MIN_LINE_HEIGHT, MAX_LINE_HEIGHT, LINE_HEIGHT_STEP, HIDDEN_SELECTION_VISUAL_ELEMENTS, NOT_DRAGGABLE_ELEMENTS, IMAGE_SELECTION_VALID_TYPES;
3205
+ var import_lucide_react, BUTTON_ALIGNMENTS, ALIGNMENT_ICONS, FONTS, TEXT_ALIGNMENT_ICONS, TEXT_TYPE_OPTIONS, DEFAULT_FONT_SIZE, MIN_FONT_SIZE, MAX_FONT_SIZE, FONT_SIZE_STEP, LINK_TYPES, LINK_PRESETS, detectLinkType, stripPrefix, normalizeWebsiteUrl, DEFAULT_LETTER_SPACING, MIN_LETTER_SPACING, MAX_LETTER_SPACING, LETTER_SPACING_STEP, DEFAULT_LINE_HEIGHT, MIN_LINE_HEIGHT, MAX_LINE_HEIGHT, LINE_HEIGHT_STEP, HIDDEN_SELECTION_VISUAL_ELEMENTS, NOT_DRAGGABLE_ELEMENTS, EDITOR_COLORS;
3200
3206
  var init_configuration = __esm({
3201
3207
  "src/core/editor/constant/configuration.ts"() {
3202
3208
  "use strict";
@@ -3258,6 +3264,17 @@ var init_configuration = __esm({
3258
3264
  prefix: "tel:"
3259
3265
  }
3260
3266
  ];
3267
+ LINK_PRESETS = {
3268
+ Phone: [
3269
+ { label: "Personal Phone", key: "personal_phone_number" },
3270
+ { label: "Office Phone", key: "office_phone_number" },
3271
+ { label: "Business Phone", key: "business_phone_number" }
3272
+ ],
3273
+ Website: [
3274
+ { label: "Team Website", key: "team_website" },
3275
+ { label: "Brokerage Website", key: "brokerage_website" }
3276
+ ]
3277
+ };
3261
3278
  detectLinkType = (href) => {
3262
3279
  if (href.startsWith("mailto:")) return LINK_TYPES[0];
3263
3280
  if (href.startsWith("tel:")) return LINK_TYPES[2];
@@ -3284,7 +3301,18 @@ var init_configuration = __esm({
3284
3301
  LINE_HEIGHT_STEP = 0.1;
3285
3302
  HIDDEN_SELECTION_VISUAL_ELEMENTS = ["text", "divider", "column"];
3286
3303
  NOT_DRAGGABLE_ELEMENTS = ["page", "social-item", "text", "property-card", "property-card-single-two", "property-card-triple", "property-card-triple-item"];
3287
- IMAGE_SELECTION_VALID_TYPES = ["section", "section-column", "image", "section-property-km", "section-property-single-two", "section-property-triple", "property-card", "property-card-single-two", "property-card-triple", "property-card-triple-item"];
3304
+ EDITOR_COLORS = {
3305
+ /** Purple — drag/drop state */
3306
+ drag: {
3307
+ solid: "rgb(59, 130, 246)",
3308
+ half: "rgba(59, 130, 246, 0.5)"
3309
+ },
3310
+ /** Blue — hover/selection state */
3311
+ hover: {
3312
+ solid: "rgb(59, 130, 246)",
3313
+ half: "rgba(59, 130, 246, 0.5)"
3314
+ }
3315
+ };
3288
3316
  }
3289
3317
  });
3290
3318
 
@@ -3311,32 +3339,32 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
3311
3339
 
3312
3340
  /* Hover state - uses CSS variable for dynamic color */
3313
3341
  .${EMAIL_BLOCK_CLASS_NAME}.is-hovered {
3314
- outline-color: var(--outline-color-hover, rgba(59, 130, 246, 0.5));
3342
+ outline-color: var(--outline-color-hover, ${EDITOR_COLORS.hover.half});
3315
3343
  }
3316
3344
 
3317
3345
  /* Selected state - uses CSS variable for dynamic color */
3318
3346
  .${EMAIL_BLOCK_CLASS_NAME}.is-selected {
3319
- outline-color: var(--outline-color, rgb(59, 130, 246));
3347
+ outline-color: var(--outline-color, ${EDITOR_COLORS.hover.solid});
3320
3348
  }
3321
3349
 
3322
3350
  /* Drop target state - highlight section being dropped into */
3323
3351
  .${EMAIL_BLOCK_CLASS_NAME}.is-drop-target {
3324
- outline-color: rgb(147, 51, 234) !important;
3352
+ outline-color: ${EDITOR_COLORS.drag.solid} !important;
3325
3353
  }
3326
3354
 
3327
3355
  /* Column selection in section-column - 50% opacity blue */
3328
3356
  .${EMAIL_BLOCK_CLASS_NAME}.is-column-selected {
3329
- outline-color: rgba(59, 130, 246, 0.5);
3357
+ outline-color: ${EDITOR_COLORS.hover.half};
3330
3358
  }
3331
3359
 
3332
3360
  /* Column hover when child element is hovered - 50% opacity blue */
3333
3361
  .${EMAIL_BLOCK_CLASS_NAME}.is-column-hover-parent {
3334
- outline-color: rgba(59, 130, 246, 0.5);
3362
+ outline-color: ${EDITOR_COLORS.hover.half};
3335
3363
  }
3336
3364
 
3337
3365
  /* Card selection in property-card-triple - 50% opacity blue */
3338
3366
  .${EMAIL_BLOCK_CLASS_NAME}.is-card-selected {
3339
- outline-color: rgba(59, 130, 246, 0.5);
3367
+ outline-color: ${EDITOR_COLORS.hover.half};
3340
3368
  }
3341
3369
 
3342
3370
  /* Hide selection visual for configured elements (unless drag button hovered) */
@@ -3356,12 +3384,12 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
3356
3384
  outline-color: transparent !important;
3357
3385
  }
3358
3386
  .node-type-button.is-selected > table {
3359
- outline: 2px solid var(--outline-color, rgb(59, 130, 246));
3387
+ outline: 2px solid var(--outline-color, ${EDITOR_COLORS.hover.solid});
3360
3388
  outline-offset: -2px;
3361
3389
  border-radius: 2px;
3362
3390
  }
3363
3391
  .node-type-button.is-hovered:not(.is-selected) > table {
3364
- outline: 2px solid var(--outline-color-hover, rgba(59, 130, 246, 0.5));
3392
+ outline: 2px solid var(--outline-color-hover, ${EDITOR_COLORS.hover.half});
3365
3393
  outline-offset: -2px;
3366
3394
  border-radius: 2px;
3367
3395
  }
@@ -3374,12 +3402,12 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
3374
3402
  outline-color: transparent !important;
3375
3403
  }
3376
3404
  .node-type-image.is-selected table td {
3377
- outline: 2px solid var(--outline-color, rgb(59, 130, 246));
3405
+ outline: 2px solid var(--outline-color, ${EDITOR_COLORS.hover.solid});
3378
3406
  outline-offset: -2px;
3379
3407
  border-radius: 2px;
3380
3408
  }
3381
3409
  .node-type-image.is-hovered:not(.is-selected) table td {
3382
- outline: 2px solid var(--outline-color-hover, rgba(59, 130, 246, 0.5));
3410
+ outline: 2px solid var(--outline-color-hover, ${EDITOR_COLORS.hover.half});
3383
3411
  outline-offset: -2px;
3384
3412
  border-radius: 2px;
3385
3413
  }
@@ -3397,7 +3425,7 @@ function getEditorStyles(isDragButtonHovered, textEditingIdx) {
3397
3425
  /* Drop indicator - uses CSS variable for dynamic color */
3398
3426
  .drop-indicator {
3399
3427
  position: absolute;
3400
- background-color: var(--outline-color, rgb(59, 130, 246));
3428
+ background-color: var(--outline-color, ${EDITOR_COLORS.hover.solid});
3401
3429
  pointer-events: none;
3402
3430
  z-index: 1000;
3403
3431
  }
@@ -3777,8 +3805,8 @@ var init_ShadowDomRenderer = __esm({
3777
3805
  contentWrapper.className = "shadow-content";
3778
3806
  contentWrapper.innerHTML = html;
3779
3807
  contentWrapper.style.setProperty("--company-footer-opacity", showCompanyFooter ? "1" : "0.25");
3780
- contentWrapper.style.setProperty("--outline-color", isDragging ? "rgb(147, 51, 234)" : "rgb(59, 130, 246)");
3781
- contentWrapper.style.setProperty("--outline-color-hover", isDragging ? "rgba(147, 51, 234, 0.5)" : "rgba(59, 130, 246, 0.5)");
3808
+ contentWrapper.style.setProperty("--outline-color", isDragging ? EDITOR_COLORS.drag.solid : EDITOR_COLORS.hover.solid);
3809
+ contentWrapper.style.setProperty("--outline-color-hover", isDragging ? EDITOR_COLORS.drag.half : EDITOR_COLORS.hover.half);
3782
3810
  const template = useEditorStore.getState().template;
3783
3811
  const linkColor2 = template?.content?.[0]?.data?.value?.linkColor || "#0000ff";
3784
3812
  contentWrapper.style.setProperty("--link-color", linkColor2);
@@ -3798,8 +3826,8 @@ var init_ShadowDomRenderer = __esm({
3798
3826
  if (!shadowRootRef.current) return;
3799
3827
  const contentWrapper = shadowRootRef.current.querySelector(".shadow-content");
3800
3828
  if (contentWrapper) {
3801
- contentWrapper.style.setProperty("--outline-color", isDragging ? "rgb(147, 51, 234)" : "rgb(59, 130, 246)");
3802
- contentWrapper.style.setProperty("--outline-color-hover", isDragging ? "rgba(147, 51, 234, 0.5)" : "rgba(59, 130, 246, 0.5)");
3829
+ contentWrapper.style.setProperty("--outline-color", isDragging ? EDITOR_COLORS.drag.solid : EDITOR_COLORS.hover.solid);
3830
+ contentWrapper.style.setProperty("--outline-color-hover", isDragging ? EDITOR_COLORS.drag.half : EDITOR_COLORS.hover.half);
3803
3831
  contentWrapper.style.setProperty("--company-footer-opacity", showCompanyFooter ? "1" : "0.25");
3804
3832
  const template = useEditorStore.getState().template;
3805
3833
  const linkColor2 = template?.content?.[0]?.data?.value?.linkColor || "#0000ff";
@@ -4259,11 +4287,11 @@ var init_ShadowDomRenderer = __esm({
4259
4287
  width: 3,
4260
4288
  height: dropIndicator.height
4261
4289
  },
4262
- backgroundColor: isDragging ? "rgb(147, 51, 234)" : "#3b82f6",
4290
+ backgroundColor: isDragging ? EDITOR_COLORS.drag.solid : EDITOR_COLORS.hover.solid,
4263
4291
  borderRadius: 2,
4264
4292
  pointerEvents: "none",
4265
4293
  zIndex: 9999,
4266
- boxShadow: isDragging ? "0 0 4px rgba(147, 51, 234, 0.5)" : "0 0 4px rgba(59, 130, 246, 0.5)"
4294
+ boxShadow: isDragging ? `0 0 4px ${EDITOR_COLORS.drag.half}` : `0 0 4px ${EDITOR_COLORS.hover.half}`
4267
4295
  },
4268
4296
  children: (dropIndicator.isNewSection || dropIndicator.isSplitSection) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4269
4297
  "div",
@@ -4273,7 +4301,7 @@ var init_ShadowDomRenderer = __esm({
4273
4301
  top: "50%",
4274
4302
  left: "50%",
4275
4303
  transform: "translate(-50%, -50%)",
4276
- backgroundColor: "rgb(147, 51, 234)",
4304
+ backgroundColor: EDITOR_COLORS.drag.solid,
4277
4305
  color: "white",
4278
4306
  fontSize: 12,
4279
4307
  fontWeight: 600,
@@ -12718,24 +12746,42 @@ var init_href_menu = __esm({
12718
12746
  init_label();
12719
12747
  init_separator();
12720
12748
  init_use_href();
12749
+ init_editor();
12721
12750
  init_helper();
12722
12751
  init_configuration();
12723
12752
  import_jsx_runtime25 = require("react/jsx-runtime");
12724
12753
  HrefMenu = () => {
12725
12754
  const { href, setHref, clearHref, copyHref, hasHref } = useHref();
12755
+ const userData = useEditorStore((s) => s.userData);
12726
12756
  const [isOpen, setIsOpen] = (0, import_react12.useState)(false);
12727
12757
  const [inputValue, setInputValue] = (0, import_react12.useState)("");
12728
12758
  const [showCopied, setShowCopied] = (0, import_react12.useState)(false);
12729
12759
  const [linkType, setLinkType] = (0, import_react12.useState)(LINK_TYPES[1]);
12730
12760
  const [isLinkTypeOpen, setIsLinkTypeOpen] = (0, import_react12.useState)(false);
12761
+ const [isPresetOpen, setIsPresetOpen] = (0, import_react12.useState)(false);
12762
+ console.log("userData", userData);
12763
+ const availablePresets = (0, import_react12.useMemo)(() => {
12764
+ const presetDefs = LINK_PRESETS[linkType.name] ?? [];
12765
+ if (!userData) return [];
12766
+ const all = presetDefs.filter((p) => userData[p.key]).map((p) => ({ ...p, value: String(userData[p.key]) }));
12767
+ if (!inputValue) return all;
12768
+ const query = inputValue.toLowerCase();
12769
+ return all.filter((p) => p.value.toLowerCase().includes(query));
12770
+ }, [linkType.name, userData, inputValue]);
12771
+ const handlePresetSelect = (0, import_react12.useCallback)((value) => {
12772
+ setInputValue(value);
12773
+ setIsPresetOpen(false);
12774
+ }, []);
12731
12775
  (0, import_react12.useEffect)(() => {
12732
12776
  if (isOpen) {
12733
12777
  setLinkType(detectLinkType(href));
12734
12778
  setInputValue(stripPrefix(href));
12779
+ setIsPresetOpen(true);
12735
12780
  }
12736
12781
  }, [isOpen, href]);
12737
12782
  const handleInputChange = (e) => {
12738
12783
  setInputValue(e.target.value);
12784
+ setIsPresetOpen(true);
12739
12785
  };
12740
12786
  const buildHref = (value) => {
12741
12787
  if (!value) return "";
@@ -12745,15 +12791,22 @@ var init_href_menu = __esm({
12745
12791
  if (value.startsWith(linkType.prefix)) return value;
12746
12792
  return linkType.prefix + value;
12747
12793
  };
12794
+ const handleInputClick = () => {
12795
+ if (availablePresets.length > 0) {
12796
+ setIsPresetOpen(true);
12797
+ }
12798
+ };
12748
12799
  const handleInputBlur = () => {
12749
12800
  setHref(buildHref(inputValue));
12750
12801
  };
12751
12802
  const handleKeyDown = (e) => {
12752
12803
  if (e.key === "Enter") {
12753
12804
  setHref(buildHref(inputValue));
12805
+ setIsPresetOpen(false);
12754
12806
  setIsOpen(false);
12755
12807
  }
12756
12808
  if (e.key === "Escape") {
12809
+ setIsPresetOpen(false);
12757
12810
  setIsOpen(false);
12758
12811
  }
12759
12812
  };
@@ -12796,55 +12849,85 @@ var init_href_menu = __esm({
12796
12849
  /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuContent, { side: "bottom", className: "w-[250px] p-3 shadow-lg z-50001", children: [
12797
12850
  /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2", children: [
12798
12851
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Label, { children: "Enter a link" }),
12799
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "relative", children: [
12800
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
12801
- Input,
12802
- {
12803
- type: linkType.inputType,
12804
- placeholder: linkType.placeholder,
12805
- className: "w-full rounded-[12px] shadow-none pl-12 h-[44px]",
12806
- value: inputValue,
12807
- onChange: handleInputChange,
12808
- onBlur: handleInputBlur,
12809
- onKeyDown: handleKeyDown,
12810
- autoFocus: true
12811
- }
12812
- ),
12813
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Popover, { open: isLinkTypeOpen, onOpenChange: setIsLinkTypeOpen, children: [
12814
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
12815
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { size: "icon", variant: "ghost", className: "absolute shadow-none rounded-[12px] left-1.5 top-1/2 -translate-y-1/2 h-[34px] w-[34px] cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(linkType.icon, {}) }) }) }),
12816
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { side: "top", className: "z-50001", children: "Link Type" })
12817
- ] }),
12852
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Popover, { open: isPresetOpen && availablePresets.length > 0, onOpenChange: setIsPresetOpen, children: [
12853
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "relative", children: [
12818
12854
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
12819
- PopoverContent,
12855
+ Input,
12820
12856
  {
12821
- side: "bottom",
12822
- align: "start",
12823
- className: "w-[160px] p-1 z-50001",
12824
- onPointerDownOutside: (e) => e.preventDefault(),
12825
- children: LINK_TYPES.map((type) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
12826
- Button,
12827
- {
12828
- variant: "ghost",
12829
- className: "w-full justify-between shadow-none cursor-pointer",
12830
- onClick: (e) => {
12831
- e.stopPropagation();
12832
- setLinkType(type);
12833
- setIsLinkTypeOpen(false);
12857
+ type: linkType.inputType,
12858
+ placeholder: linkType.placeholder,
12859
+ className: "w-full rounded-[12px] shadow-none pl-12 h-[44px]",
12860
+ value: inputValue,
12861
+ onChange: handleInputChange,
12862
+ onClick: handleInputClick,
12863
+ onBlur: handleInputBlur,
12864
+ onKeyDown: handleKeyDown,
12865
+ autoFocus: true
12866
+ }
12867
+ ),
12868
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Popover, { open: isLinkTypeOpen, onOpenChange: setIsLinkTypeOpen, children: [
12869
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
12870
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { size: "icon", variant: "ghost", className: "absolute shadow-none rounded-[12px] left-1.5 top-1/2 -translate-y-1/2 h-[34px] w-[34px] cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(linkType.icon, {}) }) }) }),
12871
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { side: "top", className: "z-50001", children: "Link Type" })
12872
+ ] }),
12873
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
12874
+ PopoverContent,
12875
+ {
12876
+ side: "bottom",
12877
+ align: "start",
12878
+ className: "w-[160px] p-1 z-50001",
12879
+ onPointerDownOutside: (e) => e.preventDefault(),
12880
+ children: LINK_TYPES.map((type) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
12881
+ Button,
12882
+ {
12883
+ variant: "ghost",
12884
+ className: "w-full justify-between shadow-none cursor-pointer",
12885
+ onClick: (e) => {
12886
+ e.stopPropagation();
12887
+ setLinkType(type);
12888
+ setIsLinkTypeOpen(false);
12889
+ },
12890
+ children: [
12891
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex items-center gap-2", children: [
12892
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(type.icon, { className: "size-4" }),
12893
+ type.name
12894
+ ] }),
12895
+ linkType.name === type.name && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react18.CheckIcon, { className: "size-4" })
12896
+ ]
12834
12897
  },
12835
- children: [
12836
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex items-center gap-2", children: [
12837
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(type.icon, { className: "size-4" }),
12838
- type.name
12839
- ] }),
12840
- linkType.name === type.name && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react18.CheckIcon, { className: "size-4" })
12841
- ]
12898
+ type.name
12899
+ ))
12900
+ }
12901
+ )
12902
+ ] })
12903
+ ] }) }),
12904
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
12905
+ PopoverContent,
12906
+ {
12907
+ side: "bottom",
12908
+ align: "start",
12909
+ className: "w-[var(--radix-popover-trigger-width)] p-0 overflow-hidden z-50001",
12910
+ onOpenAutoFocus: (e) => e.preventDefault(),
12911
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex flex-col max-h-[200px] overflow-y-auto", children: availablePresets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
12912
+ "button",
12913
+ {
12914
+ className: `flex items-center justify-between px-3 py-2 text-sm hover:bg-accent cursor-pointer ${inputValue === preset.value ? "bg-accent font-medium" : ""}`,
12915
+ onMouseDown: (e) => {
12916
+ e.preventDefault();
12917
+ handlePresetSelect(preset.value);
12842
12918
  },
12843
- type.name
12844
- ))
12845
- }
12846
- )
12847
- ] })
12919
+ children: [
12920
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col items-start gap-0.5", children: [
12921
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-xs text-muted-foreground", children: preset.label }),
12922
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-sm", children: preset.value })
12923
+ ] }),
12924
+ inputValue === preset.value && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react18.CheckIcon, { className: "w-4 h-4 shrink-0" })
12925
+ ]
12926
+ },
12927
+ preset.key
12928
+ )) })
12929
+ }
12930
+ )
12848
12931
  ] })
12849
12932
  ] }),
12850
12933
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Separator, { className: "my-2" }),
@@ -16223,15 +16306,23 @@ function TemplateNameDialog() {
16223
16306
  init_editor();
16224
16307
  init_core();
16225
16308
  var import_jsx_runtime55 = require("react/jsx-runtime");
16226
- function TemplateHeader({ template }) {
16227
- const { templateId, onSave, markAsSaved, isSaving, setIsSaving } = useEditorStore();
16309
+ function TemplateHeader() {
16310
+ const templateId = useEditorStore((s) => s.templateId);
16311
+ const onSave = useEditorStore((s) => s.onSave);
16312
+ const markAsSaved = useEditorStore((s) => s.markAsSaved);
16313
+ const isSaving = useEditorStore((s) => s.isSaving);
16314
+ const setIsSaving = useEditorStore((s) => s.setIsSaving);
16315
+ const onExit = useEditorStore((s) => s.onExit);
16316
+ const templateName = useEditorStore((s) => s.template?.name);
16228
16317
  const handleExit = async () => {
16229
16318
  console.log("handleExit - templateId:", templateId);
16230
16319
  if (isSaving || !templateId || !onSave) return;
16231
16320
  setIsSaving(true);
16232
16321
  try {
16233
- await onSave(templateId, template);
16322
+ await onSave(templateId, useEditorStore.getState().template);
16234
16323
  markAsSaved();
16324
+ onExit?.();
16325
+ console.log("handleExit - onExit called");
16235
16326
  } catch (error) {
16236
16327
  console.error("Failed to save:", error);
16237
16328
  } finally {
@@ -16248,7 +16339,7 @@ function TemplateHeader({ template }) {
16248
16339
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TemplateSizeIndicator, {})
16249
16340
  ] }),
16250
16341
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex flex-row gap-2 items-center", children: [
16251
- template?.name || "Loading...",
16342
+ templateName || "Loading...",
16252
16343
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TemplateNameDialog, {})
16253
16344
  ] }),
16254
16345
  /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex flex-row gap-1 items-center", children: [
@@ -16876,6 +16967,7 @@ function useTemplateColors() {
16876
16967
  }
16877
16968
 
16878
16969
  // src/core/editor/components/email-template-v2/sidebar/view/color-selection.tsx
16970
+ init_editor();
16879
16971
  init_label();
16880
16972
  init_popover();
16881
16973
 
@@ -17407,7 +17499,7 @@ var rgbaArrayToHex = (rgba) => {
17407
17499
  const [r, g, b] = rgba.map((v) => Math.round(v));
17408
17500
  return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()}`;
17409
17501
  };
17410
- var ColorButton = ({ color, onColorSelect, currentColor }) => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(Tooltip, { children: [
17502
+ var ColorButton = ({ colorName, color, onColorSelect, currentColor }) => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(Tooltip, { children: [
17411
17503
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
17412
17504
  "button",
17413
17505
  {
@@ -17416,11 +17508,13 @@ var ColorButton = ({ color, onColorSelect, currentColor }) => /* @__PURE__ */ (0
17416
17508
  className: `aspect-square rounded-full cursor-pointer border hover:border-gray-500 ${isColorSelected(color, currentColor) ? "border-2 border-blue-500" : "border-accent"}`
17417
17509
  }
17418
17510
  ) }),
17419
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(TooltipContent, { children: color })
17511
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(TooltipContent, { children: colorName || color })
17420
17512
  ] });
17421
17513
  function ColorSelection({ setActiveView, lastView, onColorSelect, colorType = "Color", colorTarget, focusIdx, currentColor }) {
17422
17514
  const templateColors = useTemplateColors();
17423
17515
  const lastPickedColorRef = (0, import_react44.useRef)(null);
17516
+ const userData = useEditorStore((s) => s.userData);
17517
+ const colorPalettes = userData?.brand_kits?.[0]?.color_palettes ?? [];
17424
17518
  const [colorWheelOpen, setColorWheelOpen] = (0, import_react44.useState)(false);
17425
17519
  const handleColorPickerChange = (0, import_react44.useCallback)((rgba) => {
17426
17520
  const hex = rgbaArrayToHex(rgba);
@@ -17474,7 +17568,7 @@ function ColorSelection({ setActiveView, lastView, onColorSelect, colorType = "C
17474
17568
  templateColors.map((color) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ColorButton, { color, onColorSelect, currentColor }, color))
17475
17569
  ] }) })
17476
17570
  ] }),
17477
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "w-full mb-4", children: [
17571
+ colorPalettes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "w-full mb-4", children: [
17478
17572
  /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "flex flex-row items-center justify-between w-full mb-1", children: [
17479
17573
  /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "flex flex-row items-center gap-2 h-[44px]", children: [
17480
17574
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(import_lucide_react43.Hexagon, { className: "w-4 h-4 text-muted-foreground" }),
@@ -17482,16 +17576,10 @@ function ColorSelection({ setActiveView, lastView, onColorSelect, colorType = "C
17482
17576
  ] }),
17483
17577
  /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(Button, { variant: "link", className: "text-sm pr-0 cursor-pointer", children: "Edit" })
17484
17578
  ] }),
17485
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "w-full flex flex-col gap-4", children: [
17486
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "flex flex-col gap-2", children: [
17487
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(Label, { className: "text-xs font-medium text-muted-foreground", children: "Color palette 1" }),
17488
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full grid grid-cols-7 gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ColorButton, { color: "#FFFFFF", onColorSelect, currentColor }) })
17489
- ] }),
17490
- /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "flex flex-col gap-2", children: [
17491
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(Label, { className: "text-xs font-medium text-muted-foreground", children: "Color palette 2" }),
17492
- /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full grid grid-cols-7 gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ColorButton, { color: "#E97575", onColorSelect, currentColor }) })
17493
- ] })
17494
- ] })
17579
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full flex flex-col gap-4", children: colorPalettes.map((palette) => /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "flex flex-col gap-2", children: [
17580
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(Label, { className: "text-xs font-medium text-muted-foreground", children: palette.name }),
17581
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: "w-full grid grid-cols-7 gap-2", children: palette.colors.map((c) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ColorButton, { colorName: c.name, color: c.hex, onColorSelect, currentColor }, c.color_id)) })
17582
+ ] }, palette.palette_id)) })
17495
17583
  ] }),
17496
17584
  /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "w-full", children: [
17497
17585
  /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "flex flex-row items-center justify-between w-full mb-1", children: [
@@ -17583,6 +17671,7 @@ var IMAGES_MOCK_DATA = [
17583
17671
  ];
17584
17672
  var ImageSelection = ({ setActiveView, lastView, onImageSelect, focusIdx }) => {
17585
17673
  const template = useEditorStore((state) => state.template);
17674
+ const images = useEditorStore((state) => state.images);
17586
17675
  const currentImageUrl = (0, import_react45.useMemo)(() => {
17587
17676
  if (!focusIdx || !template) return null;
17588
17677
  const path = focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
@@ -17597,16 +17686,28 @@ var ImageSelection = ({ setActiveView, lastView, onImageSelect, focusIdx }) => {
17597
17686
  ] }) }),
17598
17687
  /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "w-full", children: [
17599
17688
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "flex flex-row items-center justify-between w-full mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "text-sm font-medium", children: "Images" }) }),
17600
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "w-full grid grid-cols-3 gap-3", children: IMAGES_MOCK_DATA.map((image2, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
17601
- Button,
17602
- {
17603
- variant: "outline",
17604
- className: `aspect-square h-full w-full cursor-pointer shadow-none transition-none rounded-[12px] p-0 ${currentImageUrl === image2.src ? "ring-2 ring-blue-500 ring-offset-2" : ""}`,
17605
- onClick: () => onImageSelect?.(image2.src),
17606
- children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("img", { src: image2.src, alt: image2.alt, className: "w-full h-full object-cover rounded-[12px]" })
17607
- },
17608
- index
17609
- )) })
17689
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "w-full grid grid-cols-3 gap-3", children: [
17690
+ IMAGES_MOCK_DATA.map((image2, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
17691
+ Button,
17692
+ {
17693
+ variant: "outline",
17694
+ className: `aspect-square h-full w-full cursor-pointer shadow-none transition-none rounded-[12px] p-0 ${currentImageUrl === image2.src ? "ring-2 ring-blue-500 ring-offset-2" : ""}`,
17695
+ onClick: () => onImageSelect?.(image2.src),
17696
+ children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("img", { src: image2.src, alt: image2.alt, className: "w-full h-full object-cover rounded-[12px]" })
17697
+ },
17698
+ index
17699
+ )),
17700
+ images.map((image2, index) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
17701
+ Button,
17702
+ {
17703
+ variant: "outline",
17704
+ className: `aspect-square h-full w-full cursor-pointer shadow-none transition-none rounded-[12px] p-0 ${currentImageUrl === image2.public_url ? "ring-2 ring-blue-500 ring-offset-2" : ""}`,
17705
+ onClick: () => onImageSelect?.(image2.public_url),
17706
+ children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("img", { src: image2.public_url, alt: image2.original_name, className: "w-full h-full object-cover rounded-[12px]" })
17707
+ },
17708
+ index
17709
+ ))
17710
+ ] })
17610
17711
  ] })
17611
17712
  ] });
17612
17713
  };
@@ -17853,7 +17954,6 @@ var SelectSocial = ({ value, onChange }) => {
17853
17954
  };
17854
17955
 
17855
17956
  // src/core/editor/components/email-template-v2/sidebar/sidebar.tsx
17856
- init_configuration();
17857
17957
  var import_jsx_runtime75 = require("react/jsx-runtime");
17858
17958
  var normalizeElementType = (type) => {
17859
17959
  if (type === "section" || type === "section-column") return "section";
@@ -17866,11 +17966,24 @@ var toTemplatePath = (focusIdx) => {
17866
17966
  return focusIdx.startsWith("content.") ? focusIdx.replace("content.", "content[0].").replace(/\.\[(\d+)\]/g, "[$1]") : focusIdx;
17867
17967
  };
17868
17968
  function TemplateSidebar({ editorLoading }) {
17869
- const { activeView, setActiveView, lastView, colorType, colorTarget, imageTarget } = useSidebarContext();
17969
+ const { activeView, setActiveView, lastView, colorType, colorTarget, imageTarget, setImageTarget } = useSidebarContext();
17870
17970
  const focusIdx = useEditorStore((state) => state.focusIdx);
17871
- const template = useEditorStore((state) => state.template);
17872
17971
  const tiptapEditor = useEditorStore((state) => state.tiptapEditor);
17972
+ const focusedElementAttrs = useEditorStore(
17973
+ (s) => s.focusIdx ? (0, import_lodash8.get)(s.template, toTemplatePath(s.focusIdx))?.attributes : null
17974
+ );
17975
+ const focusedElementType = useEditorStore(
17976
+ (s) => s.focusIdx ? (0, import_lodash8.get)(s.template, toTemplatePath(s.focusIdx))?.type : null
17977
+ );
17978
+ const parentElementAttrs = useEditorStore((s) => {
17979
+ if (!s.focusIdx) return null;
17980
+ const parentIdx = getParentIdx(s.focusIdx);
17981
+ return parentIdx ? (0, import_lodash8.get)(s.template, toTemplatePath(parentIdx))?.attributes : null;
17982
+ });
17983
+ const pageBgColor = useEditorStore((s) => s.template?.content?.[0]?.attributes?.["background-color"]);
17984
+ const linkColor = useEditorStore((s) => s.template?.content?.[0]?.data?.value?.linkColor);
17873
17985
  const previousElementTypeRef = (0, import_react47.useRef)(void 0);
17986
+ const previousFocusIdxRef = (0, import_react47.useRef)(null);
17874
17987
  const [openSidebar, setOpenSidebar] = (0, import_react47.useState)(true);
17875
17988
  const [updateCounter, forceUpdate] = (0, import_react47.useState)(0);
17876
17989
  (0, import_react47.useEffect)(() => {
@@ -17891,97 +18004,71 @@ function TemplateSidebar({ editorLoading }) {
17891
18004
  if (colorTarget === "highlightColor" && tiptapEditor) {
17892
18005
  return tiptapEditor.getAttributes("textStyle").backgroundColor || null;
17893
18006
  }
17894
- if (!focusIdx || !template) return null;
17895
- const path = toTemplatePath(focusIdx);
17896
- const element = (0, import_lodash8.get)(template, path);
17897
- if (!element) return null;
18007
+ if (!focusIdx || !focusedElementAttrs) return null;
17898
18008
  switch (colorTarget) {
17899
18009
  case "sectionBgColor":
17900
18010
  case "buttonBgColor":
17901
- return element.attributes?.["background-color"] || null;
18011
+ return focusedElementAttrs["background-color"] || null;
17902
18012
  case "buttonTextColor":
17903
18013
  case "socialTextColor":
17904
18014
  case "socialItemTextColor":
17905
- return element.attributes?.["color"] || null;
18015
+ return focusedElementAttrs["color"] || null;
17906
18016
  case "strokeColor":
17907
18017
  case "buttonStrokeColor": {
17908
- const parsed = parseBorder(element.attributes?.border);
18018
+ const parsed = parseBorder(focusedElementAttrs.border);
17909
18019
  return parsed.color || null;
17910
18020
  }
17911
18021
  case "spacerBgColor":
17912
18022
  case "dividerBgColor":
17913
18023
  case "imageBgColor":
17914
18024
  case "socialBgColor":
17915
- return element.attributes?.["container-background-color"] || null;
18025
+ return focusedElementAttrs["container-background-color"] || null;
17916
18026
  case "dividerBorderColor":
17917
- return element.attributes?.["border-color"] || null;
17918
- case "columnBgColor": {
17919
- const columnIdx = getParentIdx(focusIdx);
17920
- if (!columnIdx) return null;
17921
- const column = (0, import_lodash8.get)(template, toTemplatePath(columnIdx));
17922
- return column?.attributes?.["background-color"] || null;
17923
- }
17924
- case "columnStrokeColor": {
17925
- const columnIdx = getParentIdx(focusIdx);
17926
- if (!columnIdx) return null;
17927
- const column = (0, import_lodash8.get)(template, toTemplatePath(columnIdx));
17928
- const parsed = parseBorder(column?.attributes?.border);
17929
- return parsed.color || null;
17930
- }
17931
- case "propertyBgColor": {
17932
- const columnIdx = getParentIdx(focusIdx);
17933
- if (!columnIdx) return null;
17934
- const column = (0, import_lodash8.get)(template, toTemplatePath(columnIdx));
17935
- return column?.attributes?.["background-color"] || null;
17936
- }
18027
+ return focusedElementAttrs["border-color"] || null;
18028
+ case "columnBgColor":
18029
+ case "propertyBgColor":
18030
+ return parentElementAttrs?.["background-color"] || null;
18031
+ case "columnStrokeColor":
17937
18032
  case "propertyStrokeColor": {
17938
- const columnIdx = getParentIdx(focusIdx);
17939
- if (!columnIdx) return null;
17940
- const column = (0, import_lodash8.get)(template, toTemplatePath(columnIdx));
17941
- const parsed = parseBorder(column?.attributes?.border);
18033
+ const parsed = parseBorder(parentElementAttrs?.border);
17942
18034
  return parsed.color || null;
17943
18035
  }
17944
18036
  case "propertyTextColor": {
17945
- const element2 = (0, import_lodash8.get)(template, toTemplatePath(focusIdx));
17946
- if (element2?.type === "property-card-triple-item") {
17947
- const parentIdx = getParentIdx(focusIdx);
17948
- if (!parentIdx) return "#111116";
17949
- const parent = (0, import_lodash8.get)(template, toTemplatePath(parentIdx));
17950
- return parent?.attributes?.["text-color"] || "#111116";
18037
+ if (focusedElementType === "property-card-triple-item") {
18038
+ return parentElementAttrs?.["text-color"] || "#111116";
17951
18039
  }
17952
- return element2?.attributes?.["text-color"] || "#111116";
17953
- }
17954
- case "statusColor": {
17955
- const property = (0, import_lodash8.get)(template, toTemplatePath(focusIdx));
17956
- return property?.attributes?.["status-color"] || "#B8B8B8";
18040
+ return focusedElementAttrs["text-color"] || "#111116";
17957
18041
  }
18042
+ case "statusColor":
18043
+ return focusedElementAttrs["status-color"] || "#B8B8B8";
17958
18044
  case "pageBgColor":
17959
- return template?.content?.[0]?.attributes?.["background-color"] || null;
18045
+ return pageBgColor || null;
17960
18046
  case "linkColor":
17961
- return template?.content?.[0]?.data?.value?.linkColor || "#0000ff";
18047
+ return linkColor || "#0000ff";
17962
18048
  default:
17963
18049
  return null;
17964
18050
  }
17965
- }, [colorTarget, focusIdx, template, tiptapEditor, updateCounter]);
18051
+ }, [colorTarget, focusIdx, focusedElementAttrs, parentElementAttrs, focusedElementType, pageBgColor, linkColor, tiptapEditor, updateCounter]);
17966
18052
  (0, import_react47.useEffect)(() => {
17967
- if (!focusIdx || !template) {
18053
+ if (!focusIdx || !focusedElementType) {
17968
18054
  previousElementTypeRef.current = void 0;
17969
18055
  return;
17970
18056
  }
17971
- const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx));
17972
- const currentType = normalizeElementType(element?.type);
18057
+ const currentType = normalizeElementType(focusedElementType);
17973
18058
  const previousType = previousElementTypeRef.current;
17974
18059
  if (previousType && currentType !== previousType && activeView === "color") {
17975
18060
  setActiveView(lastView);
17976
18061
  }
17977
- if (activeView === "images" && currentType && !IMAGE_SELECTION_VALID_TYPES.includes(currentType)) {
18062
+ if (activeView === "images" && previousFocusIdxRef.current !== null && previousFocusIdxRef.current !== focusIdx) {
17978
18063
  setActiveView(lastView);
18064
+ setImageTarget(null);
17979
18065
  }
17980
18066
  if (activeView === "add-social" && currentType && !ADD_SOCIAL_VALID_TYPES.includes(currentType)) {
17981
18067
  setActiveView(lastView);
17982
18068
  }
17983
18069
  previousElementTypeRef.current = currentType;
17984
- }, [focusIdx, template, activeView, lastView, setActiveView]);
18070
+ previousFocusIdxRef.current = focusIdx ?? null;
18071
+ }, [focusIdx, focusedElementType, activeView, lastView, setActiveView, setImageTarget]);
17985
18072
  const handleColorSelect = (0, import_react47.useCallback)((color) => {
17986
18073
  const tiptapEditor2 = useEditorStore.getState().tiptapEditor;
17987
18074
  if (colorTarget === "textColor" && tiptapEditor2) {
@@ -17995,9 +18082,9 @@ function TemplateSidebar({ editorLoading }) {
17995
18082
  }
17996
18083
  window.dispatchEvent(new CustomEvent("toolbar-refresh"));
17997
18084
  } else if (colorTarget === "sectionBgColor") {
17998
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
17999
- if (focusIdx2 && template2) {
18000
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18085
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18086
+ if (focusIdx2 && template) {
18087
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18001
18088
  if (element) {
18002
18089
  updateElement(focusIdx2, {
18003
18090
  attributes: { ...element.attributes, "background-color": color }
@@ -18005,9 +18092,9 @@ function TemplateSidebar({ editorLoading }) {
18005
18092
  }
18006
18093
  }
18007
18094
  } else if (colorTarget === "buttonBgColor") {
18008
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18009
- if (focusIdx2 && template2) {
18010
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18095
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18096
+ if (focusIdx2 && template) {
18097
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18011
18098
  if (element) {
18012
18099
  updateElement(focusIdx2, {
18013
18100
  attributes: { ...element.attributes, "background-color": color }
@@ -18015,9 +18102,9 @@ function TemplateSidebar({ editorLoading }) {
18015
18102
  }
18016
18103
  }
18017
18104
  } else if (colorTarget === "buttonStrokeColor") {
18018
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18019
- if (focusIdx2 && template2) {
18020
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18105
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18106
+ if (focusIdx2 && template) {
18107
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18021
18108
  if (element) {
18022
18109
  const parsed = parseBorder(element.attributes?.border);
18023
18110
  const newBorder = formatBorder({
@@ -18031,9 +18118,9 @@ function TemplateSidebar({ editorLoading }) {
18031
18118
  }
18032
18119
  }
18033
18120
  } else if (colorTarget === "buttonTextColor") {
18034
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18035
- if (focusIdx2 && template2) {
18036
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18121
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18122
+ if (focusIdx2 && template) {
18123
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18037
18124
  if (element) {
18038
18125
  updateElement(focusIdx2, {
18039
18126
  attributes: { ...element.attributes, "color": color }
@@ -18041,10 +18128,10 @@ function TemplateSidebar({ editorLoading }) {
18041
18128
  }
18042
18129
  }
18043
18130
  } else if (colorTarget === "strokeColor") {
18044
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18131
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18045
18132
  if (focusIdx2 === "content") return;
18046
- if (focusIdx2 && template2) {
18047
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18133
+ if (focusIdx2 && template) {
18134
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18048
18135
  if (element) {
18049
18136
  const parsed = parseBorder(element.attributes?.border);
18050
18137
  const newBorder = formatBorder({
@@ -18058,11 +18145,11 @@ function TemplateSidebar({ editorLoading }) {
18058
18145
  }
18059
18146
  }
18060
18147
  } else if (colorTarget === "columnBgColor") {
18061
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18062
- if (focusIdx2 && template2) {
18148
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18149
+ if (focusIdx2 && template) {
18063
18150
  const columnIdx = getParentIdx(focusIdx2);
18064
18151
  if (columnIdx) {
18065
- const column = (0, import_lodash8.get)(template2, toTemplatePath(columnIdx));
18152
+ const column = (0, import_lodash8.get)(template, toTemplatePath(columnIdx));
18066
18153
  if (column) {
18067
18154
  updateElement(columnIdx, {
18068
18155
  attributes: { ...column.attributes, "background-color": color }
@@ -18071,11 +18158,11 @@ function TemplateSidebar({ editorLoading }) {
18071
18158
  }
18072
18159
  }
18073
18160
  } else if (colorTarget === "columnStrokeColor") {
18074
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18075
- if (focusIdx2 && template2) {
18161
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18162
+ if (focusIdx2 && template) {
18076
18163
  const columnIdx = getParentIdx(focusIdx2);
18077
18164
  if (columnIdx) {
18078
- const column = (0, import_lodash8.get)(template2, toTemplatePath(columnIdx));
18165
+ const column = (0, import_lodash8.get)(template, toTemplatePath(columnIdx));
18079
18166
  if (column) {
18080
18167
  const parsed = parseBorder(column.attributes?.border);
18081
18168
  const newBorder = formatBorder({
@@ -18090,9 +18177,9 @@ function TemplateSidebar({ editorLoading }) {
18090
18177
  }
18091
18178
  }
18092
18179
  } else if (colorTarget === "spacerBgColor") {
18093
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18094
- if (focusIdx2 && template2) {
18095
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18180
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18181
+ if (focusIdx2 && template) {
18182
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18096
18183
  if (element) {
18097
18184
  updateElement(focusIdx2, {
18098
18185
  attributes: { ...element.attributes, "container-background-color": color }
@@ -18100,9 +18187,9 @@ function TemplateSidebar({ editorLoading }) {
18100
18187
  }
18101
18188
  }
18102
18189
  } else if (colorTarget === "dividerBorderColor") {
18103
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18104
- if (focusIdx2 && template2) {
18105
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18190
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18191
+ if (focusIdx2 && template) {
18192
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18106
18193
  if (element) {
18107
18194
  updateElement(focusIdx2, {
18108
18195
  attributes: { ...element.attributes, "border-color": color }
@@ -18110,9 +18197,9 @@ function TemplateSidebar({ editorLoading }) {
18110
18197
  }
18111
18198
  }
18112
18199
  } else if (colorTarget === "dividerBgColor") {
18113
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18114
- if (focusIdx2 && template2) {
18115
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18200
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18201
+ if (focusIdx2 && template) {
18202
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18116
18203
  if (element) {
18117
18204
  updateElement(focusIdx2, {
18118
18205
  attributes: { ...element.attributes, "container-background-color": color }
@@ -18120,9 +18207,9 @@ function TemplateSidebar({ editorLoading }) {
18120
18207
  }
18121
18208
  }
18122
18209
  } else if (colorTarget === "imageBgColor") {
18123
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18124
- if (focusIdx2 && template2) {
18125
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18210
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18211
+ if (focusIdx2 && template) {
18212
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18126
18213
  if (element) {
18127
18214
  updateElement(focusIdx2, {
18128
18215
  attributes: { ...element.attributes, "container-background-color": color }
@@ -18130,9 +18217,9 @@ function TemplateSidebar({ editorLoading }) {
18130
18217
  }
18131
18218
  }
18132
18219
  } else if (colorTarget === "socialBgColor") {
18133
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18134
- if (focusIdx2 && template2) {
18135
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18220
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18221
+ if (focusIdx2 && template) {
18222
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18136
18223
  if (element) {
18137
18224
  updateElement(focusIdx2, {
18138
18225
  attributes: { ...element.attributes, "container-background-color": color }
@@ -18140,9 +18227,9 @@ function TemplateSidebar({ editorLoading }) {
18140
18227
  }
18141
18228
  }
18142
18229
  } else if (colorTarget === "socialTextColor") {
18143
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18144
- if (focusIdx2 && template2) {
18145
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18230
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18231
+ if (focusIdx2 && template) {
18232
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18146
18233
  if (element) {
18147
18234
  updateElement(focusIdx2, {
18148
18235
  attributes: { ...element.attributes, "color": color }
@@ -18150,9 +18237,9 @@ function TemplateSidebar({ editorLoading }) {
18150
18237
  }
18151
18238
  }
18152
18239
  } else if (colorTarget === "socialItemTextColor") {
18153
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18154
- if (focusIdx2 && template2) {
18155
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18240
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18241
+ if (focusIdx2 && template) {
18242
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18156
18243
  if (element) {
18157
18244
  updateElement(focusIdx2, {
18158
18245
  attributes: { ...element.attributes, "color": color }
@@ -18160,9 +18247,9 @@ function TemplateSidebar({ editorLoading }) {
18160
18247
  }
18161
18248
  }
18162
18249
  } else if (colorTarget === "pageBgColor") {
18163
- const { updateElement, template: template2 } = useEditorStore.getState();
18164
- if (template2) {
18165
- const pageElement = template2.content?.[0];
18250
+ const { updateElement, template } = useEditorStore.getState();
18251
+ if (template) {
18252
+ const pageElement = template.content?.[0];
18166
18253
  if (pageElement) {
18167
18254
  updateElement("content", {
18168
18255
  attributes: { ...pageElement.attributes, "background-color": color }
@@ -18170,9 +18257,9 @@ function TemplateSidebar({ editorLoading }) {
18170
18257
  }
18171
18258
  }
18172
18259
  } else if (colorTarget === "linkColor") {
18173
- const { updateElement, template: template2 } = useEditorStore.getState();
18174
- if (template2) {
18175
- const pageElement = template2.content?.[0];
18260
+ const { updateElement, template } = useEditorStore.getState();
18261
+ if (template) {
18262
+ const pageElement = template.content?.[0];
18176
18263
  if (pageElement) {
18177
18264
  updateElement("content", {
18178
18265
  data: { value: { ...pageElement.data?.value, linkColor: color } }
@@ -18180,11 +18267,11 @@ function TemplateSidebar({ editorLoading }) {
18180
18267
  }
18181
18268
  }
18182
18269
  } else if (colorTarget === "propertyBgColor") {
18183
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18184
- if (focusIdx2 && template2) {
18270
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18271
+ if (focusIdx2 && template) {
18185
18272
  const columnIdx = getParentIdx(focusIdx2);
18186
18273
  if (columnIdx) {
18187
- const column = (0, import_lodash8.get)(template2, toTemplatePath(columnIdx));
18274
+ const column = (0, import_lodash8.get)(template, toTemplatePath(columnIdx));
18188
18275
  if (column) {
18189
18276
  updateElement(columnIdx, {
18190
18277
  attributes: { ...column.attributes, "background-color": color }
@@ -18193,12 +18280,12 @@ function TemplateSidebar({ editorLoading }) {
18193
18280
  }
18194
18281
  }
18195
18282
  } else if (colorTarget === "propertyStrokeColor") {
18196
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18197
- if (focusIdx2 && template2) {
18283
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18284
+ if (focusIdx2 && template) {
18198
18285
  const columnIdx = getParentIdx(focusIdx2);
18199
18286
  if (columnIdx) {
18200
- const column = (0, import_lodash8.get)(template2, toTemplatePath(columnIdx));
18201
- const property = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18287
+ const column = (0, import_lodash8.get)(template, toTemplatePath(columnIdx));
18288
+ const property = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18202
18289
  if (column) {
18203
18290
  const parsed = parseBorder(column.attributes?.border);
18204
18291
  const newBorder = formatBorder({
@@ -18218,13 +18305,13 @@ function TemplateSidebar({ editorLoading }) {
18218
18305
  }
18219
18306
  }
18220
18307
  } else if (colorTarget === "propertyTextColor") {
18221
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18222
- if (focusIdx2 && template2) {
18223
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18308
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18309
+ if (focusIdx2 && template) {
18310
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18224
18311
  if (element?.type === "property-card-triple-item") {
18225
18312
  const parentIdx = getParentIdx(focusIdx2);
18226
18313
  if (parentIdx) {
18227
- const parent = (0, import_lodash8.get)(template2, toTemplatePath(parentIdx));
18314
+ const parent = (0, import_lodash8.get)(template, toTemplatePath(parentIdx));
18228
18315
  if (parent) {
18229
18316
  updateElement(parentIdx, {
18230
18317
  attributes: { ...parent.attributes, "text-color": color }
@@ -18238,9 +18325,9 @@ function TemplateSidebar({ editorLoading }) {
18238
18325
  }
18239
18326
  }
18240
18327
  } else if (colorTarget === "statusColor") {
18241
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18242
- if (focusIdx2 && template2) {
18243
- const property = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18328
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18329
+ if (focusIdx2 && template) {
18330
+ const property = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18244
18331
  if (property) {
18245
18332
  updateElement(focusIdx2, {
18246
18333
  attributes: { ...property.attributes, "status-color": color }
@@ -18250,10 +18337,17 @@ function TemplateSidebar({ editorLoading }) {
18250
18337
  }
18251
18338
  }, [colorTarget]);
18252
18339
  const handleImageSelect = (0, import_react47.useCallback)((imageSrc) => {
18253
- const { focusIdx: focusIdx2, updateElement, template: template2 } = useEditorStore.getState();
18254
- if (!focusIdx2 || !template2) return;
18255
- const element = (0, import_lodash8.get)(template2, toTemplatePath(focusIdx2));
18340
+ const { focusIdx: focusIdx2, updateElement, template } = useEditorStore.getState();
18341
+ if (!focusIdx2 || !template) return;
18342
+ const element = (0, import_lodash8.get)(template, toTemplatePath(focusIdx2));
18256
18343
  if (!element) return;
18344
+ const validTypesForTarget = {
18345
+ sectionBgImage: ["section", "section-column", "section-property-km", "section-property-single-two", "section-property-triple"],
18346
+ imageElement: ["image"],
18347
+ propertyImage: ["property-card", "property-card-single-two", "property-card-triple-item"]
18348
+ };
18349
+ const validTypes = validTypesForTarget[imageTarget ?? ""];
18350
+ if (validTypes && !validTypes.includes(element.type)) return;
18257
18351
  const attributeName = imageTarget === "imageElement" ? "src" : imageTarget === "propertyImage" ? "image-src" : "background-url";
18258
18352
  updateElement(focusIdx2, {
18259
18353
  attributes: { ...element.attributes, [attributeName]: imageSrc }
@@ -18297,19 +18391,6 @@ function TemplateSidebar({ editorLoading }) {
18297
18391
  }
18298
18392
  ),
18299
18393
  /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "text-xs text-muted-foreground", children: "Styles" })
18300
- ] }),
18301
- /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "flex flex-col items-center gap-1", children: [
18302
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
18303
- Button,
18304
- {
18305
- onClick: () => handleViewClick("brand"),
18306
- variant: "ghost",
18307
- size: "icon",
18308
- className: `shadow-none transition-none w-[44px] h-[44px] p-0 flex flex-col items-center cursor-pointer ${activeView === "brand" ? "bg-sidebar-accent" : ""}`,
18309
- children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(import_lucide_react46.Hexagon, {})
18310
- }
18311
- ),
18312
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "text-xs text-muted-foreground", children: "Brand" })
18313
18394
  ] })
18314
18395
  ] }),
18315
18396
  /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
@@ -24437,10 +24518,10 @@ init_editor();
24437
24518
  init_idx();
24438
24519
  var import_jsx_runtime118 = require("react/jsx-runtime");
24439
24520
  function Toolbar() {
24440
- const { focusIdx, template } = useEditorStore();
24441
- const selectedElement = focusIdx ? getValueByIdx(template, focusIdx) : null;
24442
- const elementType = selectedElement?.type;
24443
- if (selectedElement === null) {
24521
+ const elementType = useEditorStore(
24522
+ (s) => s.focusIdx ? getValueByIdx(s.template, s.focusIdx)?.type : null
24523
+ );
24524
+ if (!elementType) {
24444
24525
  return;
24445
24526
  }
24446
24527
  if (elementType === "text") {
@@ -24556,25 +24637,19 @@ function TemplatePage({
24556
24637
  initialTemplate,
24557
24638
  onSave,
24558
24639
  onToast,
24559
- isPaidLevel = 0
24640
+ onExit,
24641
+ data
24560
24642
  }) {
24561
- console.log("Template page rendered!");
24562
- if (isPaidLevel > MAX_PAID_LEVEL) {
24563
- console.warn("This paid level is invalid:", isPaidLevel);
24564
- } else {
24565
- console.log("This paid level is valid:", isPaidLevel);
24566
- }
24567
24643
  (0, import_react83.useState)(() => {
24568
- useEditorStore.getState().initializeWithTemplate(templateId, initialTemplate, onSave, onToast, isPaidLevel);
24644
+ useEditorStore.getState().initializeWithTemplate(templateId, initialTemplate, onSave, onToast, data, onExit);
24569
24645
  });
24570
24646
  useAutoSave();
24571
24647
  const [editorLoading, setEditorLoading] = (0, import_react83.useState)(false);
24572
24648
  const [isPageHovered, setIsPageHovered] = (0, import_react83.useState)(false);
24573
- const template = useEditorStore((state) => state.template);
24574
24649
  const previewMode = useEditorStore((state) => state.previewMode);
24575
24650
  const focusIdx = useEditorStore((state) => state.focusIdx);
24576
24651
  const setFocusIdx = useEditorStore((state) => state.setFocusIdx);
24577
- const canvasBackgroundColor = template?.content?.[0]?.attributes?.["background-color"] || "#ffffff";
24652
+ const canvasBackgroundColor = useEditorStore((s) => s.template?.content?.[0]?.attributes?.["background-color"]) || "#ffffff";
24578
24653
  const handlePageClick = (e) => {
24579
24654
  if (!previewMode && e.target === e.currentTarget) {
24580
24655
  setFocusIdx("content");
@@ -24595,7 +24670,7 @@ function TemplatePage({
24595
24670
  {
24596
24671
  className: "flex flex-col bg-background overflow-hidden",
24597
24672
  children: [
24598
- /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TemplateHeader, { template }),
24673
+ /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TemplateHeader, {}),
24599
24674
  /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)("div", { className: "flex flex-row h-full bg-background", children: [
24600
24675
  /* @__PURE__ */ (0, import_jsx_runtime120.jsx)(TemplateSidebar, { editorLoading }),
24601
24676
  /* @__PURE__ */ (0, import_jsx_runtime120.jsxs)("div", { className: "flex flex-col w-full overflow-hidden h-[calc(100vh-60px)] bg-background relative", children: [