### Install dependencies Source: https://lexkit.dev/docs/contributing Install all required project dependencies using pnpm. ```bash pnpm install ``` -------------------------------- ### Basic ShadcnTemplate Usage Source: https://lexkit.dev/docs/templates/shadcn Demonstrates how to get started with the ShadcnTemplate in a React application. The `onReady` callback provides access to editor methods. ```typescript import { ShadcnTemplate } from '@lexkit/editor/templates' function MyEditor() { return ( { console.log('Editor ready!') // Access editor methods here editor.injectMarkdown('# Hello World') }} /> ) } ``` -------------------------------- ### Install SHADCN UI Components Source: https://lexkit.dev/docs/templates/shadcn Installs all required SHADCN UI components for the ShadcnTemplate. Ensure you have npm, yarn, or pnpm installed. ```bash npx shadcn@latest add button toggle command tooltip tabs select separator label input dropdown-menu switch dialog collapsible textarea ``` -------------------------------- ### Start the development server Source: https://lexkit.dev/docs/contributing Launch the local development environment to preview changes. ```bash pnpm run dev ``` -------------------------------- ### Basic Setup Source: https://lexkit.dev/docs/extensions/DraggableBlockExtension Import and add the DraggableBlockExtension to your editor for basic drag-and-drop functionality. ```APIDOC ## Basic Setup ### Description Import and add `DraggableBlockExtension` to your editor for basic drag-and-drop functionality. ### Code Example ```javascript function MyEditor() { return ( { console.log('Editor with drag-and-drop ready!') }} /> ) } ``` ``` -------------------------------- ### Create LexKit Editor with Manual RichTextPlugin Setup Source: https://lexkit.dev/docs/get-started Use createEditorSystem with manual RichTextPlugin setup for maximum control. This approach requires explicit configuration of LexicalComposer and RichTextPlugin. ```typescript import { createEditorSystem, boldExtension, italicExtension, historyExtension } from "@lexkit/editor" import { LexicalComposer } from '@lexical/react/LexicalComposer' import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin' import { ContentEditable } from '@lexical/react/LexicalContentEditable' // Define your extensions (without RichText extension) const extensions = [ boldExtension, italicExtension, historyExtension ] as const // Create typed editor system const { Provider, useEditor } = createEditorSystem() return (
} placeholder={
Start writing...
} /> {/* Add your toolbar or other UI here */}
) } ``` -------------------------------- ### Install LexKit Editor Package Source: https://lexkit.dev/docs/installation Install the main LexKit package that provides the type-safe editor system. Use this command with npm. ```bash npm install @lexkit/editor ``` -------------------------------- ### Basic ContextMenuExtension Setup Source: https://lexkit.dev/docs/extensions/ContextMenuExtension Import and add the ContextMenuExtension to your editor's extensions for basic functionality. ```javascript function MyEditor() { return ( { console.log('Editor with context menu ready!') }} /> ) } ``` -------------------------------- ### Setup LexKit Extension System Source: https://lexkit.dev/docs/get-started Set up the LexKit editor system by defining extensions, creating the editor system with a provider, and then using it within a component. This is the foundational step for adding functionality to your editor. ```typescript // 1. Define your extensions const extensions = [MyExtension] as const // 2. Create editor system const { Provider, useEditor } = createEditorSystem() // 3. Use in component function MyEditor() { return ( ) } ``` -------------------------------- ### Create an extension with createExtension Source: https://lexkit.dev/docs/api/extensions Example of using the factory function to define commands, state queries, and lifecycle hooks. ```typescript const myExtension = createExtension({ name: 'my-extension', commands: (editor) => ({ myCommand: () => console.log('Hello!'), }), stateQueries: (editor) => ({ isActive: async () => true, }), initialize: (editor) => { console.log('Extension initialized'); return () => { console.log('Extension cleaned up'); }; } }); ``` -------------------------------- ### Custom Handle Renderer Source: https://lexkit.dev/docs/extensions/DraggableBlockExtension Example of how to implement a custom handle renderer for drag-and-drop functionality. ```APIDOC ## Custom Handle Renderer ### Description Allows for custom rendering of drag handles to provide full control over their appearance and behavior. ### Usage Pass a `handleRenderer` function to the `draggableBlockExtension.configure` method. ### Parameters #### `handleRenderer` Function - **rect** (object) - The bounding box of the element being dragged. - **isDragging** (boolean) - Indicates if the element is currently being dragged. - **onDragStart** (function) - A function to call to initiate the drag operation. ### Example ```javascript function MyEditor() { const extensions = [ draggableBlockExtension.configure({ handleRenderer: ({ rect, isDragging, onDragStart }) => (
⋮⋮
) }) ] as const return } ``` ``` -------------------------------- ### Create an extension with BaseExtension Source: https://lexkit.dev/docs/api/extensions Example of implementing an extension by extending the BaseExtension class. ```typescript class MyExtension extends BaseExtension<'my-extension'> { constructor() { super('my-extension'); } register(editor: LexicalEditor): () => void { // Registration logic return () => { // Cleanup logic }; } getCommands(editor: LexicalEditor) { return { myCommand: () => console.log('Hello!'), }; } getStateQueries(editor: LexicalEditor) { return { isActive: async () => true, }; } } const myExtension = new MyExtension(); ``` -------------------------------- ### Install Lexical Peer Dependencies Source: https://lexkit.dev/docs/installation Install the necessary Lexical packages that LexKit relies on. These are peer dependencies, ensuring compatibility and access to Lexical's features. Use this command with npm. ```bash npm install lexical @lexical/react @lexical/html @lexical/markdown @lexical/list @lexical/rich-text @lexical/selection @lexical/utils ``` -------------------------------- ### DefaultTemplate Component Setup Source: https://lexkit.dev/docs/templates/default Sets up the Lexical editor environment, including theme configuration, extensions, and exposing editor methods via a ref. Handles theme toggling between light and dark modes. ```typescript useEffect(() => { imageExtension.configure({ uploadHandler: async (file: File) => URL.createObjectURL(file), defaultAlignment: "center", resizable: true, pasteListener: { insert: true, replace: true }, debug: false, }); }, []); ``` ```typescript const toggleTheme = () => setEditorTheme(isDark ? "light" : "dark"); ``` ```typescript React.useImperativeHandle(ref, () => methods as DefaultTemplateRef, [methods]); ``` ```typescript const handleReady = (m: DefaultTemplateRef) => { setMethods(m); onReady?.(m); }; ``` ```typescript return (
); ``` -------------------------------- ### Basic DraggableBlockExtension Setup Source: https://lexkit.dev/docs/extensions/DraggableBlockExtension Import and add the DraggableBlockExtension to your editor for basic drag-and-drop functionality. This sets up the extension with default configurations. ```javascript function MyEditor() { return ( { console.log('Editor with drag-and-drop ready!') }} /> ) } ``` -------------------------------- ### Basic LexKit Editor Setup with LinkExtension Source: https://lexkit.dev/docs/extensions/LinkExtension Import and configure LinkExtension for basic editor functionality, including insert and remove link buttons. ```typescript import { createEditorSystem, linkExtension } from '@lexkit/editor' const extensions = [linkExtension] as const const { Provider, useEditor } = createEditorSystem() function MyEditor() { const { commands, activeStates } = useEditor() return ( ) } ``` -------------------------------- ### Custom URL Validation with LinkExtension Source: https://lexkit.dev/docs/extensions/LinkExtension Implement custom URL validation logic by providing a `validateUrl` function. This example only accepts URLs starting with 'https://' and containing 'example.com'. ```typescript import { linkExtension } from '@lexkit/editor' const extensions = [ linkExtension.configure({ autoLinkText: true, validateUrl: (url: string) => { // Custom URL validation return url.startsWith('https://') && url.includes('example.com') } }) ] as const ``` -------------------------------- ### Create Editor System Source: https://lexkit.dev/docs/extensions Use the `createEditorSystem` function with your extensions array to generate a typed Provider and `useEditor` hook. This setup is consistent for all extension types. ```typescript const { Provider, useEditor } = createEditorSystem(); ``` -------------------------------- ### Best Practices for createEditorSystem Source: https://lexkit.dev/docs/api/create-editor-system Offers tips and recommendations for effectively using the createEditorSystem, focusing on type safety, code organization, and editor composition. ```APIDOC ## Best Practices ### Description This section outlines recommended practices to optimize the usage of `createEditorSystem` for better performance, maintainability, and type safety. ### Recommendations - **Use Const Assertions**: Always use `as const` with your extension arrays. This enables full type inference and improves type safety. ```typescript import { $createParagraphNode } from 'lexical'; import { AutoLinkPlugin } from '@lexical/react/LexicalAutoLinkPlugin'; import { LinkNode } from '@lexical/link'; const extensions = [ // ... other extensions AutoLinkPlugin, LinkNode ] as const; ``` - **Single Responsibility**: Create separate editor systems for distinct use cases. Avoid building a single, monolithic system with all possible extensions, as this can lead to complexity and performance issues. - **Type Your Props**: When calling `createEditorSystem`, use `typeof extensions` to maintain type safety for your editor's props and configurations. ```typescript import { createEditorSystem } from 'lexical'; const extensions = [...] as const; type EditorContext = ReturnType>; ``` - **Composition Over Configuration**: Build complex editors by composing simpler, focused editor systems. This approach promotes modularity and reusability, making your codebase easier to manage. ``` -------------------------------- ### Editor State Queries Source: https://lexkit.dev/docs/extensions/DraggableBlockExtension Queries to get the current state of the editor. ```APIDOC ## GET /api/editor/is-dragging ### Description Real-time boolean indicating if a drag operation is in progress. ### Method GET ### Endpoint /api/editor/is-dragging ### Response #### Success Response (200) - **isDragging** (boolean) - True if a drag operation is in progress, false otherwise. #### Response Example ```json { "isDragging": false } ``` ``` -------------------------------- ### Create a feature branch Source: https://lexkit.dev/docs/contributing Standard command to initialize a new branch for development work. ```bash git checkout -b feature/your-feature-name ``` -------------------------------- ### Clone the LexKit repository Source: https://lexkit.dev/docs/contributing Initial step to download the project source code from GitHub. ```bash git clone https://github.com/novincode/lexkit.git cd lexkit ``` -------------------------------- ### Initialize LexKit Editor with Shadcn UI Source: https://lexkit.dev/docs/templates/shadcn Sets up the LexKit editor system with various extensions and integrates it with Shadcn UI components for a rich editing experience. Includes custom themes and styles. ```typescript "use client"; import React, { useState, useEffect, useMemo, useRef, forwardRef, useCallback, useImperativeHandle } from "react"; import { createPortal } from "react-dom"; import { // Core system createEditorSystem, // Extensions boldExtension, italicExtension, underlineExtension, strikethroughExtension, linkExtension, horizontalRuleExtension, TableExtension, listExtension, historyExtension, imageExtension, blockFormatExtension, htmlExtension, MarkdownExtension, codeExtension, codeFormatExtension, HTMLEmbedExtension, commandPaletteExtension, floatingToolbarExtension, contextMenuExtension, DraggableBlockExtension, // Utilities ALL_MARKDOWN_TRANSFORMERS, // Types type ExtractCommands, type ExtractStateQueries, type BaseCommands, } from "@lexkit/editor"; import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin"; import { ContentEditable } from "@lexical/react/LexicalContentEditable"; import { LexicalEditor } from "lexical"; import { Bold, Italic, Underline, Strikethrough, List, ListOrdered, Undo, Redo, Image as ImageIcon, AlignLeft, AlignCenter, AlignRight, Upload, Link as LinkIcon, Unlink, Minus, Code, Terminal, Table as TableIcon, FileCode, Eye, Pencil, Command as CommandIcon, Type, Quote, FileText, Hash, X, CloudUpload, Globe, ChevronDown, Indent, Outdent } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Toggle } from "@/components/ui/toggle"; import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandShortcut } from "@/components/ui/command"; import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from "@/components/ui/tooltip"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Separator } from "@/components/ui/separator"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { Switch } from "@/components/ui/switch"; import { Dialog as ShadcnDialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { Textarea } from "@/components/ui/textarea"; import { commandsToCommandPaletteItems, registerKeyboardShortcuts, } from "./commands"; import { shadcnTheme } from "./theme"; import { cn } from "@/lib/utils"; import "./shadcn-styles.css"; // Editor Mode Types type EditorMode = "visual" | "html" | "markdown"; // Table Config Type type TableConfig = { rows: number; columns: number; includeHeaders: boolean; }; // Ref interface for parent control export interface ShadcnTemplateRef { injectMarkdown: (content: string) => void; injectHTML: (content: string) => void; getMarkdown: () => string; getHTML: () => string; } // Custom Shadcn-styled context menu renderer function ShadcnContextMenuRenderer(props: { items: any[]; position: { x: number; y: number }; onClose: () => void; className: string; style?: React.CSSProperties; itemClassName: string; itemStyle?: React.CSSProperties; disabledItemClassName: string; disabledItemStyle?: React.CSSProperties; }) { const { items, position, onClose } = props; return createPortal(
e.stopPropagation()} onContextMenu={(e) => e.preventDefault()} > {items.map((item: any, index: number) => (
{ if (!item.disabled && item.action) { item.action(); onClose(); } }} > ``` -------------------------------- ### Initialize DefaultTemplate Source: https://lexkit.dev/docs/templates/default Basic implementation of the DefaultTemplate component, demonstrating the onReady callback and markdown injection. ```typescript import { DefaultTemplate } from '@/components/DefaultTemplate' function MyEditor() { return ( { console.log('Editor ready!') // Access editor methods here editor.injectMarkdown('# Hello World') }} /> ) } ``` -------------------------------- ### Define a basic extension with createExtension Source: https://lexkit.dev/docs/extensions Use the createExtension factory function to initialize a new extension with a name and command set. ```typescript import { createExtension } from '@lexkit/editor' const MyExtension = createExtension({ name: 'my-extension', commands: (editor) => ({ // Define your commands here myCommand: () => console.log('Hello!') }) }) ``` -------------------------------- ### createEditorSystem API Reference Source: https://lexkit.dev/docs/api/create-editor-system Provides a detailed reference for the createEditorSystem API, including its React component, configuration options, and available utilities. ```APIDOC ## API Reference: createEditorSystem ### Description This section details the `createEditorSystem` API, which is used to initialize and configure a Lexical editor instance. ### `Provider` - **Description**: A React component that provides the editor context to its children. It should wrap your editor components. - **Props**: - `extensions` (Exts): Required. An array of Lexical extensions to be used in the editor. - `config` (EditorConfig): Optional. Configuration options for the editor. ### Available Utilities - **`commands`**: Access to all available commands exposed by your extensions. - **`activeStates`**: Provides the current state of all formatters and selections within the editor. - **`editor`**: The raw Lexical editor instance, useful for advanced use cases. - **`export` / `import`**: Utilities for serializing and deserializing editor content. ``` -------------------------------- ### contextMenuExtension.configure Source: https://lexkit.dev/docs/extensions/ContextMenuExtension Configures the behavior, appearance, and custom rendering logic for the context menu extension. ```APIDOC ## configure(config) ### Description Configures the context menu extension with custom renderers, behavior settings, and styling. ### Parameters #### Request Body - **defaultRenderer** (Component) - Optional - A custom React component to render the context menu. - **preventDefault** (boolean) - Optional - Whether to prevent the default browser context menu. - **initPriority** (number) - Optional - Priority for registration order. - **theme** (object) - Optional - CSS class names for container and items. - **styles** (object) - Optional - Inline style overrides for the container and items. ``` -------------------------------- ### Configure Theme and Options Source: https://lexkit.dev/docs/api/create-editor-system Customize the editor's appearance and behavior by passing a configuration object to the Provider. This includes defining custom themes and other settings. ```typescript import { createEditorSystem, defaultLexKitTheme } from '@lexkit/editor' const extensions = [boldExtension, italicExtension] as const const { Provider, useEditor } = createEditorSystem() const customTheme = { ...defaultLexKitTheme, text: { bold: 'font-bold text-blue-600', }, } function MyEditor() { return ( ) } ``` -------------------------------- ### Implement Main Editor Content Source: https://lexkit.dev/docs/templates/shadcn Orchestrates editor state, command registration, and content injection methods. ```typescript function EditorContent({ className, onReady, }: { className?: string; onReady?: (methods: ShadcnTemplateRef) => void; }) { const { commands, hasExtension, activeStates, lexical: editor } = useEditor(); const [mode, setMode] = useState("visual"); const [content, setContent] = useState({ html: "", markdown: "" }); const [commandPaletteOpen, setCommandPaletteOpen] = useState(false); const [linkDialogOpen, setLinkDialogOpen] = useState(false); const [imageDialogOpen, setImageDialogOpen] = useState(false); const [linkInitial, setLinkInitial] = useState({ url: "" }); const commandsRef = useRef(commands); // Store onReady in ref to avoid infinite loops const onReadyRef = useRef(onReady); const readyCalledRef = useRef(false); useEffect(() => { onReadyRef.current = onReady; }, [onReady]); useEffect(() => { commandsRef.current = commands; }, [commands]); const methods = useMemo( () => ({ injectMarkdown: (content: string) => { if (editor) { editor.update(() => { commandsRef.current.importFromMarkdown(content, { immediate: true }); }); } }, injectHTML: (content: string) => { if (editor) { editor.update(() => { commandsRef.current.importFromHTML(content); }); } }, getMarkdown: () => commandsRef.current.exportToMarkdown(), getHTML: () => commandsRef.current.exportToHTML(), }), [], // No dependencies to prevent recreation ); const { handlers: imageHandlers } = useImageHandlers(commands, editor); const openLinkDialog = useCallback( (options: { initialUrl?: string } = {}) => { const { initialUrl = "" } = options; setLinkInitial({ url: initialUrl }); setLinkDialogOpen(true); }, [], ); const handleLinkSubmit = useCallback( ({ url }: { url: string }) => { commands.insertLink(url); }, [commands], ); const handleImageSubmit = useCallback( ({ activeTab, url, alt, caption, file }: { activeTab: "upload" | "url"; url: string; alt: string; caption: string; file: File | null; }) => { if (activeTab === "upload" && file) { imageHandlers.insertImageFromFile(file, alt, caption); } else if (activeTab === "url" && url.trim()) { imageHandlers.insertImageFromUrl(url.trim(), alt, caption); } }, [imageHandlers], ); useEffect(() => { if (!editor || !commands || readyCalledRef.current) return; const paletteCommands = commandsToCommandPaletteItems(commands); paletteCommands.forEach((cmd) => commands.registerCommand(cmd)); const originalShowCommand = commands.showCommandPalette; ``` -------------------------------- ### Customize behavior and appearance Source: https://lexkit.dev/docs/extensions/ContextMenuExtension Configure global context menu settings including browser default prevention, priority, and CSS theme overrides. ```javascript const customContextMenu = contextMenuExtension.configure({ preventDefault: true, // Prevent browser context menu initPriority: 100, // High priority for early registration theme: { container: 'my-context-menu', item: 'my-menu-item', itemDisabled: 'my-menu-item-disabled' }, styles: { container: { backgroundColor: '#f8f9fa', borderRadius: '12px', boxShadow: '0 8px 32px rgba(0,0,0,0.1)' }, item: { padding: '12px 16px', fontSize: '14px' } } }) ``` -------------------------------- ### Context Menu Commands Source: https://lexkit.dev/docs/extensions/ContextMenuExtension Programmatic commands to manage context menu providers and visibility. ```APIDOC ## registerProvider(provider) ### Description Registers a new context menu provider. ## unregisterProvider(id) ### Description Removes a registered context menu provider by its ID. ## showContextMenu(config) ### Description Displays a context menu programmatically at a specific position. ### Parameters #### Request Body - **items** (array) - Required - List of menu items with labels and actions. - **position** (object) - Required - Coordinates {x, y} for the menu display. ## hideContextMenu() ### Description Hides the currently visible context menu. ``` -------------------------------- ### Configuration Options Source: https://lexkit.dev/docs/extensions/DraggableBlockExtension Customize the drag-and-drop behavior and appearance using various configuration options. ```APIDOC ## With Configuration ### Description Customize drag behavior by configuring the `draggableBlockExtension` with various options. ### Code Example ```javascript const extensionsWithDraggable = [ draggableBlockExtension.configure({ showMoveButtons: true, // Show up/down buttons showUpButton: true, // Enable move up button showDownButton: true, // Enable move down button buttonStackPosition: 'left', // Position buttons on left enableTextSelectionDrag: true, // Allow dragging via text selection theme: { handle: 'my-drag-handle', handleActive: 'my-drag-handle-active', blockDragging: 'my-block-dragging', dropIndicator: 'my-drop-indicator' } }), historyExtension ] as const ``` ### Configuration Options | Option | Type | Description | |---|---|---| | showMoveButtons | boolean | Show up/down arrow buttons for manual block movement. | | showUpButton | boolean | Enable the move up button specifically. | | showDownButton | boolean | Enable the move down button specifically. | | buttonStackPosition | 'left' | 'right' | Position of the move buttons relative to blocks. | | enableTextSelectionDrag | boolean | Allow dragging blocks by selecting text within them. | | theme | object | CSS class names for customizing handles, indicators, and animations. | | handleRenderer | function | Custom renderer for drag handles with full control. | | buttonsRenderer | function | Custom renderer for move up/down buttons. | | dropIndicatorRenderer | function | Custom renderer for the drop indicator line. | ``` -------------------------------- ### Create Typed Editor System Source: https://lexkit.dev/docs/templates/default Initializes the LexKit editor system with the defined extensions, providing typed access to commands and state queries. ```typescript // Create typed editor system const { Provider, useEditor } = createEditorSystem(); ``` -------------------------------- ### Configure Markdown Extension Source: https://lexkit.dev/docs/templates/shadcn Creates and configures a Markdown extension for Lexical, specifying custom transformers to be used. ```typescript // Create markdown extension instance for this template const markdownExt = new MarkdownExtension().configure({ customTransformers: ALL_MARKDOWN_TRANSFORMERS, }); ``` -------------------------------- ### Image Handling and Alignment Source: https://lexkit.dev/docs/templates/default Dropdown menus for image insertion and alignment options, including file upload triggers. ```jsx {/* Image */} {hasExtension("image") && (
} isOpen={showImageDropdown} onOpenChange={setShowImageDropdown} > {activeStates.imageSelected && ( } isOpen={showAlignDropdown} onOpenChange={setShowAlignDropdown} > )}
)} ``` -------------------------------- ### LexKit Monorepo Structure Source: https://lexkit.dev/docs/contributing Overview of the project directory layout and package organization. ```text lexkit/ ├── apps/ │ └── web/ # Main web application │ ├── app/ # Next.js app directory │ ├── components/ # Shared components │ └── lib/ # Utility functions ├── packages/ │ ├── editor/ # Core editor package │ ├── ui/ # UI component library │ ├── meta/ # Metadata utilities │ ├── eslint-config/ # ESLint configurations │ └── typescript-config/ # TypeScript configurations ├── package.json ├── pnpm-workspace.yaml ├── turbo.json └── tsconfig.json ``` -------------------------------- ### Run quality checks Source: https://lexkit.dev/docs/contributing Execute linting, type checking, and testing scripts before submitting a pull request. ```bash pnpm run lint pnpm run type-check pnpm run test ``` -------------------------------- ### isContextMenuOpen Source: https://lexkit.dev/docs/extensions/ContextMenuExtension Query the current visibility state of the context menu. ```APIDOC ## isContextMenuOpen() ### Description Returns a boolean indicating whether the context menu is currently visible. ### Response - **result** (boolean) - True if open, false otherwise. ``` -------------------------------- ### History and Global Toolbar Actions Source: https://lexkit.dev/docs/templates/default Undo/redo buttons, command palette trigger, and theme toggle functionality. ```jsx {/* History */} {hasExtension("history") && (
)} {/* Command Palette */}
{/* Theme Toggle */}
``` -------------------------------- ### createEditorSystem Factory Source: https://lexkit.dev/docs/api/create-editor-system The createEditorSystem function analyzes an array of extensions to generate a typed Provider component and useEditor hook. ```APIDOC ## createEditorSystem ### Description A factory function that creates a fully typed editor system based on provided extensions. It generates a Provider component and a useEditor hook with compile-time type safety. ### Method Function Call ### Parameters #### Generic Parameters - **T** (Extension[]) - Required - A const array of extensions to define the editor's capabilities. ### Request Example ```typescript const extensions = [boldExtension, italicExtension] as const; const { Provider, useEditor } = createEditorSystem(); ``` ### Response #### Success Response - **Provider** (Component) - React component to wrap editor content. - **useEditor** (Hook) - Hook to access commands and active states. ``` -------------------------------- ### Create LexKit Editor with RichText Extension Source: https://lexkit.dev/docs/get-started Use createEditorSystem with RichTextExtension for type safety and modularity. Configure placeholder and class names for the editor container, content editable area, and placeholder. ```typescript import { createEditorSystem, richTextExtension, boldExtension, italicExtension, historyExtension } from "@lexkit/editor" // Define your extensions (as const for type safety) const extensions = [ richTextExtension.configure({ placeholder: "Start writing...", classNames: { container: "my-editor-container", contentEditable: "my-editor-content", placeholder: "my-editor-placeholder" } }), boldExtension, italicExtension, historyExtension ] as const // Create typed editor system const { Provider, useEditor } = createEditorSystem() function MyEditor() { return (
{/* RichText extension renders automatically */} {/* Add your toolbar or other UI here */}
) } ``` -------------------------------- ### Configure Extension-Specific Themes Source: https://lexkit.dev/docs/theming Define custom styles for draggable blocks and floating toolbars within the LexKitTheme object. ```typescript const themeWithExtensions: LexKitTheme = { // Base properties paragraph: 'editor-paragraph', text: { bold: 'editor-bold', }, // Draggable blocks extension draggable: { handle: 'absolute -left-8 top-0 w-6 h-6 bg-gray-200 hover:bg-gray-300 rounded cursor-move flex items-center justify-center', handleHover: 'bg-gray-300', handleDragging: 'bg-blue-500', blockDragging: 'opacity-50 border-2 border-blue-500 border-dashed', dropIndicator: 'h-1 bg-blue-500 my-2 rounded', upButton: 'absolute -left-6 -top-3 w-5 h-5 bg-white border border-gray-300 rounded-full flex items-center justify-center text-xs hover:bg-gray-50', downButton: 'absolute -left-6 -bottom-3 w-5 h-5 bg-white border border-gray-300 rounded-full flex items-center justify-center text-xs hover:bg-gray-50', blockIsDragging: 'shadow-lg transform rotate-2', buttonStack: 'flex flex-col gap-1', }, // Floating toolbar extension floatingToolbar: { container: 'absolute z-50 bg-white border border-gray-300 rounded-lg shadow-lg p-2 flex gap-1', button: 'w-8 h-8 flex items-center justify-center rounded hover:bg-gray-100 text-sm', buttonActive: 'bg-blue-100 text-blue-700', }, } ``` -------------------------------- ### Implement Source View Components Source: https://lexkit.dev/docs/templates/shadcn Textarea-based components for raw HTML or Markdown editing, utilizing a shared theme configuration. ```typescript function HTMLSourceView({ htmlContent, onHtmlChange, }: { htmlContent: string; onHtmlChange: (html: string) => void; }) { return (