Skip to content

maifeeulasad/lilac

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

116 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌸 Lilac

A smooth, modern WYSIWYG text editor with a clean interface, elegant typography, and a calming editing experience.

TypeScript React Vite

preview of lilac

✨ Features

  • 🎨 Beautiful Design: Clean, calming interface with elegant typography
  • πŸ“ Rich Text Editing: Full WYSIWYG editor with formatting toolbar
  • ⚑ Modern Stack: Built with React 18, TypeScript, and Vite
  • πŸ”§ Fully Typed: Strict TypeScript configuration for better development experience
  • πŸ“± Responsive: Works seamlessly across desktop, tablet, and mobile devices
  • πŸŒ™ Dark Mode: Built-in light and dark theme support
  • β™Ώ Accessible: WCAG compliant with proper ARIA attributes
  • βš™οΈ Configurable: Extensive customization options
  • πŸ”„ Undo/Redo: Full history management with keyboard shortcuts
  • ⌨️ Keyboard Shortcuts: Full support for common formatting shortcuts
  • πŸ› οΈ Extensible Toolbar: Customizable toolbar with rich formatting options
  • πŸ”Œ Plugin System: Powerful extension system with built-in plugins
  • 🎯 Framework Agnostic: Designed to work with multiple frameworks (React first, more coming)

πŸš€ Quick Start

Installation

npm install lilac-editor
# or
yarn add lilac-editor
# or
pnpm add lilac-editor

Basic Usage

import React from 'react';
import { Editor } from 'lilac-editor';

function MyApp() {
  const [content, setContent] = useState('');

  return (
    <Editor
      initialContent="<h1>Welcome to Lilac!</h1><p>Start typing...</p>"
      placeholder="Enter your text here..."
      onChange={setContent}
      theme="light"
      autoFocus
      toolbar={{
        show: true,
        tools: ['bold', 'italic', 'underline', 'separator', 'heading1', 'heading2']
      }}
    />
  );
}

Using Built-in Plugins

import React from 'react';
import { Editor, wordCountPlugin, emojiPlugin, tablePlugin } from 'lilac-editor';

function MyApp() {
  const [content, setContent] = useState('');

  return (
    <Editor
      initialContent="<h1>Welcome to Lilac!</h1><p>Start typing...</p>"
      onChange={setContent}
      plugins={[
        wordCountPlugin,    // Document statistics panel
        emojiPlugin,        // Emoji picker with Ctrl+Shift+E
        tablePlugin,        // Table inserter with Ctrl+Shift+T
      ]}
      toolbar={{ show: true }}
    />
  );
}

Advanced Usage with Ref

import React, { useRef } from 'react';
import { Editor, type EditorRef } from 'lilac-editor';

function MyApp() {
  const editorRef = useRef<EditorRef>(null);

  const handleUndo = () => {
    editorRef.current?.undo();
  };

  const handleRedo = () => {
    editorRef.current?.redo();
  };

  const getContent = () => {
    const content = editorRef.current?.getContent();
    console.log('Current content:', content);
  };

  return (
    <div>
      <div>
        <button onClick={handleUndo}>Undo</button>
        <button onClick={handleRedo}>Redo</button>
        <button onClick={getContent}>Get Content</button>
      </div>
      
      <Editor
        ref={editorRef}
        initialContent="Welcome to Lilac Editor!"
        maxLength={5000}
        toolbar={{ show: true }}
      />
    </div>
  );
}

Custom Height and Scrolling

import React from 'react';
import { Editor } from 'lilac-editor';

function MyApp() {
  return (
    <Editor
      initialContent="<h1>Welcome to Lilac!</h1><p>This editor has custom height settings...</p>"
      placeholder="Start typing..."
      minHeight={300}
      maxHeight={500}
      toolbar={{ show: true }}
    />
  );
}

πŸ“– API Reference

EditorProps

Prop Type Default Description
initialContent string '' Initial content of the editor (HTML for rich text)
placeholder string 'Start writing...' Placeholder text when editor is empty
readOnly boolean false Whether the editor is read-only
autoFocus boolean false Auto-focus editor on mount
maxLength number undefined Maximum character limit (plain text mode only)
minHeight number 200 Minimum height of editor content area in pixels
maxHeight number 600 Maximum height of editor content area in pixels (enables scrolling)
theme 'light' | 'dark' | 'auto' 'light' Editor theme
className string undefined Additional CSS class
style CSSProperties undefined Inline styles
onChange (content: string) => void undefined Content change callback
onSelectionChange (selection: SelectionRange | null) => void undefined Selection change callback
onFocus () => void undefined Focus event callback
onBlur () => void undefined Blur event callback
toolbar ToolbarConfig undefined Toolbar configuration
plugins EditorPlugin[] [] Array of plugins to install

ToolbarConfig

Prop Type Default Description
show boolean false Whether to show the toolbar
tools ToolbarTool[] Default tools Array of toolbar tools to display
position 'top' | 'bottom' | 'floating' 'top' Toolbar position (top only for now)

Available Toolbar Tools

Tool Description Keyboard Shortcut
'bold' Bold text formatting Ctrl/Cmd + B
'italic' Italic text formatting Ctrl/Cmd + I
'underline' Underline text formatting Ctrl/Cmd + U
'strikethrough' Strikethrough text formatting -
'heading1' Heading 1 format -
'heading2' Heading 2 format -
'heading3' Heading 3 format -
'paragraph' Paragraph format -
'bulletList' Bullet list -
'orderedList' Numbered list -
'blockquote' Block quote -
'codeBlock' Code block -
'link' Insert/edit link Ctrl/Cmd + K
'image' Insert image -
'separator' Visual separator -

Example Toolbar Configuration

<Editor
  toolbar={{
    show: true,
    tools: [
      'bold',
      'italic',
      'underline',
      'separator',
      'heading1',
      'heading2',
      'heading3',
      'paragraph',
      'separator',
      'bulletList',
      'orderedList',
      'blockquote',
      'separator',
      'link',
      'codeBlock'
    ]
  }}
/>

EditorRef Methods

Method Type Description
getContent() () => string Get current editor content
setContent(content) (content: string) => void Set editor content
focus() () => void Focus the editor
blur() () => void Blur the editor
undo() () => void Undo last change
redo() () => void Redo last undone change
canUndo boolean Whether undo is available
canRedo boolean Whether redo is available

πŸ”Œ Plugin System

Lilac features a powerful plugin system that allows you to extend the editor with custom functionality. The system supports toolbar buttons, side panels, keyboard shortcuts, content transformers, and more.

Built-in Plugins

πŸ“Š Word Count Plugin

Displays real-time document statistics in a side panel.

import { wordCountPlugin } from 'lilac-editor';

<Editor plugins={[wordCountPlugin]} />

Features:

  • Words, characters, paragraphs count
  • Real-time updates
  • Right sidebar panel
  • Clean, organized display

😊 Emoji Picker Plugin

Add emojis to your content with an easy-to-use picker.

import { emojiPlugin } from 'lilac-editor';

<Editor plugins={[emojiPlugin]} />

Features:

  • Categorized emoji selection (Smileys, Nature, Food, Travel, Objects)
  • Toolbar button integration
  • Keyboard shortcut: Ctrl+Shift+E
  • Modal interface with search

πŸ“‹ Table Inserter Plugin

Insert and customize HTML tables with an interactive dialog.

import { tablePlugin } from 'lilac-editor';

<Editor plugins={[tablePlugin]} />

Features:

  • Configurable rows and columns
  • Header row option
  • Border toggle
  • Live preview
  • Keyboard shortcut: Ctrl+Shift+T

Creating Custom Plugins

Create your own plugins by implementing the EditorPlugin interface:

import { EditorPlugin, EditorContext } from 'lilac-editor';
import { MyIcon } from 'lucide-react';

export const myCustomPlugin: EditorPlugin = {
  id: 'my-custom-plugin',
  name: 'My Custom Plugin',
  version: '1.0.0',
  description: 'A custom plugin that does amazing things',
  
  // Add toolbar buttons
  toolbarButtons: [
    {
      id: 'my-button',
      icon: <MyIcon size={16} />,
      label: 'My Tool',
      tooltip: 'My custom tool (Ctrl+M)',
      onClick: (context: EditorContext) => {
        context.insertContent('<strong>Custom content!</strong>');
      },
    },
  ],
  
  // Add keyboard shortcuts
  keyboardShortcuts: [
    {
      key: 'm',
      ctrlKey: true,
      action: (context: EditorContext) => {
        context.insertContent('<em>Shortcut triggered!</em>');
      },
    },
  ],
  
  // Add custom styles
  styles: `
    .my-custom-styles {
      color: #ff6b6b;
      font-weight: bold;
    }
  `,
  
  // Lifecycle hooks
  onInstall: (context) => console.log('Plugin installed'),
  onContentChange: (content, context) => {
    // React to content changes
  },
};

Plugin Capabilities

Feature Description
Toolbar Buttons Add custom formatting tools and actions
Side Panels Create custom UI panels (left, right, bottom)
Keyboard Shortcuts Define custom hotkey combinations
Content Transformers Process and transform content automatically
Lifecycle Hooks React to editor events (mount, unmount, content changes)
Custom Styles Inject CSS for plugin-specific styling
Context Menu Add right-click menu items

Plugin Manager

Access the plugin manager for programmatic control:

import { pluginManager } from 'lilac-editor';

// Install a plugin
pluginManager.install(myCustomPlugin);

// Check if installed
if (pluginManager.isInstalled('my-plugin-id')) {
  console.log('Plugin is active');
}

// Get all plugins
const allPlugins = pluginManager.getAllPlugins();

// Uninstall a plugin
pluginManager.uninstall('my-plugin-id');

Plugin API Exports

// Plugin system
import { 
  PluginManager, 
  pluginManager,
  EditorPlugin,
  EditorContext 
} from 'lilac-editor';

// Built-in plugins
import { 
  wordCountPlugin,
  emojiPlugin,
  tablePlugin 
} from 'lilac-editor';

πŸ› οΈ Development

Prerequisites

  • Node.js 18+, recommended 20+ LTS
  • npm, yarn, or pnpm

Setup

# Clone the repository
git clone https://github.com/maifeeulasad/lilac.git
cd lilac

# Install dependencies
npm install

# Start development server
npm run dev

# Build for production
npm run build

# Run tests
npm test

# Lint code
npm run lint

# Type check
npm run typecheck

Project Structure

src/
β”œβ”€β”€ components/          # React components
β”‚   β”œβ”€β”€ Editor/         # Main editor component
β”‚   └── Toolbar/        # Toolbar component
β”œβ”€β”€ hooks/              # Custom React hooks
β”œβ”€β”€ plugins/            # Plugin system and built-in plugins
β”‚   β”œβ”€β”€ PluginManager.ts    # Plugin manager
β”‚   β”œβ”€β”€ wordCount.tsx       # Word count plugin
β”‚   β”œβ”€β”€ emojiPicker.tsx     # Emoji picker plugin
β”‚   β”œβ”€β”€ tableInserter.tsx   # Table inserter plugin
β”‚   └── index.ts            # Plugin exports
β”œβ”€β”€ types/              # TypeScript type definitions
β”‚   β”œβ”€β”€ editor.ts           # Core editor types
β”‚   β”œβ”€β”€ plugin.ts           # Plugin system types
β”‚   └── index.ts            # Type exports
β”œβ”€β”€ utils/              # Utility functions
β”œβ”€β”€ App.tsx             # Demo application
β”œβ”€β”€ main.tsx            # Entry point
└── index.ts            # Library exports

🎨 Customization

Themes

Lilac comes with built-in light and dark themes. You can also create custom themes by overriding CSS custom properties:

.lilac-editor {
  --lilac-color-primary: #your-color;
  --lilac-color-background: #your-bg;
  --lilac-border-radius: 8px;
  /* ... other variables */
}

Styling

The editor uses CSS custom properties for easy theming. All styles are scoped to prevent conflicts with your application.

πŸ—ΊοΈ Roadmap

  • πŸ”§ Rich text toolbar (Bold, Italic, Underline, etc.)
  • πŸ˜‰ Emoji support (via Emoji Picker plugin)
  • πŸ“‹ Copy/Paste enhancements
  • πŸ”— Link insertion and management
  • πŸ–ΌοΈ Image upload and embedding
  • πŸ“ Markdown support
  • πŸ” Find and replace
  • πŸ“Š Table support
  • 🎯 Vue.js integration
  • πŸ…°οΈ Angular integration
  • πŸ”Œ Plugin system
  • πŸ“± Mobile optimizations
  • 🎨 More themes
  • πŸ§ͺ Comprehensive test suite

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Workflow

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests for your changes
  5. Ensure all tests pass (npm test)
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Inspired by modern text editors like Notion, Linear, and GitHub
  • Built with love using React, TypeScript, and modern web technologies
  • Thanks to all contributors and the open-source community

Made with 🌸 by maifeeulasad

⭐ Star us on GitHub if you find this project useful!

About

lilac: A smooth and elegant WYSIWYG editor for effortless writing

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages