@kontakto/email-template-editor 2.2.0 → 2.2.2

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.cjs CHANGED
@@ -151,6 +151,13 @@ ${body}</tbody>
151
151
  }
152
152
  return `<a href="${href}" title="${title}" target="_blank">${text}</a>`;
153
153
  }
154
+ // Give paragraphs an explicit bottom margin that matches a blank line in the
155
+ // raw source. Without this, click-to-edit swaps the rendered div (flattened
156
+ // by ambient CSS) for a textarea whose blank lines take a full line-height,
157
+ // causing a visible layout jump.
158
+ paragraph(text) {
159
+ return `<p style="margin:0 0 1em 0">${text}</p>`;
160
+ }
154
161
  };
155
162
  function renderMarkdownString(str) {
156
163
  const html2 = marked.marked.parse(str, {
@@ -6521,11 +6528,20 @@ function HeadingEditor({ style, props }) {
6521
6528
  const handleTextChange = (e) => {
6522
6529
  commitText(e.target.value);
6523
6530
  };
6531
+ const displayRef = React58.useRef(null);
6532
+ const lastDisplayHeightRef = React58.useRef(0);
6533
+ React58.useLayoutEffect(() => {
6534
+ if (!isSelected && displayRef.current) {
6535
+ const h = displayRef.current.offsetHeight;
6536
+ if (h > 0) lastDisplayHeightRef.current = h;
6537
+ }
6538
+ }, [isSelected, textContent, isMarkdown, level]);
6524
6539
  const adjustTextareaHeight = (element) => {
6525
- if (element) {
6526
- element.style.height = "auto";
6527
- element.style.height = `${element.scrollHeight}px`;
6528
- }
6540
+ if (!element) return;
6541
+ element.style.height = "auto";
6542
+ const scrollH = element.scrollHeight;
6543
+ const floor = lastDisplayHeightRef.current;
6544
+ element.style.height = `${Math.max(scrollH, floor)}px`;
6529
6545
  };
6530
6546
  const { textareaRef, trackFocus, handleKeyDown, toolbarProps } = useMarkdownToolbar({
6531
6547
  text: localText,
@@ -6540,9 +6556,9 @@ function HeadingEditor({ style, props }) {
6540
6556
  });
6541
6557
  }
6542
6558
  });
6543
- React58.useEffect(() => {
6559
+ React58.useLayoutEffect(() => {
6544
6560
  if (textareaRef.current) adjustTextareaHeight(textareaRef.current);
6545
- }, [localText, textareaRef]);
6561
+ }, [localText, isSelected]);
6546
6562
  if (isSelected) {
6547
6563
  return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
6548
6564
  "textarea",
@@ -6564,7 +6580,11 @@ function HeadingEditor({ style, props }) {
6564
6580
  }
6565
6581
  ), /* @__PURE__ */ React58__default.default.createElement(InlineFormattingToolbar, __spreadValues({ anchorEl: textareaRef.current }, toolbarProps)));
6566
6582
  }
6567
- const headingProps = isMarkdown ? { style: hStyle, dangerouslySetInnerHTML: { __html: renderInlineMarkdownString(textContent) } } : { style: hStyle, children: textContent };
6583
+ const headingProps = isMarkdown ? {
6584
+ ref: displayRef,
6585
+ style: hStyle,
6586
+ dangerouslySetInnerHTML: { __html: renderInlineMarkdownString(textContent) }
6587
+ } : { ref: displayRef, style: hStyle, children: textContent };
6568
6588
  switch (level) {
6569
6589
  case "h1":
6570
6590
  return /* @__PURE__ */ React58__default.default.createElement("h1", __spreadValues({}, headingProps));
@@ -6996,11 +7016,20 @@ function TextEditor({ style, props }) {
6996
7016
  const handleTextChange = (e) => {
6997
7017
  commitText(e.target.value);
6998
7018
  };
7019
+ const displayRef = React58.useRef(null);
7020
+ const lastDisplayHeightRef = React58.useRef(0);
7021
+ React58.useLayoutEffect(() => {
7022
+ if (!isSelected && displayRef.current) {
7023
+ const h = displayRef.current.offsetHeight;
7024
+ if (h > 0) lastDisplayHeightRef.current = h;
7025
+ }
7026
+ }, [isSelected, textContent, isMarkdown]);
6999
7027
  const adjustTextareaHeight = (element) => {
7000
- if (element) {
7001
- element.style.height = "auto";
7002
- element.style.height = `${element.scrollHeight}px`;
7003
- }
7028
+ if (!element) return;
7029
+ element.style.height = "auto";
7030
+ const scrollH = element.scrollHeight;
7031
+ const floor = lastDisplayHeightRef.current;
7032
+ element.style.height = `${Math.max(scrollH, floor)}px`;
7004
7033
  };
7005
7034
  const { textareaRef, trackFocus, handleKeyDown, toolbarProps } = useMarkdownToolbar({
7006
7035
  text: localText,
@@ -7015,9 +7044,9 @@ function TextEditor({ style, props }) {
7015
7044
  });
7016
7045
  }
7017
7046
  });
7018
- React58.useEffect(() => {
7047
+ React58.useLayoutEffect(() => {
7019
7048
  if (textareaRef.current) adjustTextareaHeight(textareaRef.current);
7020
- }, [localText, textareaRef]);
7049
+ }, [localText, isSelected]);
7021
7050
  if (isSelected) {
7022
7051
  return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
7023
7052
  "textarea",
@@ -7040,9 +7069,16 @@ function TextEditor({ style, props }) {
7040
7069
  ), /* @__PURE__ */ React58__default.default.createElement(InlineFormattingToolbar, __spreadValues({ anchorEl: textareaRef.current }, toolbarProps)));
7041
7070
  }
7042
7071
  if (isMarkdown) {
7043
- return /* @__PURE__ */ React58__default.default.createElement(EmailMarkdown, { style: wStyle, markdown: textContent });
7072
+ return /* @__PURE__ */ React58__default.default.createElement(
7073
+ "div",
7074
+ {
7075
+ ref: displayRef,
7076
+ style: wStyle,
7077
+ dangerouslySetInnerHTML: { __html: renderMarkdownString(textContent) }
7078
+ }
7079
+ );
7044
7080
  }
7045
- return /* @__PURE__ */ React58__default.default.createElement("div", { style: wStyle }, textContent);
7081
+ return /* @__PURE__ */ React58__default.default.createElement("div", { ref: displayRef, style: wStyle }, textContent);
7046
7082
  }
7047
7083
 
7048
7084
  // src/editor/core.tsx