@xinosolutions/editor
v1.1.2
Published
Professional rich text editor component for React with customizable toolbar, theming, and access validation.
Readme
@xinosolutions/editor
Production-ready rich text editor component for React applications.
About XinoSolutions
XinoSolutions is a software development company dedicated to creating high-quality, developer-friendly solutions. We specialize in building modern React components and tools that help developers build better applications faster. Our commitment to excellence, clean code, and user experience drives everything we create.
This package is part of our open-source initiative to contribute valuable tools to the React ecosystem.
@xinosolutions/editor provides a WYSIWYG editing experience with customizable toolbar/navbar layouts, theme configuration, image upload hooks, and optional access validation through Xino API keys.
Why use this package
- Fast integration into existing React apps
- Rich formatting controls out of the box
- Extensible toolbar and navbar configuration
- Browser-safe access validation using
apiKey - Suitable for product forms, CMS flows, support tools, and admin panels
Installation
npm install @xinosolutions/editoryarn add @xinosolutions/editorPeer Dependencies
react^18.2.0react-dom^18.2.0
Quick Start
import { useState } from "react";
import ReactEditor from "@xinosolutions/editor";
export default function App() {
const [value, setValue] = useState("");
return (
<ReactEditor
value={value}
onChange={setValue}
placeholder="Write your content..."
height="420px"
/>
);
}Access Validation
For client-side applications, pass your API key as apiKey (xs_editor_...).
Get your API key here: https://editor.xinosolutions.com/
- Create an editor site and domain allow-list in SX Editor
- No customer backend is required — the API key is safe in browser env vars
- Validation calls
https://api.editor.xinosolutions.com/api/text_editor/validate(no host env setup required) - Validation help links/messages are handled internally by the package
Environment Variables
Vite:
VITE_TEXT_EDITOR_API_KEY=xs_editor_your_id_hereNext.js:
NEXT_PUBLIC_TEXT_EDITOR_API_KEY=xs_editor_your_id_hereUsage:
const apiKey =
import.meta?.env?.VITE_TEXT_EDITOR_API_KEY ??
process.env.NEXT_PUBLIC_TEXT_EDITOR_API_KEY ??
"";
<ReactEditor value={value} onChange={setValue} apiKey={apiKey} />;API Reference (Props)
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | "" | Current editor HTML/text content. |
| onChange | (nextValue: string) => void | undefined | Change callback for editor content. |
| placeholder | string | internal | Placeholder text when editor is empty. |
| height | string \| number | internal | Editor height (for example "400px" or 500). |
| mainProps | object | {} | Props passed to the editor root wrapper. |
| apiKey | string | "" | API key for access validation (xs_editor_...). |
| onAccessChange | ({ status, access }) => void | undefined | Access-state callback (checking, allowed, denied, etc). |
| toolbarDensity | "comfortable" \| "compact" | "comfortable" | Toolbar spacing density. |
| navbar | Array | internal | Override navbar groups/options. |
| toolbar | Array | internal | Override toolbar controls. |
| remove_from_navbar | Array | [] | Remove selected navbar items. |
| remove_from_toolbar | Array | [] | Remove selected toolbar items. |
| theme_config | object | {} | CSS variable-based editor theme overrides. |
| image_handler | (payload) => Promise<string> | undefined | Async image uploader returning a final URL string. |
| getEditorRef | (ref) => void | undefined | Access editor ref for advanced integrations. |
Access-State Example
<ReactEditor
value={value}
onChange={setValue}
apiKey={apiKey}
onAccessChange={({ status }) => setCanSave(status === "allowed")}
/>Custom Toolbar and Navbar
const navbar = [
{ name: "file", options: ["new_document", "preview", "print"] },
{ name: "view", options: ["source_code", "full_screen"] },
{ name: "insert", options: ["image", "link", "video", "hr_line", "special_char"] },
{ name: "format", options: ["bold", "italic", "underline", "font", "font_size", "alignment"] },
"|",
"select_all",
];
const toolbar = [
"undo", "redo", "|", "bold", "italic", "underline", "|", "alignment", "|", "orderedList", "unorderedList",
];
<ReactEditor value={value} onChange={setValue} navbar={navbar} toolbar={toolbar} />;Remove actions:
<ReactEditor
value={value}
onChange={setValue}
remove_from_toolbar={["bold", { name: "format", options: ["h1"] }]}
remove_from_navbar={["select_all", { name: "view", options: ["source_code"] }]}
/>Theme Customization
const theme_config = {
"background-color": "#ffffff",
"border-color": "#d0d5dd",
"text-color": "#101828",
"toolbar-button-background": "#ffffff",
"toolbar-text-color": "#101828",
"toolbar-button-hover-background": "#f2f4f7",
"toolbar-button-selected-background": "#eaecf0",
"svg-color": "#101828",
};
<ReactEditor value={value} onChange={setValue} theme_config={theme_config} />;Image Upload Integration
import axios from "axios";
async function image_handler(payload) {
const formData = new FormData();
formData.append("image", payload.image);
const response = await axios.post("/api/upload", formData);
return response.data?.url ?? "";
}
<ReactEditor value={value} onChange={setValue} image_handler={image_handler} />;Security Recommendations
- Register every production hostname in your editor site’s allowed domains.
- Use
apiKeyfrom environment variables — do not hard-code in source. - Enforce authorization again on your own save/upload endpoints if you add a backend later.
Troubleshooting
- Editor remains locked: verify domain allow-list and key type in the portal.
- Validation endpoint errors: verify your API key and domain allow-list in the portal.
- Visual issues: confirm package styles are loaded and not overridden by aggressive global CSS resets.
- Image upload fails: ensure
image_handlerresolves to a valid absolute URL.
License
MIT
Support
For product or integration support, contact Xino Solutions.
