better-react-email-editor 0.1.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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +381 -0
  3. package/dist/index.cjs +2 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.js +4190 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/styles.css +1634 -0
  8. package/dist/types/components/BetterEmailEditor.d.ts +34 -0
  9. package/dist/types/components/BlockProperties.d.ts +7 -0
  10. package/dist/types/components/BlocksTab.d.ts +13 -0
  11. package/dist/types/components/BodyTab.d.ts +9 -0
  12. package/dist/types/components/Canvas.d.ts +15 -0
  13. package/dist/types/components/CanvasOverlay.d.ts +10 -0
  14. package/dist/types/components/ContentPanel.d.ts +19 -0
  15. package/dist/types/components/ContentTab.d.ts +17 -0
  16. package/dist/types/components/LayersPanel.d.ts +9 -0
  17. package/dist/types/components/PreviewDialog.d.ts +15 -0
  18. package/dist/types/components/PropertiesPanel.d.ts +12 -0
  19. package/dist/types/components/Sidebar.d.ts +14 -0
  20. package/dist/types/components/TextProperties.d.ts +7 -0
  21. package/dist/types/components/TopBar.d.ts +37 -0
  22. package/dist/types/components/fields.d.ts +103 -0
  23. package/dist/types/components/icons.d.ts +21 -0
  24. package/dist/types/components/inspectors/ButtonInspector.d.ts +2 -0
  25. package/dist/types/components/inspectors/ColumnsInspector.d.ts +3 -0
  26. package/dist/types/components/inspectors/DefaultInspector.d.ts +3 -0
  27. package/dist/types/components/inspectors/HeadingInspector.d.ts +2 -0
  28. package/dist/types/components/inspectors/ImageInspector.d.ts +2 -0
  29. package/dist/types/components/inspectors/SimpleInspectors.d.ts +6 -0
  30. package/dist/types/components/inspectors/SocialLinksInspector.d.ts +2 -0
  31. package/dist/types/components/inspectors/groups.d.ts +22 -0
  32. package/dist/types/components/useDraggableBlock.d.ts +17 -0
  33. package/dist/types/context.d.ts +115 -0
  34. package/dist/types/core/content.d.ts +28 -0
  35. package/dist/types/core/cx.d.ts +8 -0
  36. package/dist/types/core/dnd.d.ts +73 -0
  37. package/dist/types/core/layers.d.ts +27 -0
  38. package/dist/types/core/paste-handler.d.ts +9 -0
  39. package/dist/types/core/paste.d.ts +22 -0
  40. package/dist/types/core/stores.d.ts +19 -0
  41. package/dist/types/core/style-utils.d.ts +3 -0
  42. package/dist/types/i18n/en.d.ts +247 -0
  43. package/dist/types/i18n/fr.d.ts +3 -0
  44. package/dist/types/i18n/index.d.ts +509 -0
  45. package/dist/types/index.d.ts +37 -0
  46. package/dist/types/nodes/custom-nodes.d.ts +19 -0
  47. package/dist/types/registry/default-nodes.d.ts +7 -0
  48. package/dist/types/registry/default-palette.d.ts +7 -0
  49. package/dist/types/registry/default-templates.d.ts +10 -0
  50. package/dist/types/registry/types.d.ts +56 -0
  51. package/package.json +89 -0
@@ -0,0 +1,34 @@
1
+ import { type ComponentType } from 'react';
2
+ import { type EditorRootProps, type EmailEditorHandle } from '../context';
3
+ import { type CanvasProps } from './Canvas';
4
+ import { type LayersPanelProps } from './LayersPanel';
5
+ import { type SidebarProps } from './Sidebar';
6
+ import { type TopBarProps } from './TopBar';
7
+ export interface BetterEmailEditorComponents {
8
+ TopBar?: ComponentType<TopBarProps>;
9
+ LayersPanel?: ComponentType<LayersPanelProps>;
10
+ Canvas?: ComponentType<CanvasProps>;
11
+ Sidebar?: ComponentType<SidebarProps>;
12
+ }
13
+ export interface BetterEmailEditorProps extends Omit<EditorRootProps, 'children'> {
14
+ /** Show the top bar. Default: true. */
15
+ showTopBar?: boolean;
16
+ /** Show the layers panel. Default: true. */
17
+ showLayers?: boolean;
18
+ /** Show the right sidebar. Default: true. */
19
+ showSidebar?: boolean;
20
+ /** Replace any part with your own component. */
21
+ components?: BetterEmailEditorComponents;
22
+ /** Props (className, style…) forwarded to each part. */
23
+ slotProps?: {
24
+ topBar?: TopBarProps;
25
+ layersPanel?: LayersPanelProps;
26
+ canvas?: CanvasProps;
27
+ sidebar?: SidebarProps;
28
+ };
29
+ }
30
+ /**
31
+ * The complete editor in one component: top bar, layers, canvas and sidebar.
32
+ * For a custom layout, use `EditorRoot` with the individual components instead.
33
+ */
34
+ export declare const BetterEmailEditor: import("react").ForwardRefExoticComponent<BetterEmailEditorProps & import("react").RefAttributes<EmailEditorHandle>>;
@@ -0,0 +1,7 @@
1
+ import type { InspectorNodeContext } from '@react-email/editor/ui';
2
+ import type { StyleProps } from '../core/cx';
3
+ export interface BlockPropertiesProps extends StyleProps {
4
+ ctx: InspectorNodeContext;
5
+ }
6
+ /** Properties of the selected block: picks the inspector registered for its node type. */
7
+ export declare function BlockProperties({ ctx, className, style }: BlockPropertiesProps): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { type StyleProps } from '../core/cx';
2
+ import type { TemplateItem } from '../registry/types';
3
+ export interface TemplateCardProps extends StyleProps {
4
+ template: TemplateItem;
5
+ }
6
+ /** One draggable prebuilt row. */
7
+ export declare function TemplateCard({ template, className, style }: TemplateCardProps): import("react").JSX.Element;
8
+ export interface BlocksTabProps extends StyleProps {
9
+ /** Defaults to the editor's `templates`. */
10
+ templates?: TemplateItem[];
11
+ }
12
+ /** "Blocks" tab: prebuilt rows (header, hero, footer…). */
13
+ export declare function BlocksTab({ templates, className, style }: BlocksTabProps): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import type { InspectorDocumentProps } from '@react-email/editor/ui';
2
+ import { type StyleProps } from '../core/cx';
3
+ /** Context given by `Inspector.Document`: global (theme) styles of the email. */
4
+ export type DocumentContext = Parameters<NonNullable<InspectorDocumentProps['children']>>[0];
5
+ export interface BodyTabProps extends StyleProps {
6
+ ctx: DocumentContext;
7
+ }
8
+ /** "Body" tab: email-wide settings (background, width, default colors, preview text). */
9
+ export declare function BodyTab({ ctx, className, style }: BodyTabProps): import("react").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { type SlashCommandItem } from '@react-email/editor/ui';
2
+ import { type ReactNode } from 'react';
3
+ import { type StyleProps } from '../core/cx';
4
+ export interface CanvasProps extends StyleProps {
5
+ /** Hover / selection frames, block toolbar and drag & drop. Default: true. */
6
+ overlay?: boolean;
7
+ /** The package's floating text menu (bold, link…). Default: true. */
8
+ bubbleMenu?: boolean;
9
+ /** "/" command menu. `true` (default), `false`, or your own items. */
10
+ slashCommands?: boolean | SlashCommandItem[];
11
+ /** Extra content rendered inside the canvas scroll area. */
12
+ children?: ReactNode;
13
+ }
14
+ /** The editable email. Scrolls on its own: give it a height through its parent or `style`. */
15
+ export declare function Canvas({ overlay, bubbleMenu, slashCommands, className, style, children }: CanvasProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import type { Editor } from '@tiptap/core';
2
+ /**
3
+ * Everything drawn on top of the canvas: hover outline, selection frame with
4
+ * its toolbar, and the drop indicator. Also owns the drag & drop listeners for
5
+ * the canvas so ProseMirror never sees our custom drags. Rendered by `Canvas`.
6
+ */
7
+ export declare function CanvasOverlay({ editor, host }: {
8
+ editor: Editor;
9
+ host: HTMLElement;
10
+ }): import("react").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type StyleProps } from '../core/cx';
3
+ import { type DocumentContext } from './BodyTab';
4
+ export interface ContentPanelTab {
5
+ id: string;
6
+ label: string;
7
+ render: (ctx: DocumentContext) => ReactNode;
8
+ }
9
+ export interface ContentPanelProps extends StyleProps {
10
+ ctx: DocumentContext;
11
+ /**
12
+ * Tabs to show. Built-in ids: "content", "blocks", "body". Pass objects to
13
+ * add your own tabs, e.g. `['content', { id: 'saved', label: 'Saved', render: () => <Saved /> }]`.
14
+ */
15
+ tabs?: Array<'content' | 'blocks' | 'body' | ContentPanelTab>;
16
+ defaultTab?: string;
17
+ }
18
+ /** Sidebar screen shown when nothing is selected: tabs Content / Blocks / Body. */
19
+ export declare function ContentPanel({ ctx, tabs, defaultTab, className, style }: ContentPanelProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { type StyleProps } from '../core/cx';
2
+ import type { PaletteGroup, PaletteItem } from '../registry/types';
3
+ export interface PaletteTileProps extends StyleProps {
4
+ item: PaletteItem;
5
+ }
6
+ /** One draggable tile of the palette. */
7
+ export declare function PaletteTile({ item, className, style }: PaletteTileProps): import("react").JSX.Element;
8
+ export interface ContentTabProps extends StyleProps {
9
+ /** Defaults to the editor's `palette`. */
10
+ items?: PaletteItem[];
11
+ /** Defaults to the editor's `paletteGroups`; groups found only in items are added at the end. */
12
+ groups?: PaletteGroup[];
13
+ /** Hint under the tiles. `null` hides it. */
14
+ hint?: string | null;
15
+ }
16
+ /** "Content" tab: layout and content tiles, grouped. */
17
+ export declare function ContentTab({ items, groups, hint, className, style }: ContentTabProps): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { type StyleProps } from '../core/cx';
2
+ export interface LayersPanelProps extends StyleProps {
3
+ /** Shows a close button that calls it, e.g. `() => setLayersOpen(false)` when you also render a `LayersToggle`. */
4
+ onClose?: () => void;
5
+ /** Panel title. Defaults to the localized "Layers". */
6
+ title?: string;
7
+ }
8
+ /** Tree of the email (Photoshop-like layers): select, hover, reorder and nest blocks by drag & drop. */
9
+ export declare function LayersPanel({ onClose, title, className, style }: LayersPanelProps): import("react").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { type StyleProps } from '../core/cx';
2
+ export type PreviewView = 'desktop' | 'mobile' | 'html' | 'text';
3
+ /** Triggers a browser download of `content`. */
4
+ export declare function download(filename: string, content: string, type: string): void;
5
+ export interface PreviewDialogProps extends StyleProps {
6
+ onClose: () => void;
7
+ /** Tab shown first. Default: "desktop". */
8
+ defaultView?: PreviewView;
9
+ /** Tabs to show. Default: all four. */
10
+ views?: PreviewView[];
11
+ /** Name of the downloaded file. Default: "email.html". */
12
+ filename?: string;
13
+ }
14
+ /** Modal with the rendered email: desktop / mobile preview, HTML and plain text, copy and download. Render it to open it. */
15
+ export declare function PreviewDialog({ onClose, defaultView, views, filename, className, style, }: PreviewDialogProps): import("react").ReactPortal;
@@ -0,0 +1,12 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type StyleProps } from '../core/cx';
3
+ export interface PropertiesPanelProps extends StyleProps {
4
+ title: string;
5
+ children: ReactNode;
6
+ /** Shows the hierarchy (Email / Row / Column / Text…) under the header. Default: true. */
7
+ breadcrumb?: boolean;
8
+ }
9
+ /** Deselects everything: the sidebar goes back to the content panel. */
10
+ export declare function useDeselect(): () => void;
11
+ /** Sidebar screen shown when something is selected: header, breadcrumb and the inspector below. */
12
+ export declare function PropertiesPanel({ title, children, breadcrumb, className, style }: PropertiesPanelProps): import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { type InspectorNodeContext, type InspectorTextContext } from '@react-email/editor/ui';
2
+ import type { ReactNode } from 'react';
3
+ import { type StyleProps } from '../core/cx';
4
+ import type { DocumentContext } from './BodyTab';
5
+ export interface SidebarProps extends StyleProps {
6
+ /** Screen when nothing is selected. Default: `<ContentPanel />`. */
7
+ renderDocument?: (ctx: DocumentContext) => ReactNode;
8
+ /** Screen when a block is selected. Default: `<BlockProperties />`. */
9
+ renderNode?: (ctx: InspectorNodeContext) => ReactNode;
10
+ /** Screen when text is selected. Default: `<TextProperties />`. */
11
+ renderText?: (ctx: InspectorTextContext) => ReactNode;
12
+ }
13
+ /** Right panel: switches between the content panel and the properties of the selection. */
14
+ export declare function Sidebar({ renderDocument, renderNode, renderText, className, style, }: SidebarProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { type InspectorTextContext } from '@react-email/editor/ui';
2
+ import { type StyleProps } from '../core/cx';
3
+ export interface TextPropertiesProps extends StyleProps {
4
+ ctx: InspectorTextContext;
5
+ }
6
+ /** Properties of a text selection: marks, typography and link color. */
7
+ export declare function TextProperties({ ctx, className, style }: TextPropertiesProps): import("react").JSX.Element;
@@ -0,0 +1,37 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type StyleProps } from '../core/cx';
3
+ import { type PreviewView } from './PreviewDialog';
4
+ export declare function LayersToggle({ className, style }: StyleProps): import("react").JSX.Element;
5
+ export declare function UndoRedo({ className, style }: StyleProps): import("react").JSX.Element;
6
+ export declare function DeviceToggle({ className, style }: StyleProps): import("react").JSX.Element;
7
+ /** Replaces the content with the starter document (after confirmation). */
8
+ export declare function TemplateButton({ className, style }: StyleProps): import("react").JSX.Element;
9
+ /** Loads a JSON file saved by `ExportJsonButton` (or a bare Tiptap document). */
10
+ export declare function ImportButton({ className, style }: StyleProps): import("react").JSX.Element;
11
+ /** Downloads `{ doc, settings }` as email.json. */
12
+ export declare function ExportJsonButton({ className, style, filename }: StyleProps & {
13
+ filename?: string;
14
+ }): import("react").JSX.Element;
15
+ export interface PreviewButtonProps extends StyleProps {
16
+ /** Tab opened in the preview dialog. Default: "desktop". */
17
+ view?: PreviewView;
18
+ variant?: 'default' | 'primary' | 'ghost';
19
+ children?: ReactNode;
20
+ }
21
+ /** Opens the preview / export dialog. */
22
+ export declare function PreviewButton({ view, variant, children, className, style }: PreviewButtonProps): import("react").JSX.Element;
23
+ export declare function ExportHtmlButton(props: StyleProps): import("react").JSX.Element;
24
+ export interface TopBarProps extends StyleProps {
25
+ /** Left side, e.g. your logo. Empty by default. */
26
+ brand?: ReactNode;
27
+ /** Extra controls placed before the export button. */
28
+ actions?: ReactNode;
29
+ /** Replaces the default controls (device toggle + export) with your own. */
30
+ children?: ReactNode;
31
+ }
32
+ /**
33
+ * Top bar: device toggle (desktop / mobile) and the export button. Add more
34
+ * controls with `actions`, or compose your own bar from `LayersToggle`,
35
+ * `UndoRedo`, `TemplateButton`, `ImportButton`, `ExportJsonButton`, `PreviewButton`…
36
+ */
37
+ export declare function TopBar({ brand, actions, children, className, style }: TopBarProps): import("react").JSX.Element;
@@ -0,0 +1,103 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type StyleProps } from '../core/cx';
3
+ /**
4
+ * Form controls of the properties panel. Exported so custom inspectors look
5
+ * like the built-in ones. Text-like inputs commit on blur / Enter to avoid
6
+ * spamming editor transactions.
7
+ */
8
+ export interface GroupProps extends StyleProps {
9
+ title: string;
10
+ children: ReactNode;
11
+ defaultOpen?: boolean;
12
+ }
13
+ /** Collapsible section of the properties panel. */
14
+ export declare function Group({ title, children, defaultOpen, className, style }: GroupProps): import("react").JSX.Element;
15
+ export interface FieldProps extends StyleProps {
16
+ label: string;
17
+ children: ReactNode;
18
+ /** Label above the control instead of beside it. */
19
+ stacked?: boolean;
20
+ }
21
+ export declare function Field({ label, children, stacked, className, style }: FieldProps): import("react").JSX.Element;
22
+ export interface TextInputProps extends StyleProps {
23
+ value: string;
24
+ onChange: (value: string) => void;
25
+ placeholder?: string;
26
+ type?: string;
27
+ }
28
+ export declare function TextInput({ value, onChange, placeholder, type, className, style }: TextInputProps): import("react").JSX.Element;
29
+ export interface TextAreaProps extends StyleProps {
30
+ value: string;
31
+ onChange: (value: string) => void;
32
+ rows?: number;
33
+ }
34
+ export declare function TextArea({ value, onChange, rows, className, style }: TextAreaProps): import("react").JSX.Element;
35
+ export interface NumberInputProps extends StyleProps {
36
+ value: unknown;
37
+ onChange: (value: number | '') => void;
38
+ unit?: string;
39
+ min?: number;
40
+ max?: number;
41
+ step?: number;
42
+ placeholder?: string;
43
+ }
44
+ /** Number with a unit suffix. Arrow keys step (Shift = ×10). Empty means "auto". */
45
+ export declare function NumberInput({ value, onChange, unit, min, max, step, placeholder, className, style }: NumberInputProps): import("react").JSX.Element;
46
+ export interface RangeInputProps extends StyleProps {
47
+ value: unknown;
48
+ onChange: (value: number) => void;
49
+ min: number;
50
+ max: number;
51
+ unit?: string;
52
+ }
53
+ export declare function RangeInput({ value, onChange, min, max, unit, className, style }: RangeInputProps): import("react").JSX.Element;
54
+ export declare const DEFAULT_SWATCHES: string[];
55
+ /** "#abc" / "#aabbcc" / "rgb(1, 2, 3)" -> "#aabbcc" (null when not a plain color). */
56
+ export declare function toHex(color: string): string | null;
57
+ export interface ColorInputProps extends StyleProps {
58
+ value: unknown;
59
+ onChange: (value: string) => void;
60
+ /** Colors already used in the document, offered first. */
61
+ presets?: string[];
62
+ /** Palette of the picker. */
63
+ swatches?: string[];
64
+ placeholder?: string;
65
+ /** Class name of the (portaled) picker popover. */
66
+ popoverClassName?: string;
67
+ }
68
+ /**
69
+ * Color field: swatch + hex text, opening a react-colorful picker in a Radix
70
+ * popover. The popover is portaled out of the sidebar, so it is wrapped in an
71
+ * EditorFocusScope: interacting with it keeps the block selected.
72
+ */
73
+ export declare function ColorInput({ value, onChange, presets, swatches, placeholder, className, style, popoverClassName, }: ColorInputProps): import("react").JSX.Element;
74
+ export interface SelectProps extends StyleProps {
75
+ value: string;
76
+ onChange: (value: string) => void;
77
+ /** [value, label] pairs. */
78
+ options: Array<[string, string]>;
79
+ }
80
+ export declare function Select({ value, onChange, options, className, style }: SelectProps): import("react").JSX.Element;
81
+ export interface SegmentedProps<T extends string> extends StyleProps {
82
+ value: T;
83
+ onChange: (value: T) => void;
84
+ options: Array<{
85
+ value: T;
86
+ label: ReactNode;
87
+ title?: string;
88
+ }>;
89
+ ariaLabel?: string;
90
+ }
91
+ export declare function Segmented<T extends string>({ value, onChange, options, ariaLabel, className, style }: SegmentedProps<T>): import("react").JSX.Element;
92
+ export interface AlignInputProps extends StyleProps {
93
+ value: string;
94
+ onChange: (value: string) => void;
95
+ }
96
+ export declare function AlignInput({ value, onChange, className, style }: AlignInputProps): import("react").JSX.Element;
97
+ export type Side = 'Top' | 'Right' | 'Bottom' | 'Left';
98
+ export interface PaddingInputProps extends StyleProps {
99
+ get: (side: Side) => unknown;
100
+ set: (changes: Array<[side: Side, value: number | '']>) => void;
101
+ }
102
+ /** One value for the four sides, or four values with "More options". */
103
+ export declare function PaddingInput({ get, set, className, style }: PaddingInputProps): import("react").JSX.Element;
@@ -0,0 +1,21 @@
1
+ /** Icons missing from @react-email/editor/ui. All accept a `size` like the package's icons. */
2
+ interface IconProps {
3
+ size?: number;
4
+ }
5
+ export declare const GripIcon: ({ size }: IconProps) => import("react").JSX.Element;
6
+ export declare const CopyIcon: ({ size }: IconProps) => import("react").JSX.Element;
7
+ export declare const TrashIcon: ({ size }: IconProps) => import("react").JSX.Element;
8
+ export declare const ParentIcon: ({ size }: IconProps) => import("react").JSX.Element;
9
+ export declare const UndoIcon: ({ size }: IconProps) => import("react").JSX.Element;
10
+ export declare const RedoIcon: ({ size }: IconProps) => import("react").JSX.Element;
11
+ export declare const DesktopIcon: ({ size }: IconProps) => import("react").JSX.Element;
12
+ export declare const MobileIcon: ({ size }: IconProps) => import("react").JSX.Element;
13
+ export declare const LayersIcon: ({ size }: IconProps) => import("react").JSX.Element;
14
+ export declare const PipetteIcon: ({ size }: IconProps) => import("react").JSX.Element;
15
+ /** Layers-panel spacer icon (small). */
16
+ export declare const SpacerIcon: ({ size }: IconProps) => import("react").JSX.Element;
17
+ /** Palette spacer icon (with arrows). */
18
+ export declare const SpacerTileIcon: ({ size }: IconProps) => import("react").JSX.Element;
19
+ export declare const SocialIcon: ({ size }: IconProps) => import("react").JSX.Element;
20
+ export declare const OneColumnIcon: ({ size }: IconProps) => import("react").JSX.Element;
21
+ export {};
@@ -0,0 +1,2 @@
1
+ import type { InspectorProps } from '../../registry/types';
2
+ export declare function ButtonInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type { InspectorProps } from '../../registry/types';
2
+ /** Rows of 2, 3 or 4 columns: width presets and gap. */
3
+ export declare function ColumnsInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import type { InspectorProps } from '../../registry/types';
2
+ /** Text-like blocks (paragraph, list, quote…) and any node without its own inspector. */
3
+ export declare function DefaultInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { InspectorProps } from '../../registry/types';
2
+ export declare function HeadingInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { InspectorProps } from '../../registry/types';
2
+ export declare function ImageInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import type { InspectorProps } from '../../registry/types';
2
+ export declare function SpacerInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
3
+ export declare function HtmlInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
4
+ export declare function DividerInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
5
+ /** Sections and columns: background, border and padding. */
6
+ export declare function ContainerInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import type { InspectorProps } from '../../registry/types';
2
+ export declare function SocialLinksInspector({ ctx, className, style }: InspectorProps): import("react").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import type { InspectorNodeContext } from '@react-email/editor/ui';
2
+ import type { KnownCssProperties } from '@react-email/editor/plugins';
3
+ import type { StyleProps } from '../../core/cx';
4
+ /** Reusable groups of controls, shared by the built-in inspectors. */
5
+ export declare const css: (prop: string) => KnownCssProperties;
6
+ export type StyleContext = Pick<InspectorNodeContext, 'getStyle' | 'setStyle' | 'presetColors'>;
7
+ export interface TypographyGroupProps extends StyleProps {
8
+ ctx: StyleContext;
9
+ alignment?: string;
10
+ /** Shows the alignment control when set. */
11
+ setAlignment?: (value: string) => void;
12
+ }
13
+ export declare function TypographyGroup({ ctx, alignment, setAlignment, className, style }: TypographyGroupProps): import("react").JSX.Element;
14
+ export interface SpacingGroupProps extends StyleProps {
15
+ ctx: InspectorNodeContext;
16
+ title?: string;
17
+ }
18
+ export declare function SpacingGroup({ ctx, title, className, style }: SpacingGroupProps): import("react").JSX.Element;
19
+ export interface BoxGroupProps extends StyleProps {
20
+ ctx: InspectorNodeContext;
21
+ }
22
+ export declare function BoxGroup({ ctx, className, style }: BoxGroupProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import type { JSONContent } from '@tiptap/core';
2
+ import type { DragEvent } from 'react';
3
+ /**
4
+ * Makes any element a source of new blocks: drag it onto the canvas or the
5
+ * layers panel, or click it to append the blocks at the end of the email.
6
+ *
7
+ * ```tsx
8
+ * const drag = useDraggableBlock('Promo', () => [paragraph('-20% today')]);
9
+ * return <button {...drag}>Promo</button>;
10
+ * ```
11
+ */
12
+ export declare function useDraggableBlock(label: string, content: () => JSONContent[]): {
13
+ draggable: boolean;
14
+ onDragStart: (event: DragEvent) => void;
15
+ onDragEnd: () => void;
16
+ onClick: () => void;
17
+ };
@@ -0,0 +1,115 @@
1
+ import type { Editor, Extensions, JSONContent } from '@tiptap/core';
2
+ import { type EditorThemeInput } from '@react-email/editor/plugins';
3
+ import { type ReactNode } from 'react';
4
+ import { type StyleProps } from './core/cx';
5
+ import { type DragSession, type HoverStore } from './core/stores';
6
+ import { type I18n, type Messages, type PartialMessages } from './i18n';
7
+ import type { NodeDefinition, PaletteGroup, PaletteItem, TemplateItem } from './registry/types';
8
+ export interface EmailSettings {
9
+ /** Inbox preview line (shown after the subject). */
10
+ previewText: string;
11
+ }
12
+ /** What the editor saves and loads: the document plus email-level settings. */
13
+ export interface EmailValue {
14
+ doc: JSONContent;
15
+ settings: EmailSettings;
16
+ }
17
+ export type Device = 'desktop' | 'mobile';
18
+ export interface EmailExport {
19
+ html: string;
20
+ text: string;
21
+ unformattedHtml: string;
22
+ }
23
+ /** Imperative API exposed through `ref` (and given to `onReady`). */
24
+ export interface EmailEditorHandle {
25
+ /** The underlying Tiptap editor. */
26
+ editor: Editor | null;
27
+ getValue: () => EmailValue;
28
+ setValue: (value: EmailValue | JSONContent) => void;
29
+ getJSON: () => JSONContent;
30
+ /** Renders the email (HTML, plain text and unformatted HTML). */
31
+ exportEmail: () => Promise<EmailExport>;
32
+ getHtml: () => Promise<string>;
33
+ getText: () => Promise<string>;
34
+ /** Appends blocks at the end of the email. */
35
+ insertBlocks: (content: JSONContent[]) => void;
36
+ }
37
+ export interface EmailEditorContextValue extends I18n {
38
+ editor: Editor;
39
+ handle: EmailEditorHandle;
40
+ /** Node definitions, by type. */
41
+ nodes: ReadonlyMap<string, NodeDefinition>;
42
+ nodeLabel: (type: string) => string;
43
+ palette: PaletteItem[];
44
+ paletteGroups: PaletteGroup[];
45
+ templates: TemplateItem[];
46
+ starterDocument: (i18n: I18n) => JSONContent;
47
+ uploadImage: (file: File) => Promise<{
48
+ url: string;
49
+ }>;
50
+ dragSession: DragSession;
51
+ hoverStore: HoverStore;
52
+ device: Device;
53
+ setDevice: (device: Device) => void;
54
+ layersOpen: boolean;
55
+ setLayersOpen: (open: boolean) => void;
56
+ settings: EmailSettings;
57
+ updateSettings: (patch: Partial<EmailSettings>) => void;
58
+ }
59
+ /** Everything the editor components share: editor, i18n, registries, UI state. */
60
+ export declare function useEmailEditor(): EmailEditorContextValue;
61
+ /** Like `useEmailEditor`, but returns null outside an editor. */
62
+ export declare function useOptionalEmailEditor(): EmailEditorContextValue | null;
63
+ /** UI strings, falling back to English outside an editor (lets form fields work standalone). */
64
+ export declare function useMessages(): Messages;
65
+ /** Current locale and messages. */
66
+ export declare function useI18n(): I18n;
67
+ export interface EditorRootProps extends StyleProps {
68
+ /** Initial content, read on mount. Use the ref's `setValue` to replace it later. */
69
+ defaultValue?: EmailValue | JSONContent;
70
+ /** Called on every document or settings change. */
71
+ onChange?: (value: EmailValue) => void;
72
+ /** Called once the editor is created. */
73
+ onReady?: (handle: EmailEditorHandle) => void;
74
+ /** "en" (default) or "fr". Any other value falls back to English unless `messages` covers it. */
75
+ locale?: string;
76
+ /** Overrides some or all UI strings. */
77
+ messages?: PartialMessages;
78
+ /** Node definitions (labels, icons, properties panels, custom extensions). Read on mount for extensions. */
79
+ nodes?: NodeDefinition[];
80
+ /** Tiles of the "Content" tab. */
81
+ palette?: PaletteItem[];
82
+ paletteGroups?: PaletteGroup[];
83
+ /** Prebuilt rows of the "Blocks" tab. */
84
+ templates?: TemplateItem[];
85
+ /** Content loaded by the top bar's "Template" button. */
86
+ starterDocument?: (i18n: I18n) => JSONContent;
87
+ /** Extra Tiptap extensions, read on mount. */
88
+ extensions?: Extensions;
89
+ /** Email theme used for new documents, read on mount. */
90
+ theme?: EditorThemeInput;
91
+ /** Stores an uploaded or pasted image and returns its public URL. Defaults to an inline data URL. */
92
+ uploadImage?: (file: File) => Promise<{
93
+ url: string;
94
+ }>;
95
+ editable?: boolean;
96
+ /** Canvas width, controlled. */
97
+ device?: Device;
98
+ defaultDevice?: Device;
99
+ onDeviceChange?: (device: Device) => void;
100
+ /** Layers panel visibility, controlled. */
101
+ layersOpen?: boolean;
102
+ defaultLayersOpen?: boolean;
103
+ onLayersOpenChange?: (open: boolean) => void;
104
+ children?: ReactNode;
105
+ }
106
+ export declare const defaultTheme: EditorThemeInput;
107
+ /** Inlines the file as a data URL. Replace with your own storage (S3, Cloudinary…). */
108
+ export declare const readFileAsDataUrl: (file: File) => Promise<{
109
+ url: string;
110
+ }>;
111
+ /**
112
+ * Creates the editor and provides it to every component inside: `Canvas`,
113
+ * `TopBar`, `LayersPanel`, `Sidebar`… Lay them out however you like.
114
+ */
115
+ export declare const EditorRoot: import("react").ForwardRefExoticComponent<EditorRootProps & import("react").RefAttributes<EmailEditorHandle>>;
@@ -0,0 +1,28 @@
1
+ import type { JSONContent } from '@tiptap/core';
2
+ /**
3
+ * Small helpers to build email JSON (the editor's document format).
4
+ * Handy to write palette items, templates or starter documents.
5
+ */
6
+ type Attrs = Record<string, unknown>;
7
+ export declare const text: (value: string, marks?: JSONContent["marks"]) => JSONContent;
8
+ export declare const paragraph: (value?: string | JSONContent[], attrs?: Attrs) => JSONContent;
9
+ export declare const heading: (level: 1 | 2 | 3, value: string, attrs?: Attrs) => JSONContent;
10
+ export declare const button: (label: string, attrs?: Attrs) => JSONContent;
11
+ export declare const image: (src: string, attrs?: Attrs) => JSONContent;
12
+ export declare const column: (...content: JSONContent[]) => JSONContent;
13
+ /** Sets a column's width, in percent of its row. */
14
+ export declare const sized: (col: JSONContent, width: number) => JSONContent;
15
+ export declare const columns: (count: 2 | 3 | 4, cols?: JSONContent[], attrs?: Attrs) => JSONContent;
16
+ export declare const section: (style: string, ...content: JSONContent[]) => JSONContent;
17
+ /** Longhand paddings keep the inspector's per-side controls accurate. */
18
+ export declare const padding: (y: number, x?: number) => string;
19
+ export declare const link: (href: string) => {
20
+ type: string;
21
+ attrs: {
22
+ href: string;
23
+ };
24
+ }[];
25
+ export declare const placeholderImage: (w: number, h: number, label?: string) => string;
26
+ /** Wraps blocks into a full document. */
27
+ export declare const doc: (...content: JSONContent[]) => JSONContent;
28
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { CSSProperties } from 'react';
2
+ /** Joins class names, skipping falsy values. */
3
+ export declare function cx(...classes: Array<string | false | null | undefined>): string;
4
+ /** Props accepted by every visual component of the library. */
5
+ export interface StyleProps {
6
+ className?: string;
7
+ style?: CSSProperties;
8
+ }