Skip to content

luxe-tools/luxe-edit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

68 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LuxeEdit - Rich Text Editor Monorepo

A modern, feature-rich React-based rich text editor powered by Lexical with customizable toolbars and floating toolbar support.

🌐 Live Demo: https://luxe-tools.github.io/luxe-edit/

πŸ“ Project Structure

luxe-edit/
β”œβ”€β”€ packages/
β”‚   └── core/                 # The main package to be published
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ index.tsx     # Main entry point, exports LuxeEditor
β”‚       β”‚   β”œβ”€β”€ styles.css    # CSS styles for the editor
β”‚       β”‚   β”œβ”€β”€ types/
β”‚       β”‚   β”‚   └── toolbar.ts  # Toolbar item types
β”‚       β”‚   └── plugins/
β”‚       β”‚       β”œβ”€β”€ Toolbar.tsx           # Top toolbar component
β”‚       β”‚       └── FloatingToolbarPlugin.tsx  # Floating toolbar plugin
β”‚       β”œβ”€β”€ dist/             # Built output (generated)
β”‚       β”œβ”€β”€ package.json      # Package configuration
β”‚       β”œβ”€β”€ tsconfig.json     # TypeScript config
β”‚       └── tsup.config.ts    # Build configuration
β”‚
β”œβ”€β”€ apps/
β”‚   └── demo/                 # Demo/example app
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   └── main.tsx      # Demo app entry point
β”‚       β”œβ”€β”€ index.html        # HTML template
β”‚       β”œβ”€β”€ vite.config.ts    # Vite configuration
β”‚       └── package.json      # Demo app dependencies
β”‚
β”œβ”€β”€ package.json              # Root monorepo config
└── yarn.lock                 # Dependency lock file

✨ Features

Rich Text Formatting

  • βœ… Text Formatting: Bold, Italic, Underline, Strikethrough
  • βœ… Headings: H1, H2, H3, H4, H5, H6
  • βœ… Alignment: Left, Center, Right, Justify
  • βœ… History: Undo/Redo with proper state tracking

Toolbars

  • βœ… Top Toolbar: Fixed toolbar at the top of the editor
  • βœ… Floating Toolbar: Appears above selected text (3-4 essential options)
  • βœ… Customizable: Array-based configuration for toolbar items
  • βœ… Active States: Visual feedback for active formatting

Developer Experience

  • βœ… TypeScript: Full TypeScript support with exported types
  • βœ… Customizable: Custom toolbar items, labels, and icons
  • βœ… Theme Support: CSS variable-based theming
  • βœ… Monorepo: Clean workspace structure

πŸš€ Quick Start

🌐 View Live Demo β†’

Installation (After Publishing)

# Using npm
npm install luxe-edit

# Using yarn
yarn add luxe-edit

# Using pnpm
pnpm add luxe-edit

Basic Usage

import { LuxeEditor } from 'luxe-edit';
import 'luxe-edit/index.css';

function App() {
  return (
    <LuxeEditor 
      initialConfig={{ 
        namespace: 'MyEditor',
        theme: {} 
      }} 
    />
  );
}

With Custom Toolbar

import { LuxeEditor, type ToolbarItem } from 'luxe-edit';
import 'luxe-edit/index.css';

function App() {
  const toolbarItems: ToolbarItem[] = [
    { type: 'undo' },
    { type: 'redo' },
    { type: 'divider' },
    { type: 'bold' },
    { type: 'italic' },
    { type: 'underline' },
    { type: 'strikethrough' },
    { type: 'divider' },
    { type: 'heading1' },
    { type: 'heading2' },
    { type: 'heading3' },
    { type: 'divider' },
    { type: 'alignLeft' },
    { type: 'alignCenter' },
    { type: 'alignRight' },
    { type: 'alignJustify' },
  ];

  return (
    <LuxeEditor 
      initialConfig={{ namespace: 'MyEditor', theme: {} }}
      showToolbar={true}
      showFloatingToolbar={true}
      toolbarItems={toolbarItems}
    />
  );
}

πŸ“š API Reference

LuxeEditor Component

Props

interface LuxeEditorProps {
  initialConfig: any;                    // Lexical editor initial config
  showFloatingToolbar?: boolean;         // Show floating toolbar (default: true)
  showToolbar?: boolean;                 // Show top toolbar (default: false)
  toolbarItems?: ToolbarItem[];          // Toolbar items for top toolbar
  floatingToolbarItems?: ToolbarItem[];  // Separate items for floating toolbar (optional)
  children?: React.ReactNode;            // Custom plugins/components
}

ToolbarItem Type

interface ToolbarItem {
  type: ToolbarItemType;
  label?: string;        // Optional custom label
  icon?: React.ReactNode; // Optional custom icon
}

type ToolbarItemType = 
  | 'undo'
  | 'redo'
  | 'divider'
  | 'bold'
  | 'italic'
  | 'underline'
  | 'strikethrough'
  | 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'heading5' | 'heading6'
  | 'paragraph'
  | 'alignLeft'
  | 'alignCenter'
  | 'alignRight'
  | 'alignJustify';

Available Toolbar Types

Text Formatting

  • bold - Bold text
  • italic - Italic text
  • underline - Underlined text
  • strikethrough - Strikethrough text

Headings

  • heading1 through heading6 - Heading levels

Actions

  • undo - Undo last action
  • redo - Redo last action
  • paragraph - Convert to paragraph

Alignment

  • alignLeft - Left align text
  • alignCenter - Center align text
  • alignRight - Right align text
  • alignJustify - Justify text

Utility

  • divider - Visual separator between toolbar sections

🎨 Customization

Custom Toolbar Items

const toolbarItems: ToolbarItem[] = [
  { type: 'bold', label: 'Bold Text' },
  { type: 'italic', icon: <em>I</em> },
  { type: 'divider' },
  { type: 'heading1' },
];

Custom Theme

<LuxeEditor 
  initialConfig={{ 
    namespace: 'MyEditor',
    theme: {
      text: {
        bold: 'my-bold-class',
        italic: 'my-italic-class',
      }
    }
  }} 
/>

Separate Floating Toolbar

The floating toolbar automatically filters to show only essential text formatting options (bold, italic, underline). You can customize it:

<LuxeEditor 
  toolbarItems={fullToolbarItems}        // All options for top toolbar
  floatingToolbarItems={[                // Limited options for floating toolbar
    { type: 'bold' },
    { type: 'italic' },
    { type: 'underline' }
  ]}
  showToolbar={true}
  showFloatingToolbar={true}
/>

πŸ› οΈ Development Workflow

From Root Directory

# Install all dependencies
yarn install

# Build the core package
yarn build

# Run the demo app
yarn dev

# Or use workspace commands
yarn workspace luxe-edit build
yarn workspace demo dev

Make Changes

  1. Edit source files in packages/core/src/
  2. Rebuild: yarn build (in packages/core)
  3. Demo app will hot-reload automatically

πŸ—οΈ Architecture Overview

Monorepo Setup (Yarn Workspaces)

  • Root package.json: Defines workspaces (packages/*, apps/*)
  • Local linking: The demo app automatically uses the local luxe-edit package
  • Shared dependencies: Common dependencies are hoisted to the root node_modules

Core Package (luxe-edit)

Build Process:

  1. Source: src/index.tsx (TypeScript + React/JSX)
  2. Builder: tsup (fast build tool powered by esbuild)
  3. Output: dist/ folder containing:
    • index.mjs - ESM format (modern)
    • index.js - CommonJS format (Node.js)
    • index.d.ts - TypeScript declarations
    • index.css - CSS styles

Package Configuration:

{
  "name": "luxe-edit",
  "main": "./dist/index.js",        // CommonJS entry
  "module": "./dist/index.mjs",     // ESM entry
  "types": "./dist/index.d.ts",     // TypeScript types
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.js"
    },
    "./index.css": "./dist/index.css"
  },
  "files": ["dist"]  // Only publish dist folder
}

πŸ“¦ Publishing to NPM

Before Publishing:

  1. Ensure package is built:

    cd packages/core
    yarn build
  2. Update version in packages/core/package.json:

    {
      "version": "1.0.1"  // Bump version
    }
  3. Verify dist/ contains:

    • index.js, index.mjs, index.d.ts, index.css

Publishing Steps:

cd packages/core

# Login to npm (first time only)
npm login

# Publish (with 2FA code)
npm publish --otp=YOUR_6_DIGIT_CODE

# Or use version bumping
npm version patch  # 1.0.0 -> 1.0.1
npm publish --otp=YOUR_6_DIGIT_CODE

What Gets Published:

Only files in the "files" array (dist/) are published:

  • βœ… dist/index.js
  • βœ… dist/index.mjs
  • βœ… dist/index.d.ts
  • βœ… dist/index.css
  • ❌ src/, tsconfig.json, tsup.config.ts (not included)

🎯 Features in Detail

Toolbar System

Top Toolbar

  • Always visible at the top of the editor
  • Shows active formatting states
  • Supports all toolbar item types
  • Fully customizable via toolbarItems prop

Floating Toolbar

  • Appears above selected text
  • Automatically filters to show only essential options (3-4 items)
  • Only shows: bold, italic, underline, strikethrough
  • Can be customized via floatingToolbarItems prop

Active State Tracking

The toolbar tracks and displays active formatting:

  • Bold/Italic/Underline/Strikethrough: Highlights when active
  • Headings: Shows which heading level is active
  • Undo/Redo: Disabled when not available

Heading Support

Full support for headings H1-H6:

  • Proper Lexical HeadingNode integration
  • Active state tracking
  • Seamless conversion between headings and paragraphs
  • Styled headings via CSS

πŸ“‹ Usage Examples

Minimal Setup (Default)

<LuxeEditor initialConfig={{ namespace: 'MyEditor' }} />
// Shows floating toolbar with bold, italic, underline

Full Featured Toolbar

const toolbarItems: ToolbarItem[] = [
  { type: 'undo' },
  { type: 'redo' },
  { type: 'divider' },
  { type: 'bold' },
  { type: 'italic' },
  { type: 'underline' },
  { type: 'strikethrough' },
  { type: 'divider' },
  { type: 'heading1' },
  { type: 'heading2' },
  { type: 'heading3' },
  { type: 'divider' },
  { type: 'alignLeft' },
  { type: 'alignCenter' },
  { type: 'alignRight' },
  { type: 'alignJustify' },
];

<LuxeEditor 
  initialConfig={{ namespace: 'MyEditor' }}
  showToolbar={true}
  toolbarItems={toolbarItems}
/>

Custom Floating Toolbar Only

<LuxeEditor 
  initialConfig={{ namespace: 'MyEditor' }}
  showToolbar={false}
  showFloatingToolbar={true}
  floatingToolbarItems={[
    { type: 'bold' },
    { type: 'italic' },
    { type: 'underline' }
  ]}
/>

Advanced: Custom Plugins

<LuxeEditor 
  initialConfig={{ namespace: 'MyEditor' }}
  showToolbar={true}
>
  {/* Add custom Lexical plugins */}
  <MyCustomPlugin />
</LuxeEditor>

πŸ” Testing Package Locally Before Publishing

cd packages/core

# Create a tarball (without publishing)
npm pack

# This creates: luxe-edit-1.0.0.tgz

# In another project, test it:
npm install /path/to/luxe-edit-1.0.0.tgz

πŸ“‹ Pre-Publishing Checklist

  • Update version in package.json
  • Add description, keywords, repository URL to package.json
  • Write comprehensive README (this file)
  • Fix all TypeScript any types
  • Add prepublishOnly script
  • Test installation: npm pack
  • Test the tarball locally
  • Update changelog
  • Tag git release
  • Run npm publish --otp=YOUR_6_DIGIT_CODE

βœ… Current Features

  1. βœ… Monorepo structure - Clean separation of package and demo
  2. βœ… Modern build setup - Uses tsup (fast, based on esbuild)
  3. βœ… Dual format output - ESM + CommonJS for maximum compatibility
  4. βœ… TypeScript support - Full TypeScript with exported types
  5. βœ… CSS included - Styles are part of the package
  6. βœ… React externalized - React is not bundled (prevents duplicates)
  7. βœ… Proper exports - Modern exports field with types first
  8. βœ… Customizable toolbars - Array-based configuration
  9. βœ… Floating toolbar - Context-aware toolbar for selected text
  10. βœ… Active state tracking - Visual feedback for formatting
  11. βœ… Heading support - Full H1-H6 support
  12. βœ… Text formatting - Bold, Italic, Underline, Strikethrough
  13. βœ… Alignment - Left, Center, Right, Justify
  14. βœ… History - Undo/Redo with proper state management

🎯 Recommended Improvements

1. Add Package Metadata

{
  "description": "A beautiful, customizable rich text editor for React built on Lexical",
  "keywords": ["react", "editor", "lexical", "rich-text", "wysiwyg", "toolbar"],
  "repository": {
    "type": "git",
    "url": "https://github.com/yourusername/luxe-edit.git"
  },
  "homepage": "https://github.com/yourusername/luxe-edit#readme"
}

2. Add Pre-publish Script

{
  "scripts": {
    "build": "tsup",
    "prepublishOnly": "yarn build"
  }
}

3. Improve TypeScript Types

Replace any types with proper Lexical types:

import { InitialConfigType } from '@lexical/react/LexicalComposer';

export interface LuxeEditorProps {
  initialConfig: Partial<InitialConfigType>;
  // ...
}

4. Add Peer Dependencies

{
  "peerDependencies": {
    "react": "^18.0.0 || ^19.0.0",
    "react-dom": "^18.0.0 || ^19.0.0"
  }
}

πŸ“š Resources

πŸŽ‰ Summary

LuxeEdit is a production-ready rich text editor package with:

  • βœ… Complete toolbar system (top + floating)
  • βœ… Full formatting support (text, headings, alignment)
  • βœ… Active state tracking
  • βœ… Customizable toolbar items
  • βœ… TypeScript support
  • βœ… Modern build setup
  • βœ… Ready for npm publishing

The architecture follows modern best practices for React component libraries! πŸš€

About

Luxe Edit is a modern rich-text editor built on Lexical, designed to provide a fast, customizable, and developer-friendly editing experience for web applications.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors