@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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import DOMPurify from 'dompurify';
2
2
  import { marked, Renderer } from 'marked';
3
- import React58, { createContext, forwardRef, useRef, useEffect, useImperativeHandle, useMemo, useContext, useState, useCallback, Fragment } from 'react';
3
+ import React58, { createContext, forwardRef, useRef, useEffect, useImperativeHandle, useMemo, useContext, useState, useCallback, useLayoutEffect, Fragment } from 'react';
4
4
  import { z } from 'zod';
5
5
  import { renderToStaticMarkup as renderToStaticMarkup$1 } from 'react-dom/server';
6
6
  import { createTheme, alpha, lighten, darken } from '@mui/material/styles';
@@ -141,6 +141,13 @@ ${body}</tbody>
141
141
  }
142
142
  return `<a href="${href}" title="${title}" target="_blank">${text}</a>`;
143
143
  }
144
+ // Give paragraphs an explicit bottom margin that matches a blank line in the
145
+ // raw source. Without this, click-to-edit swaps the rendered div (flattened
146
+ // by ambient CSS) for a textarea whose blank lines take a full line-height,
147
+ // causing a visible layout jump.
148
+ paragraph(text) {
149
+ return `<p style="margin:0 0 1em 0">${text}</p>`;
150
+ }
144
151
  };
145
152
  function renderMarkdownString(str) {
146
153
  const html2 = marked.parse(str, {
@@ -6511,11 +6518,20 @@ function HeadingEditor({ style, props }) {
6511
6518
  const handleTextChange = (e) => {
6512
6519
  commitText(e.target.value);
6513
6520
  };
6521
+ const displayRef = useRef(null);
6522
+ const lastDisplayHeightRef = useRef(0);
6523
+ useLayoutEffect(() => {
6524
+ if (!isSelected && displayRef.current) {
6525
+ const h = displayRef.current.offsetHeight;
6526
+ if (h > 0) lastDisplayHeightRef.current = h;
6527
+ }
6528
+ }, [isSelected, textContent, isMarkdown, level]);
6514
6529
  const adjustTextareaHeight = (element) => {
6515
- if (element) {
6516
- element.style.height = "auto";
6517
- element.style.height = `${element.scrollHeight}px`;
6518
- }
6530
+ if (!element) return;
6531
+ element.style.height = "auto";
6532
+ const scrollH = element.scrollHeight;
6533
+ const floor = lastDisplayHeightRef.current;
6534
+ element.style.height = `${Math.max(scrollH, floor)}px`;
6519
6535
  };
6520
6536
  const { textareaRef, trackFocus, handleKeyDown, toolbarProps } = useMarkdownToolbar({
6521
6537
  text: localText,
@@ -6530,9 +6546,9 @@ function HeadingEditor({ style, props }) {
6530
6546
  });
6531
6547
  }
6532
6548
  });
6533
- useEffect(() => {
6549
+ useLayoutEffect(() => {
6534
6550
  if (textareaRef.current) adjustTextareaHeight(textareaRef.current);
6535
- }, [localText, textareaRef]);
6551
+ }, [localText, isSelected]);
6536
6552
  if (isSelected) {
6537
6553
  return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
6538
6554
  "textarea",
@@ -6554,7 +6570,11 @@ function HeadingEditor({ style, props }) {
6554
6570
  }
6555
6571
  ), /* @__PURE__ */ React58.createElement(InlineFormattingToolbar, __spreadValues({ anchorEl: textareaRef.current }, toolbarProps)));
6556
6572
  }
6557
- const headingProps = isMarkdown ? { style: hStyle, dangerouslySetInnerHTML: { __html: renderInlineMarkdownString(textContent) } } : { style: hStyle, children: textContent };
6573
+ const headingProps = isMarkdown ? {
6574
+ ref: displayRef,
6575
+ style: hStyle,
6576
+ dangerouslySetInnerHTML: { __html: renderInlineMarkdownString(textContent) }
6577
+ } : { ref: displayRef, style: hStyle, children: textContent };
6558
6578
  switch (level) {
6559
6579
  case "h1":
6560
6580
  return /* @__PURE__ */ React58.createElement("h1", __spreadValues({}, headingProps));
@@ -6986,11 +7006,20 @@ function TextEditor({ style, props }) {
6986
7006
  const handleTextChange = (e) => {
6987
7007
  commitText(e.target.value);
6988
7008
  };
7009
+ const displayRef = useRef(null);
7010
+ const lastDisplayHeightRef = useRef(0);
7011
+ useLayoutEffect(() => {
7012
+ if (!isSelected && displayRef.current) {
7013
+ const h = displayRef.current.offsetHeight;
7014
+ if (h > 0) lastDisplayHeightRef.current = h;
7015
+ }
7016
+ }, [isSelected, textContent, isMarkdown]);
6989
7017
  const adjustTextareaHeight = (element) => {
6990
- if (element) {
6991
- element.style.height = "auto";
6992
- element.style.height = `${element.scrollHeight}px`;
6993
- }
7018
+ if (!element) return;
7019
+ element.style.height = "auto";
7020
+ const scrollH = element.scrollHeight;
7021
+ const floor = lastDisplayHeightRef.current;
7022
+ element.style.height = `${Math.max(scrollH, floor)}px`;
6994
7023
  };
6995
7024
  const { textareaRef, trackFocus, handleKeyDown, toolbarProps } = useMarkdownToolbar({
6996
7025
  text: localText,
@@ -7005,9 +7034,9 @@ function TextEditor({ style, props }) {
7005
7034
  });
7006
7035
  }
7007
7036
  });
7008
- useEffect(() => {
7037
+ useLayoutEffect(() => {
7009
7038
  if (textareaRef.current) adjustTextareaHeight(textareaRef.current);
7010
- }, [localText, textareaRef]);
7039
+ }, [localText, isSelected]);
7011
7040
  if (isSelected) {
7012
7041
  return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
7013
7042
  "textarea",
@@ -7030,9 +7059,16 @@ function TextEditor({ style, props }) {
7030
7059
  ), /* @__PURE__ */ React58.createElement(InlineFormattingToolbar, __spreadValues({ anchorEl: textareaRef.current }, toolbarProps)));
7031
7060
  }
7032
7061
  if (isMarkdown) {
7033
- return /* @__PURE__ */ React58.createElement(EmailMarkdown, { style: wStyle, markdown: textContent });
7062
+ return /* @__PURE__ */ React58.createElement(
7063
+ "div",
7064
+ {
7065
+ ref: displayRef,
7066
+ style: wStyle,
7067
+ dangerouslySetInnerHTML: { __html: renderMarkdownString(textContent) }
7068
+ }
7069
+ );
7034
7070
  }
7035
- return /* @__PURE__ */ React58.createElement("div", { style: wStyle }, textContent);
7071
+ return /* @__PURE__ */ React58.createElement("div", { ref: displayRef, style: wStyle }, textContent);
7036
7072
  }
7037
7073
 
7038
7074
  // src/editor/core.tsx