ESM package integration
Install and use @wztlink1013/sveditor as the default ESM package in React, Next.js, and Vite apps.
ESM package integration
ESM via npm is the default integration path. Install @wztlink1013/sveditor, import it in your bundler, and mount with SVeditor.create(). Use the UMD CDN only when you cannot add a bundler.
Packages
| Package | When to install |
|---|---|
@wztlink1013/sveditor | Always — editor runtime, UI, types, and styles |
@wztlink1013/sveditor-collab-schema | Only when your server implements collaboration APIs |
When you use the collab schema, keep both packages on the same version.
1. Install
If your license includes private registry access, add .npmrc in the project root:
@wztlink1013:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}Install a pinned version:
pnpm add @wztlink1013/sveditor@0.2.16Use the token provided with your license for CI and fresh machines.
2. Imports
| Import | Purpose |
|---|---|
@wztlink1013/sveditor | SVeditor.create(), types, theme helpers |
@wztlink1013/sveditor/style.css | Toolbar, editor chrome, toast styles |
@wztlink1013/sveditor/global | Optional window.SVeditor typings for CDN pages |
Bundlers resolve the ESM entry automatically. Prefer import over require() in application code.
3. Minimal usage
"use client";
import { SVeditor } from "@wztlink1013/sveditor";
import type { EditorOptions } from "@wztlink1013/sveditor";
import "@wztlink1013/sveditor/style.css";
const editor = SVeditor.create({
el: "#editor",
content: "<p>Hello</p>",
editable: true,
} satisfies Omit<EditorOptions, "el">);- Always import
style.css— missing CSS breaks toolbar and layout. - Call
destroy()before unmount or navigation.
4. Next.js App Router (SSR-safe)
The ESM bundle may access document during module load. Do not statically import @wztlink1013/sveditor from Server Components.
Option A — next/dynamic with ssr: false
Split the editor into a client-only module, then load it dynamically:
"use client";
import dynamic from "next/dynamic";
export const DocEditor = dynamic(
() => import("./doc-editor.client").then((m) => m.DocEditor),
{ ssr: false },
);Inside doc-editor.client.tsx:
"use client";
import { useEffect, useMemo, useRef } from "react";
import { SVeditor } from "@wztlink1013/sveditor";
import type { EditorOptions } from "@wztlink1013/sveditor";
import "@wztlink1013/sveditor/style.css";
type EditorInitOptions = Omit<EditorOptions, "el">;
export function DocEditor({ options }: { options: EditorInitOptions }) {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const el = containerRef.current;
if (!el) return;
const editor = SVeditor.create({ el, ...options });
return () => editor.destroy();
}, [options]);
return <div ref={containerRef} className="min-h-[640px]" />;
}Option B — dynamic import() in useEffect
"use client";
import { useEffect, useRef } from "react";
import type { EditorInstance } from "@wztlink1013/sveditor";
import "@wztlink1013/sveditor/style.css";
export function LazyEditor() {
const containerRef = useRef<HTMLDivElement>(null);
const instanceRef = useRef<EditorInstance | null>(null);
useEffect(() => {
const el = containerRef.current;
if (!el) return;
let cancelled = false;
void import("@wztlink1013/sveditor").then(({ SVeditor }) => {
if (cancelled) return;
instanceRef.current = SVeditor.create({ el, content: "<p>Hello</p>" });
});
return () => {
cancelled = true;
instanceRef.current?.destroy();
instanceRef.current = null;
};
}, []);
return <div ref={containerRef} className="min-h-[640px]" />;
}5. Vite / React SPA
When mount code runs only in the browser, use useEffect and stable options:
"use client";
import { useEffect, useMemo, useRef } from "react";
import { SVeditor } from "@wztlink1013/sveditor";
import type { EditorOptions } from "@wztlink1013/sveditor";
import "@wztlink1013/sveditor/style.css";
type EditorInitOptions = Omit<EditorOptions, "el">;
export function EditorPage() {
const containerRef = useRef<HTMLDivElement>(null);
const options = useMemo<EditorInitOptions>(
() => ({ content: "<p>Hello</p>", editable: true }),
[],
);
useEffect(() => {
const el = containerRef.current;
if (!el) return;
const editor = SVeditor.create({ el, ...options });
return () => editor.destroy();
}, [options]);
return <div ref={containerRef} className="min-h-[640px]" />;
}See Quick start for the full lifecycle.
6. Styles and PostCSS
Import SDK styles directly:
import "@wztlink1013/sveditor/style.css";If PostCSS re-processes node_modules CSS and fails on the pre-built stylesheet, exclude @wztlink1013/sveditor in your PostCSS config.
7. TypeScript
import { SVeditor } from "@wztlink1013/sveditor";
import type {
EditorOptions,
EditorInstance,
ExtensionOptions,
AutoSaveOptions,
} from "@wztlink1013/sveditor";8. Upgrade
- Bump the version in
package.json. - Reinstall dependencies.
- Re-test
extensionsOptionsand collab schema if applicable.
Troubleshooting
| Symptom | Fix |
|---|---|
document is not defined | Use next/dynamic + ssr: false or dynamic import() in useEffect |
| Broken toolbar | Add import "@wztlink1013/sveditor/style.css" |
| Focus lost on keystroke | Stabilize options with useMemo |
| Install auth errors | Check .npmrc and your license token |
| PostCSS parse error | Exclude SDK CSS from PostCSS |