https://github.com/robotdad/semantic-composer
A reusable React-based markdown editor component (Cortex Composer) built with Milkdown that supports both rich text editing and raw markdown modes, with toggleable read/edit modes. The component will be designed for easy integration into various web applications.
https://github.com/robotdad/semantic-composer
Last synced: about 1 year ago
JSON representation
A reusable React-based markdown editor component (Cortex Composer) built with Milkdown that supports both rich text editing and raw markdown modes, with toggleable read/edit modes. The component will be designed for easy integration into various web applications.
- Host: GitHub
- URL: https://github.com/robotdad/semantic-composer
- Owner: robotdad
- License: mit
- Created: 2025-04-02T03:11:13.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-04-03T02:14:04.000Z (about 1 year ago)
- Last Synced: 2025-04-03T02:27:11.066Z (about 1 year ago)
- Language: JavaScript
- Size: 5.14 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Semantic Composer
A markdown editor component built with React and Milkdown/Crepe, designed for easy integration into various web applications.
**[🚀 Try it live!](https://robotdad.github.io/semantic-composer)**
## Features
- Toggle between Edit and Read modes
- Toggle between Rich text and Raw markdown modes
- Support for all standard markdown features:
- Headings
- Lists
- Code blocks with syntax highlighting
- Tables
- Links and images
- Document management with localStorage persistence
- Export markdown content to file
- Fluent UI integration
- Responsive design with different sizing options
- Various appearance styles
- Word count display
- Keyboard shortcuts (Ctrl+S/Cmd+S to save)
## Getting Started
### Installation
```bash
# Install dependencies
npm install
# For Fluent UI integration
npm install @fluentui/react-components @fluentui/react-icons
```
### Running the Demo
```bash
npm start
```
### TypeScript Support
This project is built with TypeScript, providing:
- Type definitions for component props, refs, and state
- Improved editor integration with autocompletion
- Better error detection at compile time
- Enhanced developer experience
TypeScript-specific scripts:
```bash
# Type checking
npm run typecheck
# Linting TypeScript files
npm run lint
```
The development server will start at http://localhost:3000 where you can see the Semantic Composer component in action.
## Usage
### Basic Usage
```tsx
import React, { useRef } from 'react';
import { SemanticComposer } from './components';
import type { SemanticComposerRef } from './types';
function MyApp() {
const editorRef = useRef(null);
const handleChange = (markdown: string) => {
console.log('Markdown updated:', markdown);
};
const handleSave = (markdown: string, documentId: string) => {
// Save markdown to database or file
saveToDatabase(markdown);
};
const loadExternalContent = (content: string) => {
// Use the component API to load new content
if (editorRef.current?.setContent) {
editorRef.current.setContent(content);
}
};
return (
My Markdown Editor
loadExternalContent('# New Content')}>
Load Content
editorRef.current?.loadDocument('# New Document', 'doc-123')}>
Load Document
console.error('Editor error:', error)}
width="100%"
appearance="outline" // or "underline", "filled-darker", "filled-lighter"
size="medium" // or "small", "large"
autoSaveInterval={5000} // Set to 0 to disable autosave
storageKeyPrefix="editor" // Prefix for localStorage keys
useFluentProvider={true} // Wrap with FluentProvider
/>
);
}
```
## Component Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| initialValue | string | '' | Initial markdown content |
| initialDocumentId | string | 'default' | Initial document ID for persistence |
| defaultMode | 'edit' \| 'read' | 'edit' | Initial editor mode |
| defaultView | 'rich' \| 'raw' | 'rich' | Initial view mode (rich text or raw markdown) |
| onChange | function | undefined | Callback when content changes |
| onSave | function | undefined | Callback when save is triggered with (content, documentId) |
| onError | function | undefined | Callback for error handling |
| onModeChange | function | undefined | Callback when mode changes |
| onViewChange | function | undefined | Callback when view changes |
| width | string \| number | '100%' | Editor width |
| appearance | 'outline' \| 'underline' \| 'filled-darker' \| 'filled-lighter' | 'outline' | Visual style of the component |
| size | 'small' \| 'medium' \| 'large' | 'medium' | Size variant of the component |
| placeholder | string | 'Start writing...' | Placeholder text for empty editor |
| readOnly | boolean | false | Set editor to read-only mode |
| autoFocus | boolean | true | Auto-focus on load |
| spellCheck | boolean | true | Enable spell check |
| autoSaveInterval | number | 5000 | Auto-save interval in ms (0 to disable) |
| debug | boolean | false | Enable debug logging |
| storageKeyPrefix | string | 'editor' | Prefix for localStorage keys |
| useFluentProvider | boolean | true | Wrap component with FluentProvider |
| fluentProviderProps | object | {} | Props to pass to FluentProvider |
## Component API
When using a ref, the following methods are available:
| Method | Description |
|--------|-------------|
| getCurrentContent() | Get the current markdown content and document ID |
| setContent(markdown, documentId) | Update the editor content with optional document ID |
| loadDocument(content, documentId) | Load content with a specific document ID |
| getDocumentId() | Get the current document ID |
| getCurrentView() | Get current view mode ('rich' or 'raw') |
| getCurrentMode() | Get current edit mode ('edit' or 'read') |
| toggleEditorView() | Toggle between rich and raw modes |
| toggleEditorMode() | Toggle between edit and read modes |
| reset(options) | Reset the editor with options for clearing content and storage |
| getCrepeInstance() | Get the underlying Crepe instance |
| getStorageKey() | Get the current storage key being used |
## Reset Options
The `reset()` method accepts an options object with the following properties:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| clearContent | boolean | true | Clear editor content |
| clearCurrentStorage | boolean | true | Clear current document storage |
| clearAllStorage | boolean | false | Clear all editor-related storage |
| resetToDefaultDocument | boolean | false | Reset document ID to default |
## Document Management
The component maintains document content in localStorage using the following pattern:
- Each document has a unique ID (defaulting to 'default')
- Storage keys are created as `${storageKeyPrefix}:${documentId}`
- The current document ID is tracked in `${storageKeyPrefix}:current-document-id`
- The `loadDocument()` method provides the easiest way to switch between documents
## Fluent UI Integration
### Dialog Component
The package includes a `SemanticComposerDialog` component for modal editing experiences:
```tsx
import { SemanticComposerDialog } from './components';
function MyApp() {
const [open, setOpen] = useState(false);
return (
<>
setOpen(true)}>Edit Content
{
console.log('Saved:', content);
// Process saved content
}}
/>
>
);
}
```
### Styling Options
The component comes with multiple appearance options:
- `outline`: Standard bordered style (default)
- `underline`: Bottom border only
- `filled-darker`: Darker background fill
- `filled-lighter`: Lighter background fill
And size variants:
- `small`: Compact view with smaller text
- `medium`: Standard size (default)
- `large`: Larger text and spacing
### Theming
The component inherits themes from your Fluent UI theme context. If `useFluentProvider` is true (default), it creates its own FluentProvider. To use your application's theme context, set `useFluentProvider={false}`.