@trycourier/react-designer 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +75 -3
  2. package/dist/cjs/index.js +66 -58
  3. package/dist/cjs/index.js.map +4 -4
  4. package/dist/cjs/styles.css +579 -249
  5. package/dist/components/BrandEditor/Editor/BrandFooter/BrandFooter.d.ts +3 -1
  6. package/dist/components/Providers/TemplateProvider.d.ts +2 -0
  7. package/dist/components/TemplateEditor/Channels/Email/EmailEditor.d.ts +3 -1
  8. package/dist/components/TemplateEditor/Channels/Inbox/Inbox.d.ts +3 -0
  9. package/dist/components/TemplateEditor/Channels/Inbox/InboxEditor.d.ts +3 -1
  10. package/dist/components/TemplateEditor/Channels/MSTeams/MSTeams.d.ts +6 -1
  11. package/dist/components/TemplateEditor/Channels/MSTeams/MSTeamsEditor.d.ts +3 -1
  12. package/dist/components/TemplateEditor/Channels/MSTeams/SideBar/MSTeamsSideBarItemDetails.d.ts +8 -0
  13. package/dist/components/TemplateEditor/Channels/MSTeams/SideBar/index.d.ts +1 -0
  14. package/dist/components/TemplateEditor/Channels/MSTeams/index.d.ts +1 -1
  15. package/dist/components/TemplateEditor/Channels/Push/PushEditor.d.ts +3 -1
  16. package/dist/components/TemplateEditor/Channels/SMS/SMSEditor.d.ts +3 -1
  17. package/dist/components/TemplateEditor/Channels/Slack/Slack.d.ts +6 -1
  18. package/dist/components/TemplateEditor/Channels/Slack/SlackEditor.d.ts +3 -1
  19. package/dist/components/TemplateEditor/Layout/Layout.d.ts +1 -0
  20. package/dist/components/TemplateEditor/TemplateEditor.d.ts +2 -0
  21. package/dist/components/TemplateEditor/VariableViewModeSync.d.ts +27 -0
  22. package/dist/components/TemplateEditor/index.d.ts +2 -1
  23. package/dist/components/TemplateEditor/store.d.ts +19 -1
  24. package/dist/components/extensions/Blockquote/Blockquote.d.ts +4 -0
  25. package/dist/components/extensions/Button/Button.d.ts +0 -3
  26. package/dist/components/extensions/Button/Button.types.d.ts +8 -4
  27. package/dist/components/extensions/Button/ButtonComponent.d.ts +2 -3
  28. package/dist/components/extensions/Button/buttonUtils.d.ts +13 -0
  29. package/dist/components/extensions/HardBreak/HardBreak.d.ts +12 -0
  30. package/dist/components/extensions/HardBreak/index.d.ts +1 -0
  31. package/dist/components/extensions/ImageBlock/components/ImageBlockView.d.ts +1 -3
  32. package/dist/components/extensions/List/List.d.ts +0 -1
  33. package/dist/components/extensions/List/List.types.d.ts +0 -10
  34. package/dist/components/extensions/List/ListForm.d.ts +6 -1
  35. package/dist/components/extensions/MessagingChannelPaste/MessagingChannelPaste.d.ts +11 -0
  36. package/dist/components/extensions/MessagingChannelPaste/index.d.ts +2 -0
  37. package/dist/components/extensions/Variable/Variable.d.ts +5 -0
  38. package/dist/components/extensions/Variable/index.d.ts +2 -0
  39. package/dist/components/extensions/Variable/variable-storage.types.d.ts +26 -0
  40. package/dist/components/extensions/Variable/variable-storage.utils.d.ts +72 -0
  41. package/dist/components/extensions/extension-kit.d.ts +17 -0
  42. package/dist/components/extensions/index.d.ts +1 -1
  43. package/dist/components/ui/TextMenu/components/ContentTypePicker.d.ts +1 -1
  44. package/dist/components/ui/TextMenu/hooks/useTextmenuCommands.d.ts +0 -1
  45. package/dist/components/ui/TextMenu/hooks/useTextmenuStates.d.ts +1 -0
  46. package/dist/components/ui/VariableEditor/VariableChipBase.d.ts +8 -0
  47. package/dist/components/ui/VariableEditor/VariableInput.d.ts +18 -0
  48. package/dist/components/ui-kit/Button/Button.d.ts +1 -1
  49. package/dist/components/ui-kit/Toggle/Toggle.d.ts +2 -2
  50. package/dist/components/ui-kit/ToggleGroup/ToggleGroup.d.ts +2 -2
  51. package/dist/components/utils/shadowDomDndFix.d.ts +47 -0
  52. package/dist/esm/index.js +65 -57
  53. package/dist/esm/index.js.map +4 -4
  54. package/dist/esm/styles.css +579 -249
  55. package/dist/hooks/useAutoSave.d.ts +1 -0
  56. package/dist/index.d.ts +3 -0
  57. package/dist/lib/constants/block-defaults.d.ts +43 -0
  58. package/dist/lib/constants/email-editor-tiptap-styles.d.ts +62 -0
  59. package/dist/lib/index.d.ts +1 -0
  60. package/dist/lib/testHelpers.d.ts +21 -1
  61. package/dist/lib/utils/convertElementalToTiptap/convertElementalToTiptap.d.ts +6 -1
  62. package/dist/lib/utils/getTitle/index.d.ts +1 -1
  63. package/dist/lib/utils/getTitle/preserveStorageFormat.d.ts +7 -0
  64. package/dist/styles.css +579 -249
  65. package/dist/types/elemental.types.d.ts +3 -6
  66. package/package.json +6 -1
@@ -8,6 +8,7 @@ interface UseAutoSaveOptions<T> {
8
8
  }
9
9
  export declare function useAutoSave<T>({ onSave, debounceMs, enabled, onError, initialContent, flushBeforeSave, }: UseAutoSaveOptions<T>): {
10
10
  handleAutoSave: (content: T) => Promise<void>;
11
+ flush: () => Promise<void>;
11
12
  isSaving: boolean;
12
13
  };
13
14
  export {};
package/dist/index.d.ts CHANGED
@@ -16,5 +16,8 @@ export { Status as TemplateStatus } from "@/components/ui/Status";
16
16
  export { ToggleGroup, ToggleGroupItem, Toggle, Divider, Input, InputColor, } from "@/components/ui-kit";
17
17
  export { FacebookIcon, InstagramIcon, LinkedinIcon, MediumIcon, XIcon, } from "@/components/ui-kit/Icon";
18
18
  export { cn, convertElementalToTiptap, convertTiptapToElemental } from "@/lib/utils";
19
+ export { blockDefaults } from "@/lib/constants/block-defaults";
20
+ export { EMAIL_EDITOR_TEXT_STYLES, EMAIL_EDITOR_FONT_FAMILY, } from "@/lib/constants/email-editor-tiptap-styles";
19
21
  export { useAutoSave } from "@/hooks/useAutoSave";
20
22
  export { MonacoCodeEditor } from "@/components/extensions/CustomCode/MonacoCodeEditor";
23
+ export { applyShadowDomDndFix } from "@/components/utils/shadowDomDndFix";
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Central re-export of block default props. Each block's defaults live in its own
3
+ * extension (e.g. Blockquote/Blockquote.ts); this file only aggregates them for
4
+ * consumers (e.g. Studio's elemental-to-HTML converter) via blockDefaults.
5
+ */
6
+ export { defaultBlockquoteProps, QUOTE_TEXT_STYLE, QUOTE_TEXT_STYLE_VARIANTS, } from "@/components/extensions/Blockquote/Blockquote";
7
+ export { defaultButtonProps } from "@/components/extensions/Button/Button";
8
+ export { defaultDividerProps, defaultSpacerProps } from "@/components/extensions/Divider/Divider";
9
+ export { defaultImageProps } from "@/components/extensions/ImageBlock/ImageBlock";
10
+ export { defaultTextBlockProps } from "@/components/extensions/TextBlock/TextBlock.types";
11
+ export { defaultListProps } from "@/components/extensions/List";
12
+ /**
13
+ * Single namespace for all block defaults.
14
+ * Use: import { blockDefaults } from '@trycourier/react-designer'
15
+ * Then: blockDefaults.blockquote, blockDefaults.button, blockDefaults.quoteTextStyle, etc.
16
+ */
17
+ export declare const blockDefaults: {
18
+ readonly blockquote: {
19
+ backgroundColor: string;
20
+ borderColor: string;
21
+ paddingVertical: number;
22
+ paddingHorizontal: number;
23
+ borderLeftWidth: number;
24
+ id?: string | undefined;
25
+ };
26
+ readonly button: import("../../components/extensions/Button").ButtonProps;
27
+ readonly divider: import("../../components/extensions/Divider").DividerProps;
28
+ readonly spacer: import("../../components/extensions/Divider").DividerProps;
29
+ readonly image: import("../../components/extensions/ImageBlock").ImageBlockProps;
30
+ readonly text: import("@/components/extensions/TextBlock/TextBlock.types").TextBlockProps;
31
+ readonly list: import("@/components/extensions/List").ListProps;
32
+ readonly quoteTextStyle: {
33
+ readonly color: "#696969";
34
+ readonly fontSize: "14px";
35
+ readonly lineHeight: "18px";
36
+ readonly fontStyle: "italic";
37
+ };
38
+ readonly quoteTextStyleVariants: Record<"h1" | "h2" | "h3" | "subtext" | "quote", {
39
+ fontSize: string;
40
+ fontWeight: string;
41
+ lineHeight: string;
42
+ }>;
43
+ };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Single source of truth for .courier-email-editor .tiptap font styles.
3
+ * These values are applied via CSS custom properties from EmailEditorContainer
4
+ * so styles.css can use var(--email-editor-*) and stay in sync.
5
+ */
6
+ export declare const EMAIL_EDITOR_FONT_FAMILY = "Helvetica, Arial, sans-serif";
7
+ /** Paragraph and heading styles (non-blockquote) for email editor. */
8
+ export declare const EMAIL_EDITOR_TEXT_STYLES: {
9
+ readonly p: {
10
+ readonly color: "#000000";
11
+ readonly fontSize: "14px";
12
+ readonly lineHeight: "18px";
13
+ };
14
+ readonly h1: {
15
+ readonly color: "#000000";
16
+ readonly fontSize: "32px";
17
+ readonly fontWeight: "600";
18
+ readonly lineHeight: "40px";
19
+ };
20
+ readonly h2: {
21
+ readonly color: "#000000";
22
+ readonly fontSize: "24px";
23
+ readonly fontWeight: "600";
24
+ readonly lineHeight: "32px";
25
+ };
26
+ readonly h3: {
27
+ readonly color: "#000000";
28
+ readonly fontSize: "18.72px";
29
+ readonly fontWeight: "600";
30
+ readonly lineHeight: "24px";
31
+ };
32
+ readonly subtext: {
33
+ readonly color: "#8F8F8F";
34
+ readonly fontSize: "11px";
35
+ readonly lineHeight: "15px";
36
+ };
37
+ };
38
+ /**
39
+ * Text style applied to quote body content.
40
+ * Matches backend courier-email-text-style quote defaults.
41
+ */
42
+ export declare const QUOTE_TEXT_STYLE: {
43
+ readonly color: "#696969";
44
+ readonly fontSize: "14px";
45
+ readonly lineHeight: "18px";
46
+ readonly fontStyle: "italic";
47
+ };
48
+ /**
49
+ * Quote text style variants when text_style is h1/h2/h3/subtext.
50
+ * Derives sizing from EMAIL_EDITOR_TEXT_STYLES to stay in sync.
51
+ */
52
+ export declare const QUOTE_TEXT_STYLE_VARIANTS: Record<"h1" | "h2" | "h3" | "subtext" | "quote", {
53
+ fontSize: string;
54
+ fontWeight: string;
55
+ lineHeight: string;
56
+ }>;
57
+ /**
58
+ * Returns CSS custom properties to set on .courier-email-editor so that
59
+ * .courier-email-editor .tiptap rules in styles.css (using var(--email-editor-*))
60
+ * resolve from this single source of truth.
61
+ */
62
+ export declare function getEmailEditorTiptapCssVars(): Record<string, string>;
@@ -1 +1,2 @@
1
1
  export * from "./utils";
2
+ export * from "./constants/block-defaults";
@@ -1,6 +1,7 @@
1
1
  import type { Editor } from "@tiptap/react";
2
2
  import type { ElementalContent } from "@/types/elemental.types";
3
3
  type ChannelType = "email" | "sms" | "push" | "inbox" | "slack" | "teams";
4
+ type TestChannelType = "email" | "sms" | "push" | "inbox" | "slack" | "msteams";
4
5
  declare global {
5
6
  interface Window {
6
7
  __COURIER_CREATE_TEST__?: {
@@ -13,8 +14,27 @@ declare global {
13
14
  teams: Editor | null;
14
15
  };
15
16
  currentEditor: Editor | null;
16
- activeChannel: "email" | "sms" | "push" | "inbox" | "slack" | "teams" | null;
17
+ activeChannel: ChannelType | null;
17
18
  templateEditorContent: ElementalContent | null | undefined;
19
+ /**
20
+ * Programmatically set the template editor content.
21
+ * This is used for testing API-based content updates.
22
+ */
23
+ setTemplateEditorContent?: (content: ElementalContent | null) => void;
24
+ /**
25
+ * Get the current template editor content.
26
+ * Useful for verifying content state in tests.
27
+ */
28
+ getTemplateEditorContent?: () => ElementalContent | null | undefined;
29
+ /**
30
+ * Switch to a specific channel.
31
+ * Used in E2E tests to programmatically change channels.
32
+ */
33
+ setChannel?: (channel: TestChannelType) => void;
34
+ /**
35
+ * Get the current active channel.
36
+ */
37
+ getChannel?: () => TestChannelType | null;
18
38
  };
19
39
  }
20
40
  }
@@ -1,4 +1,9 @@
1
- import type { TiptapNode, ElementalContent, TiptapDoc } from "../../../types";
1
+ import type { TiptapNode, ElementalContent, ElementalTextContentNode, TiptapDoc } from "../../../types";
2
+ /**
3
+ * Convert an Elemental elements array (type: "string" | "link" sub-elements with boolean
4
+ * formatting flags) into TipTap nodes. Handles variables ({{var}}) and newlines (\n → hardBreak).
5
+ */
6
+ export declare function convertElementsArrayToTiptapNodes(elements: ElementalTextContentNode[]): TiptapNode[];
2
7
  export declare function parseMDContent(content: string): TiptapNode[];
3
8
  export interface ConvertElementalToTiptapOptions {
4
9
  channel?: string;
@@ -1,2 +1,2 @@
1
1
  export { getTitle, getTitleFromContent, getTitleForChannel } from "./getTitle";
2
- export { getSubjectStorageFormat, createTitleUpdate, extractCurrentTitle, cleanSMSElements, cleanPushElements, cleanInboxElements, } from "./preserveStorageFormat";
2
+ export { getSubjectStorageFormat, createTitleUpdate, extractCurrentTitle, extractPlainTextFromNode, cleanSMSElements, cleanPushElements, cleanInboxElements, } from "./preserveStorageFormat";
@@ -1,10 +1,17 @@
1
1
  import type { ElementalContent, ElementalNode } from "@/types/elemental.types";
2
+ /**
3
+ * Extract plain text from an ElementalNode, handling both simple format ({ content: "..." })
4
+ * and rich format ({ elements: [{ type: "string", content: "..." }, ...] }).
5
+ * The rich format is produced by convertTiptapToElemental for heading/paragraph nodes.
6
+ */
7
+ export declare function extractPlainTextFromNode(element: ElementalNode): string;
2
8
  /**
3
9
  * Cleans an Inbox element by removing styling properties from text and action elements.
4
10
  */
5
11
  export declare function cleanInboxElements(elements: ElementalNode[]): ElementalNode[];
6
12
  /**
7
13
  * Cleans Push elements by removing styling properties from text elements.
14
+ * Handles both simple format ({ content: "..." }) and rich format ({ elements: [...] }).
8
15
  */
9
16
  export declare function cleanPushElements(elements: ElementalNode[]): ElementalNode[];
10
17
  /**