/lexiwind

Combining technologies such as lexical + tailwind

Primary LanguageTypeScript

Lexiwind

This is a simple React application where I utilize Lexiwind, a custom Tailwind CSS variant, for styling and shadcn/ui for UI components.

Installation

  1. npm i lexiwind or pnpm i

Simple Use Example

import { Lexiwind, ToolbarPlugin, useToolbar, RichTextPlugin } from "lexiwind";


export const LexiwindEditor = () => {
  const [value, setValue] = useState("");

  console.log(value)

  return (
    <>
      <Lexiwind value={value} onChange={setValue}>
        <div
          className={
            "lexiwind-border-1 lexiwind-mx-auto lexiwind-max-w-3xl lexiwind-rounded-lg lexiwind-bg-white lexiwind-p-4 lexiwind-shadow-md"
          }
        >
          <ToolbarPlugin>
            <CustomToolbar />
          </ToolbarPlugin>
          <div className="editor-inner">
            <RichTextPlugin />
          </div>
        </div>
      </Lexiwind>
    </>
  );
};

Custom Toolbar Type

type ToolbarContextType = {
  canUndo: boolean;
  canRedo: boolean;
  isBold: boolean;
  isUnderline: boolean;
  isItalic: boolean;
  isStrikethrough: boolean;
  undoHandler: () => void;
  redoHandler: () => void;
  boldHandler: () => void;
  italicHandler: () => void;
  underlineHandler: () => void;
  strikethroughHandler: () => void;
  alignLeftHandler: () => void;
  alignCenterHandler: () => void;
  alignRightHandler: () => void;
  alignJustifyHandler: () => void;
};

Custom Toolbar Example

"use client";

import { useState, useEffect } from "react";
import { Lexiwind,useToolbar } from "lexiwind";
import { Button } from "./ui/Button";

const CustomToolbar = () => {
  const toolbar = useToolbar();

  return (
    <div className="lexiwind-flex lexiwind-flex-wrap lexiwind-gap-3 lexiwind-p-1">
      <Button disabled={!toolbar.canUndo} onClick={toolbar.undoHandler}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <path d="M9 14 4 9l5-5" />
          <path d="M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5v0a5.5 5.5 0 0 1-5.5 5.5H11" />
        </svg>
      </Button>
      <Button disabled={!toolbar.canRedo} onClick={toolbar.redoHandler}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <path d="m15 14 5-5-5-5" />
          <path d="M20 9H9.5A5.5 5.5 0 0 0 4 14.5v0A5.5 5.5 0 0 0 9.5 20H13" />
        </svg>
      </Button>
      <Button
        onClick={toolbar.boldHandler}
        variant={toolbar.isBold ? "active" : "default"}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <path d="M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8" />
        </svg>
      </Button>
      <Button
        onClick={toolbar.italicHandler}
        variant={toolbar.isItalic ? "active" : "default"}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <line x1="19" x2="10" y1="4" y2="4" />
          <line x1="14" x2="5" y1="20" y2="20" />
          <line x1="15" x2="9" y1="4" y2="20" />
        </svg>
      </Button>
      <Button
        onClick={toolbar.underlineHandler}
        variant={toolbar.isUnderline ? "active" : "default"}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <path d="M6 4v6a6 6 0 0 0 12 0V4" />
          <line x1="4" x2="20" y1="20" y2="20" />
        </svg>
      </Button>
      <Button
        onClick={toolbar.strikethroughHandler}
        variant={toolbar.isStrikethrough ? "active" : "default"}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <path d="M16 4H9a3 3 0 0 0-2.83 4" />
          <path d="M14 12a4 4 0 0 1 0 8H6" />
          <line x1="4" x2="20" y1="12" y2="12" />
        </svg>
      </Button>
      <Button onClick={toolbar.alignLeftHandler}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <line x1="21" x2="3" y1="6" y2="6" />
          <line x1="15" x2="3" y1="12" y2="12" />
          <line x1="17" x2="3" y1="18" y2="18" />
        </svg>
      </Button>
      <Button onClick={toolbar.alignCenterHandler}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <line x1="21" x2="3" y1="6" y2="6" />
          <line x1="17" x2="7" y1="12" y2="12" />
          <line x1="19" x2="5" y1="18" y2="18" />
        </svg>
      </Button>
      <Button onClick={toolbar.alignRightHandler}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <line x1="21" x2="3" y1="6" y2="6" />
          <line x1="21" x2="9" y1="12" y2="12" />
          <line x1="21" x2="7" y1="18" y2="18" />
        </svg>
      </Button>
      <Button onClick={toolbar.alignJustifyHandler}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
        >
          <line x1="3" x2="21" y1="6" y2="6" />
          <line x1="3" x2="21" y1="12" y2="12" />
          <line x1="3" x2="21" y1="18" y2="18" />
        </svg>
      </Button>
    </div>
  );
};

// CustomToolbar Component
const CustomToolbar = () => {
  const toolbar = useToolbar();

  return (
    <div className="some-wrapper-toolbar-class">
      <Button disabled={!toolbar.canUndo} onClick={toolbar.undoHandler}>
        ...
      </Button>
      <Button disabled={!toolbar.canRedo} onClick={toolbar.redoHandler}>
        ...
      </Button>
      ...
    </div>
  );
};

Technologies Used

  • React.js
  • tailwind
  • shadcn/ui
  • lexical

Credits

License

This project is licensed under the MIT License.