A Svelte 5 component library for creating and editing UN-style resolutions. Built for Model United Nations conferences.
- Full Resolution Editor: Complete editing experience for UN resolutions with preamble and operative clauses
- Block-based Structure: Support for nested subclauses up to 4 levels deep
- Phrase Validation: Validate clause openings against official UN resolution vocabulary
- Phrase Suggestions: Inline autocomplete for common resolution phrases
- Import from Text: Parse plain text or LLM-formatted resolutions
- Preview Mode: Render resolutions in official UN document format
- Fully Customizable: i18n support, custom phrases, and snippet-based extension points
- Type-safe: Full TypeScript support with Zod schema validation
# Using bun
bun add -d @deutschemodelunitednations/munify-resolution-editor
# Using npm
npm install -D @deutschemodelunitednations/munify-resolution-editor
# Using pnpm
pnpm add -D @deutschemodelunitednations/munify-resolution-editorNote: Svelte component libraries should be installed as
devDependencies(-d/-Dflag). SvelteKit bundles components at build time, so they don't need to be runtime dependencies.
This library requires:
svelte^5.0.0- TailwindCSS and DaisyUI configured in your project (for styling)
This library uses TailwindCSS utility classes for styling. Since the components are distributed as Svelte files, you need to configure your project's Tailwind to scan the library's components. This is the standard approach for Tailwind-based component libraries.
Option 1: Import the helper CSS file (simplest)
@import 'tailwindcss';
@import '@deutschemodelunitednations/munify-resolution-editor/tailwind.css';
@plugin "daisyui";Option 2: Add the @source directive manually
@import 'tailwindcss';
@source "../node_modules/@deutschemodelunitednations/munify-resolution-editor/dist/**/*.svelte";
@plugin "daisyui";Add the library to your content array in tailwind.config.js:
export default {
content: [
'./src/**/*.{html,js,svelte,ts}',
'./node_modules/@deutschemodelunitednations/munify-resolution-editor/dist/**/*.svelte'
]
// ... rest of config
};Tailwind CSS generates only the CSS for utility classes that are actually used in your project. By default, it ignores node_modules since most packages don't use Tailwind. This library ships Svelte components that use Tailwind utilities, so Tailwind needs to scan them to generate the necessary styles.
Note: This is different from libraries like daisyUI, which are Tailwind plugins that generate CSS programmatically. Our library is a component library that uses Tailwind utilities in its templates.
<script lang="ts">
import { ResolutionEditor } from '@deutschemodelunitednations/munify-resolution-editor';
import {
germanPreamblePhrases,
germanOperativePhrases
} from '@deutschemodelunitednations/munify-resolution-editor/phrases/de';
import { germanLabels } from '@deutschemodelunitednations/munify-resolution-editor/i18n/de';
import type { Resolution } from '@deutschemodelunitednations/munify-resolution-editor/schema';
let resolution: Resolution = $state({
committeeName: 'General Assembly',
preamble: [],
operative: []
});
function handleChange(updated: Resolution) {
resolution = updated;
console.log('Resolution updated:', updated);
}
</script>
<ResolutionEditor
committeeName="General Assembly"
{resolution}
editable={true}
labels={germanLabels}
preamblePhrases={germanPreamblePhrases}
operativePhrases={germanOperativePhrases}
onResolutionChange={handleChange}
/><script lang="ts">
import { ResolutionPreview } from '@deutschemodelunitednations/munify-resolution-editor';
import { germanLabels } from '@deutschemodelunitednations/munify-resolution-editor/i18n/de';
</script>
<ResolutionPreview
{resolution}
labels={germanLabels}
headerData={{
conferenceName: 'Model United Nations',
committeeName: 'Security Council',
topic: 'International Peace and Security',
documentNumber: 'S/RES/2026/1'
}}
/>import {
ResolutionEditor, // Full editing interface
ResolutionPreview, // Read-only preview
ClauseEditor, // Preamble clause editor
OperativeClauseEditor, // Operative clause editor
SubClauseEditor, // Recursive subclause editor
PhraseLookupModal, // Phrase browsing modal
PhraseSuggestions, // Inline autocomplete
ImportModal // Text import modal
} from '@deutschemodelunitednations/munify-resolution-editor';import {
type Resolution,
type PreambleClause,
type OperativeClause,
type SubClause,
type ClauseBlock,
type TextBlock,
type SubclausesBlock,
type ResolutionHeaderData,
resolutionSchema,
createEmptyOperativeClause,
createEmptySubClause,
createTextBlock,
createSubclausesBlock,
getSubClauseLabel
} from '@deutschemodelunitednations/munify-resolution-editor/schema';// All German phrases
import {
germanPreamblePhrases,
germanOperativePhrases
} from '@deutschemodelunitednations/munify-resolution-editor/phrases/de';
// Or import individually
import { preamblePhrases } from '@deutschemodelunitednations/munify-resolution-editor/phrases/de';
import { operativePhrases } from '@deutschemodelunitednations/munify-resolution-editor/phrases/de';import type { ResolutionEditorLabels } from '@deutschemodelunitednations/munify-resolution-editor/i18n';
import { germanLabels } from '@deutschemodelunitednations/munify-resolution-editor/i18n/de';The editor supports Svelte 5 snippet-based extension points for customization:
<ResolutionEditor {...props}>
{#snippet clauseToolbar({ clause, index })}
<button onclick={() => addAmendment(clause)}>Add Amendment</button>
{/snippet}
{#snippet clauseAnnotations({ clause, index })}
{#if hasAmendments(clause)}
<div class="badge badge-warning">Has amendments</div>
{/if}
{/snippet}
{#snippet previewHeader({ resolution, headerData })}
<div class="custom-header">Custom header content</div>
{/snippet}
{#snippet previewFooter({ resolution })}
<div class="signatures">Signatures section</div>
{/snippet}
</ResolutionEditor># Install dependencies
bun install
# Start dev server
bun run dev
# Build library
bun run package
# Type checking
bun run check
# Run tests
bun testMIT - Deutsche Model United Nations e.V.