svelte-outliner
v0.0.1
Published
A Svelte 5 outline editor with keyboard shortcuts, drag-and-drop, zoom, undo/redo, and optional markdown rendering
Maintainers
Readme
svelte-outliner
A Svelte outline editor component with hierarchical content organization, keyboard shortcuts, drag-and-drop, zoom navigation, undo/redo, and optional markdown rendering.
Ported from solid-outliner (itself from react-outliner) with the same interaction model.
Features
- Keyboard shortcuts
Enter: Create new sibling (or split at cursor)Shift + Enter: Create sibling before current itemTab/Shift + Tab: Indent / outdentAlt + ↑/↓: Move item up / down↑/↓: Navigate between itemsBackspaceon empty non-root item: DeleteCtrl/Cmd + Z/Ctrl/Cmd + Shift + Z/Ctrl + Y: Undo / redo
- Expand / collapse
- Drag and drop reordering (before / inside / after)
- Zoom into a node with breadcrumb navigation
- Read-only mode
- Optional markdown renderer
- Dark mode via CSS variables (
.darkclass)
Install
pnpm add svelte-outliner
# peer: svelte ^5Usage
<script lang="ts">
import { Outliner, type OutlineItem } from 'svelte-outliner';
// Styles are imported by the component. If they are missing in your setup:
// import 'svelte-outliner/OutlineItem.css';
let data = $state<OutlineItem[]>([
{
id: '1',
topic: 'Root Node',
children: [
{
id: '1-1',
topic: '**Bold text** and *italic text*',
children: []
}
]
}
]);
</script>
<div class="dark">
<Outliner
data={data}
onChange={(next) => (data = next)}
markdown={(text) => text}
readonly={false}
fileName="My Outline"
/>
</div>Local development (this repo)
The demo site imports from $lib instead of the package name:
import { Outliner } from '$lib';
import '$lib/outliner/OutlineItem.css';API
Props
| Prop | Type | Default | Description |
| ---------- | --------------------------------------------- | ---------------- | ---------------------------- |
| data | OutlineData[] | required | Initial outline data |
| onChange | (data: OutlineItem[]) => void | optional | Fired when outline changes |
| readonly | boolean | false | Read-only mode |
| markdown | (text: string, item: OutlineItem) => string | optional | Markdown/HTML renderer |
| fileName | string | optional | Shown in breadcrumb root |
| i18n | Partial<OutlinerI18n> | Chinese defaults | Menu / UI strings |
Data structure
interface OutlineData {
id: string;
topic: string;
children?: OutlineData[];
expanded?: boolean; // default: true
}This is the same node shape as Mind Elixir / mindmapcn-svelte (id, topic, children, expanded). A mind-map root maps to outliner as fileName={root.topic} + data={root.children}. Demo: /mindmap.
Other exports
import {
Outliner,
createHistory,
addSiblingOperation,
addSiblingBeforeOperation,
indentOperation,
outdentOperation,
moveUpOperation,
moveDownOperation,
moveToOperation,
type OutlineItem,
type OutlineData,
type OutlinerProps,
type OutlinerI18n,
type HistoryManager
} from 'svelte-outliner';Development
pnpm install
pnpm dev # demo site (src/routes)
pnpm build # build demo site only
pnpm package # build library to dist/ (for npm)
pnpm check # typecheck| Command | Output |
| --------------- | ------------------------------ |
| pnpm build | Demo / docs site |
| pnpm package | npm library (dist/) |
Library source lives in src/lib/outliner. The demo site and mindmap live under src/routes / other $lib folders and are not published to npm.
Publish
See docs/PUBLISH.md for the full checklist (version bump, npm publish, site deploy).
Tech stack
- Svelte 5 (runes)
- SvelteKit (demo app +
@sveltejs/packagefor the library) - TypeScript
- Vite
