@mhamz.01/easyflow-texteditor
v2.1.0
Published
A rich text editor built on Tiptap
Readme
@mhamz.01/easyflow-texteditor
A rich text / multi-tab document editor for React, built on Tiptap.
Ships with a toolbar, a sidebar for tab/subtab document management, image
upload, tables, and view/edit access control — as a single drop-in <Editor>
component.
Installation
npm install @mhamz.01/easyflow-texteditorPeer dependencies
These must also be installed in the consuming app:
npm install react react-dom @tiptap/core @tiptap/pm @tiptap/react| Peer dependency | Version |
| --- | --- |
| react | >=18 |
| react-dom | >=18 |
| @tiptap/core | ^3 |
| @tiptap/pm | ^3 |
| @tiptap/react | ^3 |
Styles are bundled as a side effect of importing the package — no separate CSS import is required.
Quick start
import { Editor } from "@mhamz.01/easyflow-texteditor";
export default function DocumentPage() {
return (
<div style={{ height: "100vh" }}>
<Editor
initialTabs={[{ id: "1", title: "Untitled", content: null, subtabs: [] }]}
onChange={(payload) => console.log(payload)}
/>
</div>
);
}<Editor> renders its own sidebar, toolbar, and content area, and fills the
size of its parent container — give the parent an explicit height (as above)
or pass className/style.
Editor props
interface EditorProps {
initialTabs?: EditorTab[]
onChange?: (payload: EditorChangePayload) => void
onTabsChange?: (tabs: EditorTab[]) => void
className?: string
style?: React.CSSProperties
editable?: boolean
restrictTabActions?: boolean
}| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| initialTabs | EditorTab[] | [] | Tabs/documents to load on mount. An empty array (or omitting the prop) starts with a single blank "Tab 1". |
| onChange | (payload: EditorChangePayload) => void | — | Debounced (~100ms) callback fired on content changes, tab switches, and tab/subtab add/delete. Does not fire from user edits while editable={false}. |
| onTabsChange | (tabs: EditorTab[]) => void | — | Fired whenever the tab list changes (add/rename/delete/content edit) — useful for persisting the full tab tree, e.g. to local storage or your backend. |
| className / style | string / React.CSSProperties | — | Applied to the editor's root wrapper div. |
| editable | boolean | true | Set false to render the document read-only — see Access control below. |
| restrictTabActions | boolean | false | Opt-in: also lock the sidebar's add/rename/delete controls while editable={false}. See Access control. |
Exported types
import type {
EditorTab,
EditorSubTab,
EditorChangePayload,
EditorChangeSource,
} from "@mhamz.01/easyflow-texteditor";interface EditorTab {
id: string
title: string
content: any | null // Tiptap JSON document, or null when empty
subtabs: EditorSubTab[]
}
interface EditorSubTab {
id: string
title: string
content: any | null
}
interface EditorChangePayload {
tabs: EditorTab[]
activeTabId: string
activeSubTabId: string | null
source: EditorChangeSource
}
type EditorChangeSource =
| "editor" // typing / content change
| "tab-switch"
| "subtab-switch"
| "add-tab"
| "add-subtab"
| "delete-tab"
| "delete-subtab"
| "restore"
| "storage"
| "manual"content on a tab/subtab is a Tiptap JSON document. Persist it as-is
and pass it straight back through initialTabs to restore a document — no
transformation needed.
Access control
For per-document view/edit permissions, see access-control-props.md
for the full reference on editable and restrictTabActions, including
exactly what each one does and does not lock down. Short version:
<Editor
initialTabs={tabs}
onChange={handleChange}
editable={hasEditAccess} // false = read-only content, formatting, uploads
restrictTabActions // optional: also lock sidebar add/rename/delete
/>Server-side/save-time enforcement is still required on your backend — these props only control the editor UI's own interactive behavior.
