trance-richtext-editor 0.2.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 peterkyle01
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # trance-richtext-editor
2
+
3
+ A plug-and-play rich text editor for React, powered by [Lexical](https://lexical.dev/). Drop in a single component, get a production-quality editor with HTML output and a matching renderer.
4
+
5
+ Inspired by [Payload CMS's rich text editor](https://payloadcms.com/docs/fields/rich-text), extracted for standalone use — no CMS dependency required.
6
+
7
+ ## Features
8
+
9
+ - 🎨 **Beautiful out of the box** — polished toolbar, floating formatting bar, dark mode
10
+ - ⚡ **Plug and play** — single `<TranceEditor />` component, zero config needed
11
+ - 📤 **Dual output** — get both HTML strings and Lexical JSON from `onChange`
12
+ - 🖼️ **Rich content** — images, tables, code blocks, checklists, blockquotes, horizontal rules
13
+ - 🎯 **Feature flags** — enable/disable any formatting feature via props
14
+ - 🎭 **Theming** — light, dark, and auto (system preference) themes via CSS custom properties
15
+ - 📐 **TranceRenderer** — separate, lightweight component to beautifully render editor HTML
16
+ - 📄 **Page sizes** — constrain renderer output to A4, Letter, and other standard formats
17
+ - 🔒 **XSS-safe** — renderer sanitizes HTML via DOMPurify
18
+ - 📦 **Tree-shakeable** — ESM + CJS dual output, renderer has no Lexical dependency
19
+ - ⌨️ **Markdown shortcuts** — type `# `, `**text**`, `- `, etc. for quick formatting
20
+ - 🔧 **Ref API** — programmatically get/set HTML, JSON, focus, and clear
21
+ - 📝 **TypeScript** — fully typed with exported interfaces
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install trance-richtext-editor
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ ### Editor
32
+
33
+ ```tsx
34
+ import { TranceEditor } from 'trance-richtext-editor';
35
+ import 'trance-richtext-editor/styles.css';
36
+
37
+ function MyEditor() {
38
+ return (
39
+ <TranceEditor
40
+ placeholder="Write something amazing..."
41
+ onChange={({ html, json }) => {
42
+ console.log('HTML:', html);
43
+ console.log('JSON:', json);
44
+ }}
45
+ />
46
+ );
47
+ }
48
+ ```
49
+
50
+ ### Renderer
51
+
52
+ ```tsx
53
+ import { TranceRenderer } from 'trance-richtext-editor/renderer';
54
+ import 'trance-richtext-editor/styles.css';
55
+
56
+ function BlogPost({ content }: { content: string }) {
57
+ return <TranceRenderer html={content} theme="dark" />;
58
+ }
59
+ ```
60
+
61
+ ## Props
62
+
63
+ ### `<TranceEditor />`
64
+
65
+ | Prop | Type | Default | Description |
66
+ |------|------|---------|-------------|
67
+ | `initialHtml` | `string` | — | Initialize editor from HTML |
68
+ | `initialJson` | `SerializedEditorState` | — | Initialize from Lexical JSON |
69
+ | `placeholder` | `string` | `"Start writing..."` | Placeholder text |
70
+ | `onChange` | `(data: { html, json }) => void` | — | Content change callback (debounced) |
71
+ | `onBlur` | `() => void` | — | Blur callback |
72
+ | `onFocus` | `() => void` | — | Focus callback |
73
+ | `features` | `ToolbarFeatures` | all enabled | Feature flags object |
74
+ | `onImageUpload` | `(file: File) => Promise<{ url, alt? }>` | base64 fallback | Custom image upload handler |
75
+ | `theme` | `'light' \| 'dark' \| 'auto'` | `'light'` | Theme mode |
76
+ | `className` | `string` | — | Additional CSS class |
77
+ | `editable` | `boolean` | `true` | Read-only mode |
78
+ | `autoFocus` | `boolean` | `false` | Auto-focus on mount |
79
+ | `maxLength` | `number` | — | Character limit |
80
+ | `debounceMs` | `number` | `300` | Debounce ms for onChange |
81
+
82
+ ### Feature Flags
83
+
84
+ All features are enabled by default. Disable any via the `features` prop:
85
+
86
+ ```tsx
87
+ <TranceEditor
88
+ features={{
89
+ table: false,
90
+ image: false,
91
+ checkList: false,
92
+ }}
93
+ />
94
+ ```
95
+
96
+ Available flags: `bold`, `italic`, `underline`, `strikethrough`, `code`, `link`, `orderedList`, `unorderedList`, `checkList`, `blockquote`, `codeBlock`, `image`, `table`, `horizontalRule`, `heading`, `textAlign`, `superscript`, `subscript`, `highlight`
97
+
98
+ ### Ref API
99
+
100
+ ```tsx
101
+ import { useRef } from 'react';
102
+ import { TranceEditor, TranceEditorRef } from 'trance-richtext-editor';
103
+
104
+ function MyEditor() {
105
+ const editorRef = useRef<TranceEditorRef>(null);
106
+
107
+ return (
108
+ <>
109
+ <TranceEditor ref={editorRef} />
110
+ <button onClick={() => console.log(editorRef.current?.getHtml())}>
111
+ Get HTML
112
+ </button>
113
+ <button onClick={() => editorRef.current?.clear()}>
114
+ Clear
115
+ </button>
116
+ </>
117
+ );
118
+ }
119
+ ```
120
+
121
+ ### `<TranceRenderer />`
122
+
123
+ | Prop | Type | Default | Description |
124
+ |------|------|---------|-------------|
125
+ | `html` | `string` | — | HTML string to render |
126
+ | `className` | `string` | — | Additional CSS class |
127
+ | `theme` | `'light' \| 'dark' \| 'auto'` | `'light'` | Theme mode |
128
+ | `pageSize` | `PageSize` | — | Constrain content to a standard page size |
129
+
130
+ **`PageSize` options:** `'A3'`, `'A4'`, `'A5'`, `'Letter'`, `'Legal'`, `'Tabloid'`
131
+
132
+ When `pageSize` is set, the renderer centers itself with a paper-like background and shadow:
133
+
134
+ ```tsx
135
+ <TranceRenderer html={content} pageSize="A4" />
136
+ ```
137
+
138
+ ## Theming
139
+
140
+ Override any CSS custom property to customize the look:
141
+
142
+ ```css
143
+ [data-trance-theme="light"] {
144
+ --trance-accent: #8b5cf6; /* Purple accent */
145
+ --trance-font-sans: 'Outfit', sans-serif;
146
+ --trance-radius-md: 12px;
147
+ }
148
+ ```
149
+
150
+ ## Server-Side Utilities
151
+
152
+ Convert between formats on the server (API routes, SSR, email templates):
153
+
154
+ ```ts
155
+ import { convertJsonToHtml, convertHtmlToJson } from 'trance-richtext-editor';
156
+
157
+ // JSON → HTML
158
+ const html = convertJsonToHtml(savedEditorState);
159
+
160
+ // HTML → JSON
161
+ const json = convertHtmlToJson('<p>Hello <strong>world</strong></p>');
162
+ ```
163
+
164
+ ## Image Upload
165
+
166
+ Provide a custom upload handler, or images will be base64-encoded by default:
167
+
168
+ ```tsx
169
+ <TranceEditor
170
+ onImageUpload={async (file) => {
171
+ const formData = new FormData();
172
+ formData.append('file', file);
173
+ const res = await fetch('/api/upload', { method: 'POST', body: formData });
174
+ const { url } = await res.json();
175
+ return { url, alt: file.name };
176
+ }}
177
+ />
178
+ ```
179
+
180
+ ## Browser Support
181
+
182
+ | Browser | Version |
183
+ |---------|---------|
184
+ | Chrome | 90+ |
185
+ | Firefox | 90+ |
186
+ | Safari | 15+ |
187
+ | Edge | 90+ |
188
+
189
+ ## License
190
+
191
+ MIT © [peterkyle01](https://github.com/peterkyle01)