ritext 1.0.28 → 1.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/README.md +65 -10
- package/dist/index.d.mts +23 -6
- package/dist/index.d.ts +23 -6
- package/dist/index.js +50 -3
- package/dist/index.mjs +51 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,16 +1,71 @@
|
|
|
1
|
-
<
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/logo/logo-white.png">
|
|
4
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/logo/logo-black.png">
|
|
5
|
+
<img alt="Ritext" src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/logo/logo-black.png" width="240">
|
|
6
|
+
</picture>
|
|
7
|
+
</p>
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
Ritext
|
|
9
|
+
<p align="center">
|
|
10
|
+
<b>Ritext</b> — A modern, composable WYSIWYG rich text editor built with <b>Tailwind CSS</b>, powered by <b>Tiptap</b>.
|
|
11
|
+
<br />
|
|
12
|
+
Build your own toolbars & controls with clean React components — no heavy UI layer, no extra dependencies beyond Tiptap.
|
|
13
|
+
</p>
|
|
10
14
|
|
|
11
|
-
<
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://www.npmjs.com/package/ritext"><img alt="npm" src="https://img.shields.io/npm/v/ritext?logo=npm"></a>
|
|
17
|
+
<a href="https://www.npmjs.com/package/ritext"><img alt="downloads" src="https://img.shields.io/npm/dm/ritext"></a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<a href="https://www.buymeacoffee.com/siamahnaf" target="_blank">
|
|
22
|
+
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="48">
|
|
23
|
+
</a>
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ✨ Why Ritext?
|
|
29
|
+
- **Composable UI**: bring your own toolbar/buttons/components
|
|
30
|
+
- **Tiptap-powered**: reliable ProseMirror foundation
|
|
31
|
+
- **Tailwind-friendly**: build modern UI fast
|
|
32
|
+
- **Package-first**: works great in Next.js apps & component libraries
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 📚 Docs help needed (Contributions welcome!)
|
|
37
|
+
Ritext is stable and production-ready — but the documentation is still growing.
|
|
38
|
+
|
|
39
|
+
If you like this project, please help by writing or improving docs:
|
|
40
|
+
- ✅ Installation & setup (Next.js / React)
|
|
41
|
+
- ✅ Basic editor example + toolbar patterns
|
|
42
|
+
- ✅ Extension usage & custom UI components
|
|
43
|
+
- ✅ Theming, styling, and Tailwind tips
|
|
44
|
+
- ✅ Recipes (tables, images, placeholders, slash menu, etc.)
|
|
45
|
+
|
|
46
|
+
### Good first contribution ideas
|
|
47
|
+
- Add a “Getting Started” page
|
|
48
|
+
- Document one extension (Bold/Italic/Table/Image/etc.)
|
|
49
|
+
- Add small code examples + screenshots/GIFs
|
|
50
|
+
|
|
51
|
+
**Want to contribute?**
|
|
52
|
+
1. Fork the repo
|
|
53
|
+
2. Create a new branch: `docs/<topic>`
|
|
54
|
+
3. Update or add docs inside `content/` (Markdown)
|
|
55
|
+
4. Open a PR ✨
|
|
56
|
+
|
|
57
|
+
> If you’re not sure what to write, open an issue and I’ll assign you a docs task.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🤝 Contributing
|
|
62
|
+
All contributions are welcome — issues, PRs, bug reports, improvements, and docs.
|
|
63
|
+
|
|
64
|
+
- Create an issue for bugs/feature requests
|
|
65
|
+
- PRs should include a clear description and screenshots if UI-related
|
|
66
|
+
|
|
67
|
+
---
|
|
12
68
|
|
|
13
|
-
### This is an testing phase will publish soon.
|
|
14
69
|
|
|
15
70
|
## Connect with me
|
|
16
71
|
<div style="display: flex; align-items: center; gap: 3px;">
|
package/dist/index.d.mts
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { Extensions } from '@tiptap/react';
|
|
3
|
+
import { Extensions, JSONContent, Editor as Editor$1 } from '@tiptap/react';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
5
|
|
|
5
|
-
interface
|
|
6
|
+
interface EditorRef {
|
|
7
|
+
editor: Editor$1 | null;
|
|
8
|
+
insert: (value: string) => void;
|
|
9
|
+
insertAtEnd: (value: string) => void;
|
|
10
|
+
replaceSelection: (value: string) => void;
|
|
11
|
+
focus: () => void;
|
|
12
|
+
getHTML: () => string;
|
|
13
|
+
setContent: (value: string) => void;
|
|
14
|
+
clear: () => void;
|
|
15
|
+
}
|
|
16
|
+
type OutputType = "html" | "json" | "text";
|
|
17
|
+
type ContentValue = string | JSONContent;
|
|
18
|
+
type EditorProps = {
|
|
6
19
|
children?: ReactNode;
|
|
7
20
|
extensions?: Extensions;
|
|
8
21
|
className?: string;
|
|
9
22
|
dragHandler?: boolean;
|
|
10
23
|
showBubbleMenu?: boolean;
|
|
11
|
-
|
|
12
|
-
|
|
24
|
+
content?: ContentValue;
|
|
25
|
+
output?: OutputType;
|
|
26
|
+
onContentChange?: (value: string | JSONContent) => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
declare const Editor: react.ForwardRefExoticComponent<EditorProps & react.RefAttributes<EditorRef>>;
|
|
13
30
|
|
|
14
31
|
interface Props$1 {
|
|
15
32
|
className?: string;
|
|
@@ -24,4 +41,4 @@ interface Props {
|
|
|
24
41
|
}
|
|
25
42
|
declare const Content: ({ className }: Props) => react_jsx_runtime.JSX.Element;
|
|
26
43
|
|
|
27
|
-
export { Content, Editor, Toolbar };
|
|
44
|
+
export { Content, Editor, type EditorRef, Toolbar };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { Extensions } from '@tiptap/react';
|
|
3
|
+
import { Extensions, JSONContent, Editor as Editor$1 } from '@tiptap/react';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
5
|
|
|
5
|
-
interface
|
|
6
|
+
interface EditorRef {
|
|
7
|
+
editor: Editor$1 | null;
|
|
8
|
+
insert: (value: string) => void;
|
|
9
|
+
insertAtEnd: (value: string) => void;
|
|
10
|
+
replaceSelection: (value: string) => void;
|
|
11
|
+
focus: () => void;
|
|
12
|
+
getHTML: () => string;
|
|
13
|
+
setContent: (value: string) => void;
|
|
14
|
+
clear: () => void;
|
|
15
|
+
}
|
|
16
|
+
type OutputType = "html" | "json" | "text";
|
|
17
|
+
type ContentValue = string | JSONContent;
|
|
18
|
+
type EditorProps = {
|
|
6
19
|
children?: ReactNode;
|
|
7
20
|
extensions?: Extensions;
|
|
8
21
|
className?: string;
|
|
9
22
|
dragHandler?: boolean;
|
|
10
23
|
showBubbleMenu?: boolean;
|
|
11
|
-
|
|
12
|
-
|
|
24
|
+
content?: ContentValue;
|
|
25
|
+
output?: OutputType;
|
|
26
|
+
onContentChange?: (value: string | JSONContent) => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
declare const Editor: react.ForwardRefExoticComponent<EditorProps & react.RefAttributes<EditorRef>>;
|
|
13
30
|
|
|
14
31
|
interface Props$1 {
|
|
15
32
|
className?: string;
|
|
@@ -24,4 +41,4 @@ interface Props {
|
|
|
24
41
|
}
|
|
25
42
|
declare const Content: ({ className }: Props) => react_jsx_runtime.JSX.Element;
|
|
26
43
|
|
|
27
|
-
export { Content, Editor, Toolbar };
|
|
44
|
+
export { Content, Editor, type EditorRef, Toolbar };
|
package/dist/index.js
CHANGED
|
@@ -316,19 +316,66 @@ var EditorProvider = ({ children, value }) => {
|
|
|
316
316
|
|
|
317
317
|
// src/lib/Editor.tsx
|
|
318
318
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
319
|
-
var Editor = ({ children, extensions = [], className, dragHandler = true, showBubbleMenu = true }) => {
|
|
319
|
+
var Editor = (0, import_react6.forwardRef)(({ children, extensions = [], className, dragHandler = true, showBubbleMenu = true, content, onContentChange, output }, ref) => {
|
|
320
320
|
const stableExtensions = (0, import_react6.useMemo)(() => extensions, [extensions]);
|
|
321
321
|
const editor = (0, import_react7.useEditor)({
|
|
322
322
|
extensions: stableExtensions,
|
|
323
|
-
immediatelyRender: false
|
|
323
|
+
immediatelyRender: false,
|
|
324
|
+
content,
|
|
325
|
+
onUpdate: ({ editor: editor2 }) => {
|
|
326
|
+
if (!onContentChange) return;
|
|
327
|
+
const out = output === "json" ? editor2.getJSON() : output === "text" ? editor2.getText() : editor2.getHTML();
|
|
328
|
+
onContentChange(out);
|
|
329
|
+
}
|
|
324
330
|
}, [stableExtensions]);
|
|
325
331
|
const value = (0, import_react6.useMemo)(() => ({ editor }), [editor]);
|
|
332
|
+
(0, import_react6.useImperativeHandle)(
|
|
333
|
+
ref,
|
|
334
|
+
() => ({
|
|
335
|
+
editor,
|
|
336
|
+
insert: (val) => {
|
|
337
|
+
if (!editor) return;
|
|
338
|
+
editor.chain().focus().insertContent(val).run();
|
|
339
|
+
},
|
|
340
|
+
insertAtEnd: (val) => {
|
|
341
|
+
if (!editor) return;
|
|
342
|
+
const end = editor.state.doc.content.size;
|
|
343
|
+
editor.commands.insertContentAt(end, val);
|
|
344
|
+
editor.commands.focus(end);
|
|
345
|
+
},
|
|
346
|
+
replaceSelection: (val) => {
|
|
347
|
+
if (!editor) return;
|
|
348
|
+
const { from, to } = editor.state.selection;
|
|
349
|
+
editor.commands.insertContentAt({ from, to }, val);
|
|
350
|
+
editor.chain().focus().run();
|
|
351
|
+
},
|
|
352
|
+
focus: () => {
|
|
353
|
+
if (!editor) return;
|
|
354
|
+
editor.chain().focus().run();
|
|
355
|
+
},
|
|
356
|
+
getHTML: () => {
|
|
357
|
+
var _a, _b;
|
|
358
|
+
return (_b = (_a = editor == null ? void 0 : editor.getHTML) == null ? void 0 : _a.call(editor)) != null ? _b : "";
|
|
359
|
+
},
|
|
360
|
+
setContent: (val) => {
|
|
361
|
+
if (!editor) return;
|
|
362
|
+
editor.commands.setContent(val);
|
|
363
|
+
},
|
|
364
|
+
clear: () => {
|
|
365
|
+
var _a, _b;
|
|
366
|
+
if (!editor) return;
|
|
367
|
+
(_b = (_a = editor.commands).clearContent) == null ? void 0 : _b.call(_a);
|
|
368
|
+
}
|
|
369
|
+
}),
|
|
370
|
+
[editor]
|
|
371
|
+
);
|
|
326
372
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(EditorProvider, { value: __spreadProps(__spreadValues({}, value), { dragHandler }), children: [
|
|
327
373
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className, children }),
|
|
328
374
|
value.editor && dragHandler && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RiDragHandler_default, { editor: value.editor }),
|
|
329
375
|
value.editor && showBubbleMenu && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BubbleMenu_default, { editor: value.editor })
|
|
330
376
|
] });
|
|
331
|
-
};
|
|
377
|
+
});
|
|
378
|
+
Editor.displayName = "Editor";
|
|
332
379
|
var Editor_default = Editor;
|
|
333
380
|
|
|
334
381
|
// src/lib/Toolbar.tsx
|
package/dist/index.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import "@siamf/react-color-pick/dist/index.css";
|
|
17
17
|
|
|
18
18
|
// src/lib/Editor.tsx
|
|
19
|
-
import { useMemo } from "react";
|
|
19
|
+
import { forwardRef, useMemo, useImperativeHandle } from "react";
|
|
20
20
|
import { useEditor as useEditor2 } from "@tiptap/react";
|
|
21
21
|
|
|
22
22
|
// src/lib/internal_com/RiDragHandler.tsx
|
|
@@ -115,19 +115,66 @@ var BubbleMenu_default = BubbleMenu;
|
|
|
115
115
|
|
|
116
116
|
// src/lib/Editor.tsx
|
|
117
117
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
118
|
-
var Editor = ({ children, extensions = [], className, dragHandler = true, showBubbleMenu = true }) => {
|
|
118
|
+
var Editor = forwardRef(({ children, extensions = [], className, dragHandler = true, showBubbleMenu = true, content, onContentChange, output }, ref) => {
|
|
119
119
|
const stableExtensions = useMemo(() => extensions, [extensions]);
|
|
120
120
|
const editor = useEditor2({
|
|
121
121
|
extensions: stableExtensions,
|
|
122
|
-
immediatelyRender: false
|
|
122
|
+
immediatelyRender: false,
|
|
123
|
+
content,
|
|
124
|
+
onUpdate: ({ editor: editor2 }) => {
|
|
125
|
+
if (!onContentChange) return;
|
|
126
|
+
const out = output === "json" ? editor2.getJSON() : output === "text" ? editor2.getText() : editor2.getHTML();
|
|
127
|
+
onContentChange(out);
|
|
128
|
+
}
|
|
123
129
|
}, [stableExtensions]);
|
|
124
130
|
const value = useMemo(() => ({ editor }), [editor]);
|
|
131
|
+
useImperativeHandle(
|
|
132
|
+
ref,
|
|
133
|
+
() => ({
|
|
134
|
+
editor,
|
|
135
|
+
insert: (val) => {
|
|
136
|
+
if (!editor) return;
|
|
137
|
+
editor.chain().focus().insertContent(val).run();
|
|
138
|
+
},
|
|
139
|
+
insertAtEnd: (val) => {
|
|
140
|
+
if (!editor) return;
|
|
141
|
+
const end = editor.state.doc.content.size;
|
|
142
|
+
editor.commands.insertContentAt(end, val);
|
|
143
|
+
editor.commands.focus(end);
|
|
144
|
+
},
|
|
145
|
+
replaceSelection: (val) => {
|
|
146
|
+
if (!editor) return;
|
|
147
|
+
const { from, to } = editor.state.selection;
|
|
148
|
+
editor.commands.insertContentAt({ from, to }, val);
|
|
149
|
+
editor.chain().focus().run();
|
|
150
|
+
},
|
|
151
|
+
focus: () => {
|
|
152
|
+
if (!editor) return;
|
|
153
|
+
editor.chain().focus().run();
|
|
154
|
+
},
|
|
155
|
+
getHTML: () => {
|
|
156
|
+
var _a, _b;
|
|
157
|
+
return (_b = (_a = editor == null ? void 0 : editor.getHTML) == null ? void 0 : _a.call(editor)) != null ? _b : "";
|
|
158
|
+
},
|
|
159
|
+
setContent: (val) => {
|
|
160
|
+
if (!editor) return;
|
|
161
|
+
editor.commands.setContent(val);
|
|
162
|
+
},
|
|
163
|
+
clear: () => {
|
|
164
|
+
var _a, _b;
|
|
165
|
+
if (!editor) return;
|
|
166
|
+
(_b = (_a = editor.commands).clearContent) == null ? void 0 : _b.call(_a);
|
|
167
|
+
}
|
|
168
|
+
}),
|
|
169
|
+
[editor]
|
|
170
|
+
);
|
|
125
171
|
return /* @__PURE__ */ jsxs2(EditorProvider, { value: __spreadProps(__spreadValues({}, value), { dragHandler }), children: [
|
|
126
172
|
/* @__PURE__ */ jsx3("div", { className, children }),
|
|
127
173
|
value.editor && dragHandler && /* @__PURE__ */ jsx3(RiDragHandler_default, { editor: value.editor }),
|
|
128
174
|
value.editor && showBubbleMenu && /* @__PURE__ */ jsx3(BubbleMenu_default, { editor: value.editor })
|
|
129
175
|
] });
|
|
130
|
-
};
|
|
176
|
+
});
|
|
177
|
+
Editor.displayName = "Editor";
|
|
131
178
|
var Editor_default = Editor;
|
|
132
179
|
|
|
133
180
|
// src/lib/Toolbar.tsx
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ritext",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Ritext is a modern WYSIWYG rich text editor built with Tailwind CSS, powered by Tiptap. It offers a customizable UI and functional layer that lets you design your own editor controls and toolbars with clean, composable React components—no heavy UI, no extra dependencies beyond Tiptap.",
|
|
5
5
|
"homepage": "https://ritext.vercel.app/",
|
|
6
6
|
"main": "dist/index.js",
|