bootstrap-email-wysiwyg 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.
- package/LICENSE +21 -0
- package/README.md +374 -0
- package/dist/bootstrap-email-wysiwyg.cjs +18 -0
- package/dist/bootstrap-email-wysiwyg.css +1 -0
- package/dist/bootstrap-email-wysiwyg.js +1957 -0
- package/dist/index.d.ts +483 -0
- package/package.json +73 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import { DecoratorNode } from 'lexical';
|
|
2
|
+
import { DOMConversionMap } from 'lexical';
|
|
3
|
+
import { DOMExportOutput } from 'lexical';
|
|
4
|
+
import { EditorConfig } from 'lexical';
|
|
5
|
+
import { EditorThemeClasses } from 'lexical';
|
|
6
|
+
import { ElementFormatType } from 'lexical';
|
|
7
|
+
import { ElementNode } from 'lexical';
|
|
8
|
+
import { ForwardRefExoticComponent } from 'react';
|
|
9
|
+
import { JSX as JSX_2 } from 'react';
|
|
10
|
+
import { LexicalEditor } from 'lexical';
|
|
11
|
+
import { LexicalNode } from 'lexical';
|
|
12
|
+
import { NodeKey } from 'lexical';
|
|
13
|
+
import { ParagraphNode } from 'lexical';
|
|
14
|
+
import { ReactNode } from 'react';
|
|
15
|
+
import { RefAttributes } from 'react';
|
|
16
|
+
import { SerializedElementNode } from 'lexical';
|
|
17
|
+
import { SerializedLexicalNode } from 'lexical';
|
|
18
|
+
import { SerializedParagraphNode } from 'lexical';
|
|
19
|
+
import { Spread } from 'lexical';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Step the font size up or down one notch. Replaces any existing size (never
|
|
23
|
+
* stacks) and treats "no size" as base. Targets, in order:
|
|
24
|
+
* - cursor inside a button → the button (inline font-size),
|
|
25
|
+
* - collapsed selection → the enclosing block (text-* class),
|
|
26
|
+
* - non-empty text selection → the selected text (span, text-* class).
|
|
27
|
+
* Must run inside an `editor.update()`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function $adjustFontSize(direction: FontSizeDirection): void;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Apply a color following the target rules. Must be called inside an
|
|
33
|
+
* `editor.update()` (hence the `$` prefix):
|
|
34
|
+
* - cursor inside a button → the button node,
|
|
35
|
+
* - collapsed selection → the enclosing block (parent element),
|
|
36
|
+
* - non-empty text selection → the selected text (inline span).
|
|
37
|
+
*/
|
|
38
|
+
export declare function $applyColor(kind: ColorKind, token: string | null): void;
|
|
39
|
+
|
|
40
|
+
export declare function $createButtonNode(payload?: ButtonPayload): ButtonNode;
|
|
41
|
+
|
|
42
|
+
/** Create a button already populated with a text label. */
|
|
43
|
+
export declare function $createButtonWithLabel(label: string, payload?: ButtonPayload): ButtonNode;
|
|
44
|
+
|
|
45
|
+
export declare function $createHrNode(payload?: HrPayload): HrNode;
|
|
46
|
+
|
|
47
|
+
export declare function $createImageNode(payload: ImagePayload): ImageNode;
|
|
48
|
+
|
|
49
|
+
export declare function $isButtonNode(node: LexicalNode | null | undefined): node is ButtonNode;
|
|
50
|
+
|
|
51
|
+
export declare function $isHrNode(node: LexicalNode | null | undefined): node is HrNode;
|
|
52
|
+
|
|
53
|
+
export declare function $isImageNode(node: LexicalNode | null | undefined): node is ImageNode;
|
|
54
|
+
|
|
55
|
+
export declare function addCustomColor(hex: string): void;
|
|
56
|
+
|
|
57
|
+
/** Convenience wrapper that runs {@link $adjustFontSize} in an editor update. */
|
|
58
|
+
export declare function adjustFontSize(editor: LexicalEditor, direction: FontSizeDirection): void;
|
|
59
|
+
|
|
60
|
+
export declare type Align = "left" | "center" | "right" | "justify";
|
|
61
|
+
|
|
62
|
+
/** Convenience wrapper that runs {@link $applyColor} in an editor update. */
|
|
63
|
+
export declare function applyColor(editor: LexicalEditor, kind: ColorKind, token: string | null): void;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Bootstrap Email horizontal-alignment class for block content (buttons,
|
|
67
|
+
* images). `justify` is meaningless here, so it yields no class.
|
|
68
|
+
*/
|
|
69
|
+
export declare function axAlignClass(format: ElementFormatType): string | null;
|
|
70
|
+
|
|
71
|
+
/** Contextual + absolute colors shown as the top row of the picker. */
|
|
72
|
+
export declare const BASE_COLORS: Swatch[];
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The root WYSIWYG editor component: a rich-text surface with a Quill-style
|
|
76
|
+
* toolbar (inline formatting, font sizing, colors, image / button / separator
|
|
77
|
+
* insertion) and undo/redo history. Every block is a Bootstrap Email `<div>`.
|
|
78
|
+
*
|
|
79
|
+
* Get content out via `onChange` or the imperative `ref`; seed it with
|
|
80
|
+
* `initialContent`.
|
|
81
|
+
*/
|
|
82
|
+
export declare const BootstrapEmailEditor: ForwardRefExoticComponent<BootstrapEmailEditorProps & RefAttributes<BootstrapEmailEditorHandle>>;
|
|
83
|
+
|
|
84
|
+
/** Imperative handle exposed via `ref`. */
|
|
85
|
+
export declare interface BootstrapEmailEditorHandle {
|
|
86
|
+
/** Export Bootstrap Email HTML (fragment by default; pass `{ document: true }`). */
|
|
87
|
+
getHtml: (options?: BootstrapEmailHtmlOptions) => string;
|
|
88
|
+
/** Serialized editor state JSON, suitable for `initialContent`. */
|
|
89
|
+
getJson: () => string;
|
|
90
|
+
focus: () => void;
|
|
91
|
+
/** Remove all content. */
|
|
92
|
+
clear: () => void;
|
|
93
|
+
/** The underlying Lexical editor, for advanced use. */
|
|
94
|
+
getEditor: () => LexicalEditor | null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export declare interface BootstrapEmailEditorProps {
|
|
98
|
+
/** Placeholder text shown when the editor is empty. */
|
|
99
|
+
placeholder?: string;
|
|
100
|
+
/** Show the built-in formatting toolbar. Defaults to true. */
|
|
101
|
+
toolbar?: boolean;
|
|
102
|
+
/** Seed the editor from a serialized state (as produced by `getJson`). */
|
|
103
|
+
initialContent?: string;
|
|
104
|
+
/** Called on every edit with the current HTML + serialized state. */
|
|
105
|
+
onChange?: (change: EditorChange) => void;
|
|
106
|
+
/** Called when Lexical throws during an update. */
|
|
107
|
+
onError?: (error: Error) => void;
|
|
108
|
+
/**
|
|
109
|
+
* Extra Lexical plugins/components rendered inside the composer, so they
|
|
110
|
+
* have access to the editor context.
|
|
111
|
+
*/
|
|
112
|
+
children?: ReactNode;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export declare interface BootstrapEmailHtmlOptions {
|
|
116
|
+
/** Wrap the content in a full HTML email document. Default: false (fragment). */
|
|
117
|
+
document?: boolean;
|
|
118
|
+
/** Pretty-print with indentation. Default: true. */
|
|
119
|
+
pretty?: boolean;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Maps Lexical node types to CSS class names. These classes are styled in
|
|
124
|
+
* `editor.css`. Keeping the theme separate lets consumers override styling
|
|
125
|
+
* without touching editor logic.
|
|
126
|
+
*/
|
|
127
|
+
export declare const bootstrapEmailTheme: EditorThemeClasses;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* A paragraph that exports as a Bootstrap Email `<div>` line rather than a
|
|
131
|
+
* `<p>`. Alignment becomes a `text-*` class (or `ax-*` when the block's content
|
|
132
|
+
* is a button), and block-level text/background colors become `text-*` / `bg-*`
|
|
133
|
+
* classes (or inline styles for custom colors).
|
|
134
|
+
*/
|
|
135
|
+
export declare class BootstrapParagraphNode extends ParagraphNode {
|
|
136
|
+
__textColor: string | null;
|
|
137
|
+
__bgColor: string | null;
|
|
138
|
+
__fontSize: string | null;
|
|
139
|
+
constructor(textColor?: string | null, bgColor?: string | null, fontSize?: string | null, key?: string);
|
|
140
|
+
static getType(): string;
|
|
141
|
+
static clone(node: BootstrapParagraphNode): BootstrapParagraphNode;
|
|
142
|
+
static importJSON(serializedNode: SerializedBootstrapParagraphNode): BootstrapParagraphNode;
|
|
143
|
+
exportJSON(): SerializedBootstrapParagraphNode;
|
|
144
|
+
getFontSize(): string | null;
|
|
145
|
+
setFontSize(key: string | null): this;
|
|
146
|
+
getTextColor(): string | null;
|
|
147
|
+
setTextColor(token: string | null): this;
|
|
148
|
+
getBgColor(): string | null;
|
|
149
|
+
setBgColor(token: string | null): this;
|
|
150
|
+
private applyInlineStyles;
|
|
151
|
+
createDOM(config: EditorConfig): HTMLElement;
|
|
152
|
+
updateDOM(prevNode: BootstrapParagraphNode, dom: HTMLElement, config: EditorConfig): boolean;
|
|
153
|
+
private hasButtonChild;
|
|
154
|
+
exportDOM(): DOMExportOutput;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* A Bootstrap Email button, authored in source as
|
|
159
|
+
* `<a href="…" class="btn btn-primary">Label</a>`. Modeled as an inline
|
|
160
|
+
* element so the label text is edited natively, while href / color variant /
|
|
161
|
+
* outline are node properties.
|
|
162
|
+
*/
|
|
163
|
+
export declare class ButtonNode extends ElementNode {
|
|
164
|
+
__href: string;
|
|
165
|
+
__variant: ButtonVariant;
|
|
166
|
+
__outline: boolean;
|
|
167
|
+
__textColor: string | null;
|
|
168
|
+
__bgColor: string | null;
|
|
169
|
+
__borderColor: string | null;
|
|
170
|
+
__fontSize: string | null;
|
|
171
|
+
static getType(): string;
|
|
172
|
+
static clone(node: ButtonNode): ButtonNode;
|
|
173
|
+
constructor(href?: string, variant?: ButtonVariant, outline?: boolean, textColor?: string | null, bgColor?: string | null, borderColor?: string | null, fontSize?: string | null, key?: string);
|
|
174
|
+
private variantClass;
|
|
175
|
+
private buildClassName;
|
|
176
|
+
private applyInlineStyles;
|
|
177
|
+
createDOM(_config: EditorConfig): HTMLElement;
|
|
178
|
+
updateDOM(prevNode: ButtonNode, dom: HTMLElement): boolean;
|
|
179
|
+
static importDOM(): DOMConversionMap | null;
|
|
180
|
+
exportDOM(): DOMExportOutput;
|
|
181
|
+
static importJSON(serializedNode: SerializedButtonNode): ButtonNode;
|
|
182
|
+
exportJSON(): SerializedButtonNode;
|
|
183
|
+
getHref(): string;
|
|
184
|
+
setHref(href: string): this;
|
|
185
|
+
getVariant(): ButtonVariant;
|
|
186
|
+
setVariant(variant: ButtonVariant): this;
|
|
187
|
+
getOutline(): boolean;
|
|
188
|
+
setOutline(outline: boolean): this;
|
|
189
|
+
getTextColor(): string | null;
|
|
190
|
+
setTextColor(token: string | null): this;
|
|
191
|
+
getBgColor(): string | null;
|
|
192
|
+
setBgColor(token: string | null): this;
|
|
193
|
+
getBorderColor(): string | null;
|
|
194
|
+
setBorderColor(token: string | null): this;
|
|
195
|
+
getFontSize(): string | null;
|
|
196
|
+
setFontSize(key: string | null): this;
|
|
197
|
+
isInline(): boolean;
|
|
198
|
+
canBeEmpty(): boolean;
|
|
199
|
+
canInsertTextBefore(): boolean;
|
|
200
|
+
canInsertTextAfter(): boolean;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export declare interface ButtonPayload {
|
|
204
|
+
href?: string;
|
|
205
|
+
variant?: ButtonVariant;
|
|
206
|
+
outline?: boolean;
|
|
207
|
+
textColor?: string | null;
|
|
208
|
+
bgColor?: string | null;
|
|
209
|
+
borderColor?: string | null;
|
|
210
|
+
fontSize?: string | null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** The full visual styling of a button, minus href/label. */
|
|
214
|
+
export declare interface ButtonStyle {
|
|
215
|
+
variant: ButtonVariant;
|
|
216
|
+
outline: boolean;
|
|
217
|
+
textColor: string | null;
|
|
218
|
+
bgColor: string | null;
|
|
219
|
+
borderColor: string | null;
|
|
220
|
+
fontSize: string | null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Bootstrap contextual color variants supported by Bootstrap Email buttons. */
|
|
224
|
+
export declare type ButtonVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Clean Lexical's raw HTML export into Bootstrap Email source (class-based,
|
|
228
|
+
* span-free). Browser-only (uses the DOM).
|
|
229
|
+
*/
|
|
230
|
+
export declare function cleanBootstrapHtml(rawHtml: string, pretty?: boolean): string;
|
|
231
|
+
|
|
232
|
+
export declare const COLOR_FAMILIES: ColorFamily[];
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Resolve a text/bg color token into the classes and inline styles needed on
|
|
236
|
+
* an exported element (palette → class, custom → inline style).
|
|
237
|
+
*/
|
|
238
|
+
export declare function colorAttributes(textToken?: string | null, bgToken?: string | null, borderToken?: string | null): {
|
|
239
|
+
classes: string[];
|
|
240
|
+
style: string;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export declare interface ColorFamily {
|
|
244
|
+
name: string;
|
|
245
|
+
/** Shades ordered light → dark (100 → 900). */
|
|
246
|
+
shades: {
|
|
247
|
+
shade: number;
|
|
248
|
+
token: string;
|
|
249
|
+
hex: string;
|
|
250
|
+
}[];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export declare type ColorKind = "text" | "bg" | "border";
|
|
254
|
+
|
|
255
|
+
export declare function ColorPicker({ onSelect }: ColorPickerProps): JSX_2.Element;
|
|
256
|
+
|
|
257
|
+
declare interface ColorPickerProps {
|
|
258
|
+
/** Called with a palette token, a custom "#hex", or null to clear color. */
|
|
259
|
+
onSelect: (token: string | null) => void;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** A plain `<hr>` has 20px top/bottom spacing; mt-5 / mb-5 = 20px. */
|
|
263
|
+
export declare const DEFAULT_HR_MARGIN = "5";
|
|
264
|
+
|
|
265
|
+
/** Payload passed to `onChange` on every edit. */
|
|
266
|
+
export declare interface EditorChange {
|
|
267
|
+
/** Bootstrap Email source HTML (content fragment). */
|
|
268
|
+
html: string;
|
|
269
|
+
/** Serialized editor state, for persistence / `initialContent`. */
|
|
270
|
+
json: string;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export declare const FONT_SIZE_KEYS: readonly ["xs", "sm", "base", "lg", "xl", "2xl", "3xl", "4xl", "5xl", "6xl", "7xl"];
|
|
274
|
+
|
|
275
|
+
/** Class for a size key, or null for the default ("base"). */
|
|
276
|
+
export declare function fontSizeClass(key: string | null | undefined): string | null;
|
|
277
|
+
|
|
278
|
+
export declare type FontSizeDirection = "increase" | "decrease";
|
|
279
|
+
|
|
280
|
+
export declare type FontSizeKey = (typeof FONT_SIZE_KEYS)[number];
|
|
281
|
+
|
|
282
|
+
export declare function fontSizePx(key: FontSizeKey): number;
|
|
283
|
+
|
|
284
|
+
export declare function getCustomColors(): string[];
|
|
285
|
+
|
|
286
|
+
export declare function getLastButtonStyle(): ButtonStyle;
|
|
287
|
+
|
|
288
|
+
/** Reverse a rendered hex back to a palette token, or null if not in palette. */
|
|
289
|
+
export declare function hexToToken(hex: string): string | null;
|
|
290
|
+
|
|
291
|
+
/** Classes for an HR's spacing — separate `mt-` / `mb-` rather than `my-`. */
|
|
292
|
+
export declare function hrClasses(top: string, bottom: string): string[];
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* A Bootstrap Email horizontal rule (`<hr>`) with configurable top/bottom
|
|
296
|
+
* spacing (`mt-*` / `mb-*`). Rendered as a decorator for the settings overlay.
|
|
297
|
+
*/
|
|
298
|
+
export declare class HrNode extends DecoratorNode<ReactNode> {
|
|
299
|
+
__top: string;
|
|
300
|
+
__bottom: string;
|
|
301
|
+
static getType(): string;
|
|
302
|
+
static clone(node: HrNode): HrNode;
|
|
303
|
+
constructor(top?: string, bottom?: string, key?: NodeKey);
|
|
304
|
+
static importJSON(serializedNode: SerializedHrNode): HrNode;
|
|
305
|
+
exportJSON(): SerializedHrNode;
|
|
306
|
+
static importDOM(): DOMConversionMap | null;
|
|
307
|
+
exportDOM(): DOMExportOutput;
|
|
308
|
+
getTop(): string;
|
|
309
|
+
setTop(top: string): this;
|
|
310
|
+
getBottom(): string;
|
|
311
|
+
setBottom(bottom: string): this;
|
|
312
|
+
createDOM(): HTMLElement;
|
|
313
|
+
updateDOM(): boolean;
|
|
314
|
+
isInline(): boolean;
|
|
315
|
+
decorate(): ReactNode;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export declare interface HrPayload {
|
|
319
|
+
top?: string;
|
|
320
|
+
bottom?: string;
|
|
321
|
+
key?: NodeKey;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** Bootstrap Email classes for an image's sizing. */
|
|
325
|
+
export declare function imageClasses(mode: ImageMode, width: string | null, height: string | null): string[];
|
|
326
|
+
|
|
327
|
+
export declare type ImageMode = "fluid" | "fixed" | "max";
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* A Bootstrap Email image (`<img>` from a URL). Sizing is one of three modes:
|
|
331
|
+
* fluid (`img-fluid`), fixed (`w-*`/`h-*`), or max-width (`max-w-* w-full`).
|
|
332
|
+
* Rendered as a decorator so the editor can show a settings (gear) overlay.
|
|
333
|
+
*/
|
|
334
|
+
export declare class ImageNode extends DecoratorNode<ReactNode> {
|
|
335
|
+
__src: string;
|
|
336
|
+
__alt: string;
|
|
337
|
+
__mode: ImageMode;
|
|
338
|
+
__width: string | null;
|
|
339
|
+
__height: string | null;
|
|
340
|
+
static getType(): string;
|
|
341
|
+
static clone(node: ImageNode): ImageNode;
|
|
342
|
+
constructor(src: string, alt?: string, mode?: ImageMode, width?: string | null, height?: string | null, key?: NodeKey);
|
|
343
|
+
static importJSON(serializedNode: SerializedImageNode): ImageNode;
|
|
344
|
+
exportJSON(): SerializedImageNode;
|
|
345
|
+
static importDOM(): DOMConversionMap | null;
|
|
346
|
+
exportDOM(): DOMExportOutput;
|
|
347
|
+
getSrc(): string;
|
|
348
|
+
setSrc(src: string): this;
|
|
349
|
+
getAlt(): string;
|
|
350
|
+
setAlt(alt: string): this;
|
|
351
|
+
getMode(): ImageMode;
|
|
352
|
+
setMode(mode: ImageMode): this;
|
|
353
|
+
getWidth(): string | null;
|
|
354
|
+
setWidth(width: string | null): this;
|
|
355
|
+
getHeight(): string | null;
|
|
356
|
+
setHeight(height: string | null): this;
|
|
357
|
+
createDOM(): HTMLElement;
|
|
358
|
+
updateDOM(): boolean;
|
|
359
|
+
isInline(): boolean;
|
|
360
|
+
decorate(): ReactNode;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export declare interface ImagePayload {
|
|
364
|
+
src: string;
|
|
365
|
+
alt?: string;
|
|
366
|
+
mode?: ImageMode;
|
|
367
|
+
width?: string | null;
|
|
368
|
+
height?: string | null;
|
|
369
|
+
key?: NodeKey;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Inline styles mirroring {@link imageClasses}, for live editor preview. */
|
|
373
|
+
export declare function imagePreviewStyle(mode: ImageMode, width: string | null, height: string | null): Record<string, string>;
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Insert a Bootstrap Email button at the current selection. No-op when there
|
|
377
|
+
* is no range selection (e.g. the editor isn't focused).
|
|
378
|
+
*/
|
|
379
|
+
export declare function insertButton(editor: LexicalEditor, options?: InsertButtonOptions): void;
|
|
380
|
+
|
|
381
|
+
export declare interface InsertButtonOptions extends ButtonPayload {
|
|
382
|
+
/** Text label for the button. Defaults to "Button". */
|
|
383
|
+
label?: string;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** Insert a horizontal rule (separator) as a block at the current selection. */
|
|
387
|
+
export declare function insertHr(editor: LexicalEditor, payload?: HrPayload): void;
|
|
388
|
+
|
|
389
|
+
/** Insert an image (from a URL) as a block at the current selection. */
|
|
390
|
+
export declare function insertImage(editor: LexicalEditor, payload: ImagePayload): void;
|
|
391
|
+
|
|
392
|
+
export declare const MARGIN_STEPS: MarginStep[];
|
|
393
|
+
|
|
394
|
+
export declare function marginKeyToPx(key: string | null): number;
|
|
395
|
+
|
|
396
|
+
export declare interface MarginStep {
|
|
397
|
+
key: string;
|
|
398
|
+
px: number;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** Collapse Lexical's element format into a Bootstrap Email alignment, or null. */
|
|
402
|
+
export declare function normalizeAlign(format: ElementFormatType): Align | null;
|
|
403
|
+
|
|
404
|
+
/** Match a pixel size back to a scale key, or null if off-scale. */
|
|
405
|
+
export declare function pxToFontSizeKey(px: number): FontSizeKey | null;
|
|
406
|
+
|
|
407
|
+
export declare function rememberButtonStyle(style: ButtonStyle): void;
|
|
408
|
+
|
|
409
|
+
export declare function removeCustomColor(hex: string): void;
|
|
410
|
+
|
|
411
|
+
declare type SerializedBootstrapParagraphNode = Spread<{
|
|
412
|
+
textColor: string | null;
|
|
413
|
+
bgColor: string | null;
|
|
414
|
+
fontSize: string | null;
|
|
415
|
+
}, SerializedParagraphNode>;
|
|
416
|
+
|
|
417
|
+
export declare type SerializedButtonNode = Spread<{
|
|
418
|
+
href: string;
|
|
419
|
+
variant: ButtonVariant;
|
|
420
|
+
outline: boolean;
|
|
421
|
+
textColor: string | null;
|
|
422
|
+
bgColor: string | null;
|
|
423
|
+
borderColor: string | null;
|
|
424
|
+
fontSize: string | null;
|
|
425
|
+
}, SerializedElementNode>;
|
|
426
|
+
|
|
427
|
+
export declare type SerializedHrNode = Spread<{
|
|
428
|
+
top: string;
|
|
429
|
+
bottom: string;
|
|
430
|
+
}, SerializedLexicalNode>;
|
|
431
|
+
|
|
432
|
+
export declare type SerializedImageNode = Spread<{
|
|
433
|
+
src: string;
|
|
434
|
+
alt: string;
|
|
435
|
+
mode: ImageMode;
|
|
436
|
+
width: string | null;
|
|
437
|
+
height: string | null;
|
|
438
|
+
}, SerializedLexicalNode>;
|
|
439
|
+
|
|
440
|
+
/** The discrete Bootstrap Email sizing scale (w-0 … w-150). */
|
|
441
|
+
export declare const SIZE_STEPS: SizeStep[];
|
|
442
|
+
|
|
443
|
+
export declare function sizeKeyToPx(key: string | null): number | null;
|
|
444
|
+
|
|
445
|
+
export declare interface SizeStep {
|
|
446
|
+
key: string;
|
|
447
|
+
px: number;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Step a size one notch up (+1) or down (-1) the scale, clamped at the ends.
|
|
452
|
+
* A null/unknown current size is treated as "base".
|
|
453
|
+
*/
|
|
454
|
+
export declare function stepFontSize(current: string | null | undefined, direction: 1 | -1): FontSizeKey;
|
|
455
|
+
|
|
456
|
+
export declare interface Swatch {
|
|
457
|
+
/** Token stored on nodes, e.g. "blue-500", "primary", or a custom "#a1b2c3". */
|
|
458
|
+
token: string;
|
|
459
|
+
hex: string;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/** Bootstrap Email text-alignment class for a block of inline text. */
|
|
463
|
+
export declare function textAlignClass(format: ElementFormatType): string | null;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Export the editor's content as Bootstrap Email source HTML — a content
|
|
467
|
+
* fragment by default, or a full email document with `{ document: true }`.
|
|
468
|
+
* Browser-only (uses the DOM). Feed the result to the bootstrap-email compiler.
|
|
469
|
+
*/
|
|
470
|
+
export declare function toBootstrapEmailHtml(editor: LexicalEditor, options?: BootstrapEmailHtmlOptions): string;
|
|
471
|
+
|
|
472
|
+
/** Bootstrap Email class for a palette token, or null for custom hex colors. */
|
|
473
|
+
export declare function tokenToClass(token: string, kind: ColorKind): string | null;
|
|
474
|
+
|
|
475
|
+
/** CSS color for live rendering. */
|
|
476
|
+
export declare function tokenToHex(token: string): string;
|
|
477
|
+
|
|
478
|
+
export declare function Toolbar(): JSX_2.Element;
|
|
479
|
+
|
|
480
|
+
/** React hook returning the live list of custom colors. */
|
|
481
|
+
export declare function useCustomColors(): string[];
|
|
482
|
+
|
|
483
|
+
export { }
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bootstrap-email-wysiwyg",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A Lexical-based WYSIWYG editor for building Bootstrap Email templates.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Süleyman Kenar <suleyman@kenar.net>",
|
|
8
|
+
"homepage": "https://github.com/kenarsuleyman/bootstrap-email-wysiwyg#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/kenarsuleyman/bootstrap-email-wysiwyg.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/kenarsuleyman/bootstrap-email-wysiwyg/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"lexical",
|
|
18
|
+
"wysiwyg",
|
|
19
|
+
"editor",
|
|
20
|
+
"bootstrap",
|
|
21
|
+
"email",
|
|
22
|
+
"react"
|
|
23
|
+
],
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"main": "./dist/bootstrap-email-wysiwyg.cjs",
|
|
28
|
+
"module": "./dist/bootstrap-email-wysiwyg.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/bootstrap-email-wysiwyg.js",
|
|
34
|
+
"require": "./dist/bootstrap-email-wysiwyg.cjs"
|
|
35
|
+
},
|
|
36
|
+
"./styles.css": "./dist/bootstrap-email-wysiwyg.css"
|
|
37
|
+
},
|
|
38
|
+
"sideEffects": [
|
|
39
|
+
"*.css"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"dev": "vite",
|
|
43
|
+
"build": "tsc --noEmit && vite build",
|
|
44
|
+
"preview": "vite preview",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"prepublishOnly": "npm run build"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"react": ">=18",
|
|
50
|
+
"react-dom": ">=18"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@lexical/react": "^0.36.2",
|
|
54
|
+
"@lexical/rich-text": "^0.36.2",
|
|
55
|
+
"@lexical/selection": "^0.36.2",
|
|
56
|
+
"@lexical/utils": "^0.36.2",
|
|
57
|
+
"lexical": "^0.36.2"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@lexical/headless": "^0.36.2",
|
|
61
|
+
"@lexical/html": "^0.36.2",
|
|
62
|
+
"@types/node": "^22.20.0",
|
|
63
|
+
"@types/react": "^18.3.12",
|
|
64
|
+
"@types/react-dom": "^18.3.1",
|
|
65
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
66
|
+
"jsdom": "^25.0.1",
|
|
67
|
+
"react": "^18.3.1",
|
|
68
|
+
"react-dom": "^18.3.1",
|
|
69
|
+
"typescript": "^5.7.2",
|
|
70
|
+
"vite": "^6.0.5",
|
|
71
|
+
"vite-plugin-dts": "^4.4.0"
|
|
72
|
+
}
|
|
73
|
+
}
|