Package Exports
- platejs-customization
- platejs-customization/dist/styles.css
- platejs-customization/styles
Readme
platejs-customization
A powerful, customizable rich-text editor component built on top of Plate.js for React applications.
Quick Start
import { PlateLiteEditor } from "platejs-customization";
// That's it! No CSS import needed ✨
function App() {
return <PlateLiteEditor value={value} onChange={handleChange} />;
}
Works exactly like shadcn/ui - just import the component and use it!
Features
- ✨ Zero Configuration - Just import and use, no CSS import needed!
- 🎨 Fully Customizable - Extensive props for styling and behavior
- 📝 Rich Text Editing - All Plate.js features including:
- Basic formatting (bold, italic, underline, etc.)
- Lists (ordered and unordered)
- Tables
- Code blocks with syntax highlighting
- Media embeds (images, videos)
- Math equations
- Mentions
- Comments and suggestions
- Slash commands
- AI-powered features
- 🎯 TypeScript Support - Full type definitions included
- 🔒 CSS Isolation - Styles don't conflict with your app
- 📦 Optimized - Small bundle size with automatic CSS injection
- 🚀 Production Ready - Works like shadcn/ui components
Installation
# Using pnpm (recommended)
pnpm add platejs-customization platejs react react-dom
# Using npm
npm install platejs-customization platejs react react-dom
# Using yarn
yarn add platejs-customization platejs react react-dom
Peer Dependencies
This package requires the following peer dependencies:
react
>= 18.0.0react-dom
>= 18.0.0platejs
>= 49.0.0
Usage
Basic Example
import { useState } from "react";
import { PlateLiteEditor } from "platejs-customization";
// ✅ No CSS import needed - styles are automatically loaded!
import type { Value } from "platejs";
function App() {
const [value, setValue] = useState<Value>([
{ type: "p", children: [{ text: "Hello, world!" }] },
]);
const handleChange = (newValue: Value) => {
setValue(newValue);
console.log("Editor content changed:", newValue);
};
return (
<div className="container mx-auto p-4">
<PlateLiteEditor
value={value}
onChange={handleChange}
placeholder="Start typing..."
/>
</div>
);
}
export default App;
Note: Styles are automatically injected when you use the component - no manual CSS import required!
With Custom Styling
import { PlateLiteEditor } from "platejs-customization";
function CustomEditor({ value, handleChange }) {
return (
<PlateLiteEditor
value={value}
onChange={handleChange}
placeholder="Enter your content here..."
className="max-w-4xl mx-auto p-4"
editorClassName="min-h-[400px] border rounded-lg p-4"
/>
);
}
Read-Only Mode
import { PlateLiteEditor } from "platejs-customization";
function ReadOnlyEditor() {
return <PlateLiteEditor value={content} readOnly={true} />;
}
API Reference
PlateLiteEditor Props
Prop | Type | Default | Description |
---|---|---|---|
value |
Value |
undefined |
The editor content value |
onChange |
(value: Value) => void |
undefined |
Callback fired when content changes |
placeholder |
string |
"Type your message here." |
Placeholder text |
className |
string |
undefined |
CSS class for the container |
editorClassName |
string |
undefined |
CSS class for the editor |
readOnly |
boolean |
false |
Whether the editor is read-only |
autoFocus |
boolean |
false |
Whether to auto-focus on mount |
disabled |
boolean |
false |
Whether the editor is disabled |
Advanced Usage
Custom Editor Kit
import { EditorKit, useEditor } from "platejs-customization";
import { usePlateEditor } from "platejs/react";
// Use the full editor kit
const editor = usePlateEditor({
plugins: EditorKit,
value: initialValue,
});
Using Individual Hooks
import {
useDebounce,
useIsTouchDevice,
useMounted,
} from "platejs-customization";
function MyComponent() {
const isTouchDevice = useIsTouchDevice();
const isMounted = useMounted();
const debouncedValue = useDebounce(value, 500);
// Your component logic
}
Styling & CSS
Option 1: Automatic Style Loading (Recommended)
✨ No CSS import needed! Styles are automatically injected when you use the component.
import { PlateLiteEditor } from "platejs-customization";
// That's it! Styles load automatically 🎉
function MyEditor() {
return <PlateLiteEditor value={value} onChange={handleChange} />;
}
Option 2: Manual CSS Import (Advanced)
For consumers who prefer to handle CSS loading separately or use CSS-in-JS solutions:
Method A: CSS-Only Import (Recommended for CSS-in-JS)
// Import CSS only (no JavaScript components bundled)
import "platejs-customization/styles";
// Then import the component separately
import { PlateLiteEditor } from "platejs-customization";
function MyEditor() {
return <PlateLiteEditor value={value} onChange={handleChange} />;
}
Method B: Direct CSS File Import
// Import CSS file directly
import "platejs-customization/dist/styles.css";
// Then import the component
import { PlateLiteEditor } from "platejs-customization";
function MyEditor() {
return <PlateLiteEditor value={value} onChange={handleChange} />;
}
Note: When using manual CSS import, make sure to import the CSS before importing the component to avoid styling issues.
Next.js Users
If you're using Next.js and getting module resolution errors, try this approach:
// In your page or component
import { PlateLiteEditor } from "platejs-customization";
import "platejs-customization/dist/styles.css"; // Use the direct path
export default function MyPage() {
return <PlateLiteEditor value={value} onChange={handleChange} />;
}
Vite Users
// In your main.tsx or component
import { PlateLiteEditor } from "platejs-customization";
import "platejs-customization/styles"; // Use the shorter path
function App() {
return <PlateLiteEditor value={value} onChange={handleChange} />;
}
CSS Isolation & Layout Integration
The editor CSS is automatically scoped and will NOT affect your application:
- ✅ Works with any layout (sidebar, navbar, etc.)
- ✅ No conflicts with your existing CSS
- ✅ No global style pollution
- ✅ Works with your Tailwind/design system
The component respects your project's existing styles and theme.
Using in Complex Layouts
The editor works seamlessly with any layout structure:
// ✅ Works perfectly with sidebar layouts
function Dashboard() {
return (
<div className="flex">
{/* Your sidebar - NOT affected by editor styles */}
<aside className="w-64 bg-gray-800">
<nav>...</nav>
</aside>
{/* Main content area */}
<main className="flex-1">
{/* Your navbar - NOT affected */}
<header className="bg-white shadow">...</header>
{/* Editor in content area - fully scoped */}
<div className="p-6">
<PlateLiteEditor
value={value}
onChange={handleChange}
className="max-w-4xl"
editorClassName="min-h-[500px] border rounded-lg p-4"
/>
</div>
</main>
</div>
);
}
Custom Styling
You can customize the editor using the provided props:
<PlateLiteEditor
// Container styling (wrapper around editor)
className="max-w-4xl mx-auto my-8"
// Editor content area styling
editorClassName="min-h-[600px] bg-white border-2 border-gray-300 rounded-xl p-6 shadow-lg"
value={value}
onChange={handleChange}
/>
Tailwind CSS Integration
If your project uses Tailwind CSS, the editor styles work alongside it without conflicts:
<div className="container mx-auto p-4">
<h1 className="text-3xl font-bold mb-6">My Editor</h1>
{/* Editor with Tailwind classes */}
<PlateLiteEditor
className="bg-gray-50 rounded-lg shadow-md"
editorClassName="prose prose-lg max-w-none p-8"
value={value}
onChange={handleChange}
/>
</div>
Dark Mode Support
The editor includes built-in dark mode support. Add the dark
class to any parent element:
<div className="dark">
<PlateLiteEditor value={value} onChange={handleChange} />
</div>
Troubleshooting
Problem: Editor doesn't show properly
Solution: Styles are auto-injected. If you still have issues:
- Make sure you're using the latest version:
pnpm update platejs-customization
- Check browser console for any errors
- Ensure your bundler supports dynamic imports
Problem: CSS conflicts with my design system
Solution: The editor uses CSS variables that can be customized:
/* In your global CSS */
:root {
/* Override editor variables if needed */
--primary: your-color;
--radius: your-border-radius;
}
The editor will respect your existing Tailwind configuration.
Problem: Styles not loading in production
Solution: Ensure your bundler includes CSS files in the build:
- Vite: Works out of the box ✅
- Next.js: Works out of the box ✅
- Webpack: Ensure
css-loader
andstyle-loader
are configured
TypeScript
Full TypeScript support is included:
import type { PlateLiteEditorProps, MyEditor } from "platejs-customization";
import type { Value } from "platejs";
// Use types in your components
const props: PlateLiteEditorProps = {
value: myValue,
onChange: handleChange,
};
Dependencies
This package bundles the following Plate.js plugins:
- AI features
- Autoformat
- Basic blocks and marks
- Code blocks
- Tables
- Comments and suggestions
- Media embeds
- Math equations
- And many more!
See the full list in package.json
.
Development
Local Development
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Build the library
pnpm build:lib
# Lint
pnpm lint
Building
# Build library for production
pnpm build:lib
# Generate type declarations only
pnpm build:types
Publishing
# Build and publish to npm
pnpm publish
Note: The prepublishOnly
script will automatically build the library before publishing.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
Author
zonaet
Support
For issues and questions, please open an issue on the GitHub repository.
Changelog
See CHANGELOG.md for version history and changes.