luxe-edit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -0
- package/dist/index.css +116 -0
- package/dist/index.d.mts +38 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +2 -0
- package/package.json +69 -0
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# @luxe-edit/core
|
|
2
|
+
|
|
3
|
+
A beautiful, customizable rich text editor for React built on Lexical with customizable toolbars and floating toolbar support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @luxe-edit/core
|
|
9
|
+
# or
|
|
10
|
+
yarn add @luxe-edit/core
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @luxe-edit/core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { LuxeEditor } from '@luxe-edit/core';
|
|
19
|
+
import '@luxe-edit/core/index.css';
|
|
20
|
+
|
|
21
|
+
function App() {
|
|
22
|
+
return (
|
|
23
|
+
<LuxeEditor
|
|
24
|
+
initialConfig={{
|
|
25
|
+
namespace: 'MyEditor',
|
|
26
|
+
theme: {}
|
|
27
|
+
}}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- ✅ Rich text formatting (Bold, Italic, Underline, Strikethrough)
|
|
36
|
+
- ✅ Headings (H1-H6)
|
|
37
|
+
- ✅ Text and background colors
|
|
38
|
+
- ✅ Alignment options
|
|
39
|
+
- ✅ Undo/Redo
|
|
40
|
+
- ✅ Customizable toolbars
|
|
41
|
+
- ✅ Floating toolbar
|
|
42
|
+
- ✅ TypeScript support
|
|
43
|
+
|
|
44
|
+
## Documentation
|
|
45
|
+
|
|
46
|
+
For complete documentation, examples, and API reference, please visit the [main repository README](../../README.md).
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
|
|
50
|
+
MIT
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--luxe-primary: #3b82f6;
|
|
3
|
+
--luxe-border: #e5e7eb;
|
|
4
|
+
--luxe-bg: #ffffff;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.luxe-editor-container {
|
|
8
|
+
border: 1px solid var(--luxe-border);
|
|
9
|
+
border-radius: 8px;
|
|
10
|
+
background: var(--luxe-bg);
|
|
11
|
+
padding: 1rem;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.luxe-input {
|
|
15
|
+
min-height: 200px;
|
|
16
|
+
outline: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.luxe-bold { font-weight: bold; }
|
|
20
|
+
.luxe-italic { font-style: italic; }
|
|
21
|
+
.luxe-underline {
|
|
22
|
+
text-decoration: underline !important;
|
|
23
|
+
}
|
|
24
|
+
.luxe-strikethrough {
|
|
25
|
+
text-decoration: line-through !important;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Support combined formats */
|
|
29
|
+
.luxe-underline.luxe-strikethrough {
|
|
30
|
+
text-decoration: underline line-through !important;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Heading styles */
|
|
34
|
+
.luxe-heading-h1 {
|
|
35
|
+
font-size: 2em;
|
|
36
|
+
font-weight: bold;
|
|
37
|
+
margin: 0.67em 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.luxe-heading-h2 {
|
|
41
|
+
font-size: 1.5em;
|
|
42
|
+
font-weight: bold;
|
|
43
|
+
margin: 0.75em 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.luxe-heading-h3 {
|
|
47
|
+
font-size: 1.17em;
|
|
48
|
+
font-weight: bold;
|
|
49
|
+
margin: 0.83em 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.luxe-heading-h4 {
|
|
53
|
+
font-size: 1em;
|
|
54
|
+
font-weight: bold;
|
|
55
|
+
margin: 1em 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.luxe-heading-h5 {
|
|
59
|
+
font-size: 0.83em;
|
|
60
|
+
font-weight: bold;
|
|
61
|
+
margin: 1.17em 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.luxe-heading-h6 {
|
|
65
|
+
font-size: 0.67em;
|
|
66
|
+
font-weight: bold;
|
|
67
|
+
margin: 1.33em 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.luxe-paragraph {
|
|
71
|
+
margin: 1em 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Fullscreen mode */
|
|
75
|
+
.luxe-editor-fullscreen {
|
|
76
|
+
position: fixed !important;
|
|
77
|
+
top: 0 !important;
|
|
78
|
+
left: 0 !important;
|
|
79
|
+
right: 0 !important;
|
|
80
|
+
bottom: 0 !important;
|
|
81
|
+
width: 100vw !important;
|
|
82
|
+
height: 100vh !important;
|
|
83
|
+
z-index: 9999 !important;
|
|
84
|
+
margin: 0 !important;
|
|
85
|
+
border-radius: 0 !important;
|
|
86
|
+
background: var(--luxe-bg, #ffffff);
|
|
87
|
+
display: flex !important;
|
|
88
|
+
flex-direction: column;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.luxe-editor-fullscreen .luxe-input {
|
|
92
|
+
flex: 1;
|
|
93
|
+
min-height: auto;
|
|
94
|
+
height: 100%;
|
|
95
|
+
overflow-y: auto;
|
|
96
|
+
padding: 2rem;
|
|
97
|
+
max-width: 900px;
|
|
98
|
+
margin: 0 auto;
|
|
99
|
+
width: 100%;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.luxe-editor-fullscreen .luxe-editor-container {
|
|
103
|
+
padding: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Link styles */
|
|
107
|
+
.luxe-input a {
|
|
108
|
+
color: #3b82f6;
|
|
109
|
+
text-decoration: underline;
|
|
110
|
+
cursor: pointer;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.luxe-input a:hover {
|
|
114
|
+
color: #2563eb;
|
|
115
|
+
text-decoration: underline;
|
|
116
|
+
}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import React__default from 'react';
|
|
4
|
+
import { InitialConfigType } from '@lexical/react/LexicalComposer';
|
|
5
|
+
|
|
6
|
+
type ToolbarItemType = 'undo' | 'redo' | 'divider' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'heading5' | 'heading6' | 'paragraph' | 'alignLeft' | 'alignCenter' | 'alignRight' | 'alignJustify' | 'textColor' | 'backgroundColor' | 'fullscreen' | 'headingDropdown' | 'link';
|
|
7
|
+
interface ToolbarItem {
|
|
8
|
+
type: ToolbarItemType;
|
|
9
|
+
label?: string;
|
|
10
|
+
icon?: React__default.ReactNode;
|
|
11
|
+
color?: string;
|
|
12
|
+
colors?: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface FloatingToolbarPluginProps {
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
items?: ToolbarItem[];
|
|
18
|
+
}
|
|
19
|
+
declare function FloatingToolbarPlugin({ enabled, items }: FloatingToolbarPluginProps): React.ReactPortal | null;
|
|
20
|
+
|
|
21
|
+
interface ToolbarProps {
|
|
22
|
+
items: ToolbarItem[];
|
|
23
|
+
onFullscreenToggle?: () => void;
|
|
24
|
+
isFullscreen?: boolean;
|
|
25
|
+
}
|
|
26
|
+
declare function Toolbar({ items, onFullscreenToggle, isFullscreen }: ToolbarProps): react_jsx_runtime.JSX.Element;
|
|
27
|
+
|
|
28
|
+
interface LuxeEditorProps {
|
|
29
|
+
initialConfig: Partial<InitialConfigType>;
|
|
30
|
+
showFloatingToolbar?: boolean;
|
|
31
|
+
showToolbar?: boolean;
|
|
32
|
+
toolbarItems?: ToolbarItem[];
|
|
33
|
+
floatingToolbarItems?: ToolbarItem[];
|
|
34
|
+
children?: React__default.ReactNode;
|
|
35
|
+
}
|
|
36
|
+
declare function LuxeEditor({ initialConfig, showFloatingToolbar, showToolbar, toolbarItems, floatingToolbarItems, children }: LuxeEditorProps): react_jsx_runtime.JSX.Element;
|
|
37
|
+
|
|
38
|
+
export { FloatingToolbarPlugin, LuxeEditor, type LuxeEditorProps, Toolbar, type ToolbarItem, type ToolbarItemType };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import React__default from 'react';
|
|
4
|
+
import { InitialConfigType } from '@lexical/react/LexicalComposer';
|
|
5
|
+
|
|
6
|
+
type ToolbarItemType = 'undo' | 'redo' | 'divider' | 'bold' | 'italic' | 'underline' | 'strikethrough' | 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'heading5' | 'heading6' | 'paragraph' | 'alignLeft' | 'alignCenter' | 'alignRight' | 'alignJustify' | 'textColor' | 'backgroundColor' | 'fullscreen' | 'headingDropdown' | 'link';
|
|
7
|
+
interface ToolbarItem {
|
|
8
|
+
type: ToolbarItemType;
|
|
9
|
+
label?: string;
|
|
10
|
+
icon?: React__default.ReactNode;
|
|
11
|
+
color?: string;
|
|
12
|
+
colors?: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface FloatingToolbarPluginProps {
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
items?: ToolbarItem[];
|
|
18
|
+
}
|
|
19
|
+
declare function FloatingToolbarPlugin({ enabled, items }: FloatingToolbarPluginProps): React.ReactPortal | null;
|
|
20
|
+
|
|
21
|
+
interface ToolbarProps {
|
|
22
|
+
items: ToolbarItem[];
|
|
23
|
+
onFullscreenToggle?: () => void;
|
|
24
|
+
isFullscreen?: boolean;
|
|
25
|
+
}
|
|
26
|
+
declare function Toolbar({ items, onFullscreenToggle, isFullscreen }: ToolbarProps): react_jsx_runtime.JSX.Element;
|
|
27
|
+
|
|
28
|
+
interface LuxeEditorProps {
|
|
29
|
+
initialConfig: Partial<InitialConfigType>;
|
|
30
|
+
showFloatingToolbar?: boolean;
|
|
31
|
+
showToolbar?: boolean;
|
|
32
|
+
toolbarItems?: ToolbarItem[];
|
|
33
|
+
floatingToolbarItems?: ToolbarItem[];
|
|
34
|
+
children?: React__default.ReactNode;
|
|
35
|
+
}
|
|
36
|
+
declare function LuxeEditor({ initialConfig, showFloatingToolbar, showToolbar, toolbarItems, floatingToolbarItems, children }: LuxeEditorProps): react_jsx_runtime.JSX.Element;
|
|
37
|
+
|
|
38
|
+
export { FloatingToolbarPlugin, LuxeEditor, type LuxeEditorProps, Toolbar, type ToolbarItem, type ToolbarItemType };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";var ge=Object.create;var _=Object.defineProperty;var fe=Object.getOwnPropertyDescriptor;var he=Object.getOwnPropertyNames;var be=Object.getPrototypeOf,xe=Object.prototype.hasOwnProperty;var me=(e,s)=>{for(var r in s)_(e,r,{get:s[r],enumerable:!0})},V=(e,s,r,t)=>{if(s&&typeof s=="object"||typeof s=="function")for(let d of he(s))!xe.call(e,d)&&d!==r&&_(e,d,{get:()=>s[d],enumerable:!(t=fe(s,d))||t.enumerable});return e};var ye=(e,s,r)=>(r=e!=null?ge(be(e)):{},V(s||!e||!e.__esModule?_(r,"default",{value:e,enumerable:!0}):r,e)),Ce=e=>V(_({},"__esModule",{value:!0}),e);var Re={};me(Re,{FloatingToolbarPlugin:()=>G,LuxeEditor:()=>we,Toolbar:()=>B});module.exports=Ce(Re);var Q=ye(require("react")),ae=require("@lexical/react/LexicalComposer"),le=require("@lexical/react/LexicalRichTextPlugin"),ie=require("@lexical/react/LexicalContentEditable"),se=require("@lexical/react/LexicalHistoryPlugin"),de=require("@lexical/react/LexicalErrorBoundary"),pe=require("@lexical/react/LexicalLinkPlugin"),ce=require("@lexical/rich-text"),X=require("@lexical/link"),J=require("lexical");var oe=require("@lexical/react/LexicalComposerContext"),v=require("lexical"),q=require("@lexical/selection"),j=require("@lexical/rich-text"),D=require("react"),ne=require("react-dom");var ee=require("@lexical/react/LexicalComposerContext"),te=require("@lexical/utils"),n=require("lexical"),Y=require("@lexical/selection"),P=require("@lexical/rich-text"),W=require("@lexical/link"),f=require("react"),i=require("react/jsx-runtime"),Z=["#000000","#ffffff","#ff0000","#00ff00","#0000ff","#ffff00","#ff00ff","#00ffff","#808080","#800000","#008000","#000080","#808000","#800080","#008080"];function U(e){return{undo:"\u21B6",redo:"\u21B7",divider:"",bold:"B",italic:"I",underline:"U",strikethrough:"S",heading1:"H1",heading2:"H2",heading3:"H3",heading4:"H4",heading5:"H5",heading6:"H6",paragraph:"P",alignLeft:"\u2B05",alignCenter:"\u2B0C",alignRight:"\u27A1",alignJustify:"\u2B0C",textColor:"A",backgroundColor:"\u2B1B",fullscreen:"\u26F6",headingDropdown:"Normal",link:"\u{1F517}"}[e]||e}function Te(){return(0,i.jsx)("div",{style:{width:"1px",height:"24px",background:"#e5e7eb",margin:"0 4px"}})}function ve({item:e,onAction:s}){let[r,t]=(0,f.useState)(!1),d=(0,f.useRef)(null),h=e.colors||Z;return(0,f.useEffect)(()=>{let l=x=>{d.current&&!d.current.contains(x.target)&&t(!1)};if(r)return document.addEventListener("mousedown",l),()=>document.removeEventListener("mousedown",l)},[r]),e.color?(0,i.jsx)("button",{onClick:()=>s(e,e.color),title:`${e.type==="textColor"?"Text":"Background"} Color: ${e.color}`,style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:e.type==="backgroundColor"?e.color:"white",color:e.type==="textColor"?e.color:"#000",cursor:"pointer",borderRadius:"4px",minWidth:"40px",height:"32px",display:"flex",alignItems:"center",justifyContent:"center"},children:e.icon||U(e.type)}):(0,i.jsxs)("div",{style:{position:"relative"},ref:d,children:[(0,i.jsxs)("button",{onClick:()=>t(!r),title:`${e.type==="textColor"?"Text":"Background"} Color`,style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:"white",cursor:"pointer",borderRadius:"4px",minWidth:"40px",height:"32px",display:"flex",alignItems:"center",justifyContent:"center",position:"relative"},children:[e.icon||(0,i.jsx)("span",{style:{display:"block",width:"20px",height:"20px",background:e.type==="backgroundColor"?"linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%)":"currentColor",backgroundSize:e.type==="backgroundColor"?"8px 8px":"auto",backgroundPosition:e.type==="backgroundColor"?"0 0, 0 4px, 4px -4px, -4px 0px":"auto"},children:e.type==="textColor"&&(0,i.jsx)("span",{style:{color:"#000",fontSize:"12px"},children:"A"})}),(0,i.jsx)("span",{style:{marginLeft:"4px",fontSize:"10px"},children:"\u25BC"})]}),r&&(0,i.jsxs)("div",{style:{position:"absolute",top:"100%",left:0,marginTop:"4px",background:"white",border:"1px solid #e5e7eb",borderRadius:"6px",padding:"8px",display:"grid",gridTemplateColumns:"repeat(5, 1fr)",gap:"4px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1)",zIndex:1e3,minWidth:"160px"},children:[h.map(l=>(0,i.jsxs)("button",{onClick:()=>{s(e,l),t(!1)},title:l,style:{width:"24px",height:"24px",borderRadius:"4px",border:e.type==="textColor"?`3px solid ${l}`:"1px solid #e5e7eb",background:e.type==="backgroundColor"?l:"white",color:e.type==="textColor"?"#000":"inherit",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",fontSize:"12px",fontWeight:"bold",position:"relative"},children:[e.type==="textColor"&&(0,i.jsx)("span",{style:{color:l,fontSize:"14px",fontWeight:"bold",lineHeight:"1"},children:"A"}),e.type==="backgroundColor"&&l==="#ffffff"&&(0,i.jsx)("span",{style:{color:"#000",fontSize:"10px",border:"1px solid #ccc",width:"12px",height:"12px",display:"block"},children:"\u25A1"})]},l)),(0,i.jsx)("input",{type:"color",onChange:l=>{s(e,l.target.value),t(!1)},style:{gridColumn:"1 / -1",width:"100%",height:"32px",border:"1px solid #e5e7eb",borderRadius:"4px",cursor:"pointer"}})]})]})}function ke({item:e,onAction:s,currentBlockType:r="paragraph"}){let[t,d]=(0,f.useState)(!1),h=(0,f.useRef)(null);(0,f.useEffect)(()=>{let c=o=>{h.current&&!h.current.contains(o.target)&&d(!1)};if(t)return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[t]);let l=()=>r==="paragraph"?"Normal":r.startsWith("h")?`Heading ${r.replace("h","")}`:"Normal",x=c=>{s(e,void 0,c),d(!1)},m=[{value:"paragraph",label:"Normal"},{value:"h1",label:"Heading 1"},{value:"h2",label:"Heading 2"},{value:"h3",label:"Heading 3"},{value:"h4",label:"Heading 4"},{value:"h5",label:"Heading 5"},{value:"h6",label:"Heading 6"}];return(0,i.jsxs)("div",{style:{position:"relative"},ref:h,children:[(0,i.jsxs)("button",{onClick:()=>d(!t),title:"Heading",style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:"white",cursor:"pointer",borderRadius:"4px",minWidth:"100px",height:"32px",display:"flex",alignItems:"center",justifyContent:"space-between",position:"relative",fontSize:r==="paragraph"?"14px":r==="h1"?"20px":r==="h2"?"18px":r==="h3"?"16px":"14px",fontWeight:r!=="paragraph"?"bold":"normal"},children:[(0,i.jsx)("span",{children:e.label||l()}),(0,i.jsx)("span",{style:{marginLeft:"8px",fontSize:"10px"},children:"\u25BC"})]}),t&&(0,i.jsx)("div",{style:{position:"absolute",top:"100%",left:0,marginTop:"4px",background:"white",border:"1px solid #e5e7eb",borderRadius:"6px",padding:"4px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1)",zIndex:1e3,minWidth:"150px"},children:m.map(c=>(0,i.jsx)("button",{onClick:()=>x(c.value),style:{width:"100%",padding:"8px 12px",border:"none",background:r===c.value?"#e5e7eb":"transparent",cursor:"pointer",borderRadius:"4px",textAlign:"left",fontSize:c.value==="paragraph"?"14px":c.value==="h1"?"20px":c.value==="h2"?"18px":c.value==="h3"?"16px":"14px",fontWeight:c.value!=="paragraph"?"bold":"normal",display:"flex",alignItems:"center"},onMouseEnter:o=>{r!==c.value&&(o.currentTarget.style.background="#f3f4f6")},onMouseLeave:o=>{r!==c.value?o.currentTarget.style.background="transparent":o.currentTarget.style.background="#e5e7eb"},children:c.label},c.value))})]})}function Ne({item:e,onAction:s,editor:r}){let[t,d]=(0,f.useState)(!1),[h,l]=(0,f.useState)(""),[x,m]=(0,f.useState)(!1),c=(0,f.useRef)(null),o=(0,f.useRef)(null);(0,f.useEffect)(()=>{let a=()=>{r.getEditorState().read(()=>{let H=(0,n.$getSelection)();if((0,n.$isRangeSelection)(H)){let L=H.getNodes(),w=null;for(let K of L){let p=K.getParent();for(;p!==null;){if((0,W.$isLinkNode)(p)){w=p;break}p=p.getParent()}if(w)break}w&&(0,W.$isLinkNode)(w)?(m(!0),l(w.getURL())):(m(!1),l(""))}else m(!1),l("")})},b=r.registerUpdateListener(()=>{a()}),g=r.registerCommand(n.SELECTION_CHANGE_COMMAND,()=>(a(),!1),n.COMMAND_PRIORITY_LOW);return a(),()=>{b(),g()}},[r]),(0,f.useEffect)(()=>{let a=b=>{c.current&&!c.current.contains(b.target)&&d(!1)};if(t)return document.addEventListener("mousedown",a),setTimeout(()=>o.current?.focus(),0),()=>document.removeEventListener("mousedown",a)},[t,x,h]);let y=()=>{if(!h.trim()){r.dispatchCommand(W.TOGGLE_LINK_COMMAND,null),d(!1),l("");return}let a=h.trim();!a.startsWith("http://")&&!a.startsWith("https://")&&!a.startsWith("mailto:")&&!a.startsWith("#")&&!a.startsWith("/")&&(a="https://"+a),r.dispatchCommand(W.TOGGLE_LINK_COMMAND,a),d(!1),l("")},u=()=>{r.dispatchCommand(W.TOGGLE_LINK_COMMAND,null),d(!1),l("")},T=a=>{a.key==="Enter"?(a.preventDefault(),y()):a.key==="Escape"&&(d(!1),l(""))};return(0,i.jsxs)("div",{style:{position:"relative"},ref:c,children:[(0,i.jsx)("button",{onClick:()=>{d(!t)},title:x?"Edit Link":"Insert Link",style:{padding:"6px 12px",border:"none",background:x?"#e5e7eb":"transparent",cursor:"pointer",borderRadius:"4px",minWidth:"32px",display:"flex",alignItems:"center",justifyContent:"center",transition:"background-color 0.2s"},onMouseEnter:a=>{x||(a.currentTarget.style.background="#f3f4f6")},onMouseLeave:a=>{x?a.currentTarget.style.background="#e5e7eb":a.currentTarget.style.background="transparent"},children:e.icon||U(e.type)}),t&&(0,i.jsxs)("div",{style:{position:"absolute",top:"100%",left:0,marginTop:"4px",background:"white",border:"1px solid #e5e7eb",borderRadius:"6px",padding:"12px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1)",zIndex:1e3,minWidth:"300px"},children:[(0,i.jsx)("input",{ref:o,type:"text",placeholder:"Enter URL (e.g., https://example.com)",value:h,onChange:a=>l(a.target.value),onKeyDown:T,style:{width:"100%",padding:"8px",border:"1px solid #e5e7eb",borderRadius:"4px",fontSize:"14px",marginBottom:"8px"}}),(0,i.jsxs)("div",{style:{display:"flex",gap:"8px",justifyContent:"flex-end"},children:[x&&(0,i.jsx)("button",{onClick:u,style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:"white",cursor:"pointer",borderRadius:"4px",fontSize:"14px",color:"#dc2626"},children:"Remove"}),(0,i.jsx)("button",{onClick:()=>d(!1),style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:"white",cursor:"pointer",borderRadius:"4px",fontSize:"14px"},children:"Cancel"}),(0,i.jsx)("button",{onClick:y,style:{padding:"6px 12px",border:"none",background:"#3b82f6",color:"white",cursor:"pointer",borderRadius:"4px",fontSize:"14px"},children:x?"Update":"Insert"})]})]})]})}function Ee({item:e,active:s=!1,disabled:r=!1,onAction:t,currentBlockType:d}){let l=e.type.startsWith("heading")&&e.type!=="headingDropdown"?parseInt(e.type.replace("heading","")):null,x=e.label||U(e.type);return e.type==="divider"?(0,i.jsx)(Te,{}):e.type==="headingDropdown"?(0,i.jsx)(ke,{item:e,onAction:t,currentBlockType:d}):e.type==="textColor"||e.type==="backgroundColor"?(0,i.jsx)(ve,{item:e,onAction:t}):(0,i.jsx)("button",{onClick:()=>t(e),disabled:r,title:e.type.charAt(0).toUpperCase()+e.type.slice(1).replace(/([A-Z])/g," $1").trim(),style:{padding:"6px 12px",border:"none",background:s?"#e5e7eb":"transparent",cursor:r?"not-allowed":"pointer",borderRadius:"4px",fontWeight:e.type==="bold"?"bold":"normal",fontStyle:e.type==="italic"?"italic":"normal",textDecoration:e.type==="underline"?"underline":e.type==="strikethrough"?"line-through":"none",fontSize:l?`${18-l*2}px`:"14px",minWidth:"32px",display:"flex",alignItems:"center",justifyContent:"center",transition:"background-color 0.2s",opacity:r?.5:1},onMouseEnter:m=>{!r&&!s&&(m.currentTarget.style.background="#f3f4f6")},onMouseLeave:m=>{s?m.currentTarget.style.background="#e5e7eb":m.currentTarget.style.background="transparent"},children:e.icon||x})}function B({items:e,onFullscreenToggle:s,isFullscreen:r=!1}){let[t]=(0,ee.useLexicalComposerContext)(),[d,h]=(0,f.useState)(!1),[l,x]=(0,f.useState)(!1),[m,c]=(0,f.useState)(!1),[o,y]=(0,f.useState)(!1),[u,T]=(0,f.useState)(!1),[a,b]=(0,f.useState)(!1),[g,H]=(0,f.useState)("paragraph"),L=(0,f.useCallback)(()=>{let p=(0,n.$getSelection)();if((0,n.$isRangeSelection)(p)){c(p.hasFormat("bold")),y(p.hasFormat("italic")),T(p.hasFormat("underline")),b(p.hasFormat("strikethrough"));let R=p.anchor.getNode(),S=R.getKey()==="root"?R:R.getTopLevelElementOrThrow(),C=S.getKey();if(t.getElementByKey(C)!==null){let E=(0,P.$isHeadingNode)(S)?S.getTag():S.getType();H(E)}}},[t]);(0,f.useEffect)(()=>(0,te.mergeRegister)(t.registerUpdateListener(({editorState:p})=>{p.read(()=>{L()})}),t.registerCommand(n.SELECTION_CHANGE_COMMAND,()=>(L(),!1),n.COMMAND_PRIORITY_LOW),t.registerCommand(n.CAN_UNDO_COMMAND,p=>(h(p),!1),n.COMMAND_PRIORITY_LOW),t.registerCommand(n.CAN_REDO_COMMAND,p=>(x(p),!1),n.COMMAND_PRIORITY_LOW)),[t,L]);let w=(0,f.useCallback)((p,R,S)=>{let{type:C}=p;if(C==="fullscreen"){s?.();return}if(C==="undo"){t.dispatchCommand(n.UNDO_COMMAND,void 0);return}if(C==="redo"){t.dispatchCommand(n.REDO_COMMAND,void 0);return}if(C==="textColor"&&R){t.update(()=>{let N=(0,n.$getSelection)();(0,n.$isRangeSelection)(N)&&(0,Y.$patchStyleText)(N,{color:R})});return}if(C==="backgroundColor"&&R){t.update(()=>{let N=(0,n.$getSelection)();(0,n.$isRangeSelection)(N)&&(0,Y.$patchStyleText)(N,{"background-color":R})});return}if(C==="bold"||C==="italic"||C==="underline"||C==="strikethrough"){t.dispatchCommand(n.FORMAT_TEXT_COMMAND,C);return}if(C==="alignLeft"){t.dispatchCommand(n.FORMAT_ELEMENT_COMMAND,"left");return}if(C==="alignCenter"){t.dispatchCommand(n.FORMAT_ELEMENT_COMMAND,"center");return}if(C==="alignRight"){t.dispatchCommand(n.FORMAT_ELEMENT_COMMAND,"right");return}if(C==="alignJustify"){t.dispatchCommand(n.FORMAT_ELEMENT_COMMAND,"justify");return}if(C==="headingDropdown"&&S){if(S==="paragraph")t.update(()=>{let N=(0,n.$getSelection)();if((0,n.$isRangeSelection)(N)){let E=N.anchor.getNode(),k=E.getKey()==="root"?E:E.getTopLevelElementOrThrow(),I=k.getKey();if(t.getElementByKey(I)!==null&&(0,P.$isHeadingNode)(k)&&(0,n.$isElementNode)(k)){let $=(0,n.$createParagraphNode)(),O=k.getChildren();$.append(...O),k.replace($),$.selectEnd()}}});else{let N=S;t.update(()=>{let E=(0,n.$getSelection)();if((0,n.$isRangeSelection)(E)){let k=E.anchor.getNode(),I=k.getKey()==="root"?k:k.getTopLevelElementOrThrow(),A=I.getKey();if(t.getElementByKey(A)!==null&&(0,n.$isElementNode)(I)){let O=(0,P.$createHeadingNode)(N),F=I.getChildren();O.append(...F),I.replace(O),O.selectEnd()}}})}return}if(C.startsWith("heading")&&C!=="headingDropdown"){let E=`h${parseInt(C.replace("heading",""))}`;t.update(()=>{let k=(0,n.$getSelection)();if((0,n.$isRangeSelection)(k)){let I=k.anchor.getNode(),A=I.getKey()==="root"?I:I.getTopLevelElementOrThrow(),$=A.getKey();if(t.getElementByKey($)!==null&&(0,n.$isElementNode)(A)){let F=(0,P.$createHeadingNode)(E),ue=A.getChildren();F.append(...ue),A.replace(F),F.selectEnd()}}});return}if(C==="paragraph"){t.update(()=>{let N=(0,n.$getSelection)();if((0,n.$isRangeSelection)(N)){let E=N.anchor.getNode(),k=E.getKey()==="root"?E:E.getTopLevelElementOrThrow(),I=k.getKey();if(t.getElementByKey(I)!==null&&(0,P.$isHeadingNode)(k)&&(0,n.$isElementNode)(k)){let $=(0,n.$createParagraphNode)(),O=k.getChildren();$.append(...O),k.replace($),$.selectEnd()}}});return}},[t,s]),K=p=>{switch(p){case"undo":return{disabled:!d};case"redo":return{disabled:!l};case"bold":return{active:m};case"italic":return{active:o};case"underline":return{active:u};case"strikethrough":return{active:a};case"fullscreen":return{active:r};case"heading1":return{active:g==="h1"};case"heading2":return{active:g==="h2"};case"heading3":return{active:g==="h3"};case"heading4":return{active:g==="h4"};case"heading5":return{active:g==="h5"};case"heading6":return{active:g==="h6"};case"paragraph":return{active:g==="paragraph"};default:return{}}};return(0,i.jsx)("div",{className:"luxe-toolbar",style:{display:"flex",gap:"4px",alignItems:"center",background:"white",borderBottom:"1px solid #e5e7eb",borderRadius:"8px 8px 0 0",padding:"8px",flexWrap:"wrap"},children:e.map((p,R)=>{let S=K(p.type);return p.type==="link"?(0,i.jsx)(Ne,{item:p,onAction:w,editor:t},`${p.type}-${R}`):(0,i.jsx)(Ee,{item:p,active:S.active,disabled:S.disabled,onAction:w,currentBlockType:g},`${p.type}-${R}`)})})}var z=require("react/jsx-runtime"),Ie=[{type:"bold"},{type:"italic"},{type:"underline"}];function Le(e){let s=["bold","italic","underline","strikethrough","textColor","backgroundColor"];return e.filter(r=>s.includes(r.type))}function G({enabled:e=!0,items:s}){let r=s?Le(s).slice(0,4):Ie,[t]=(0,oe.useLexicalComposerContext)(),[d,h]=(0,D.useState)(null),[l,x]=(0,D.useState)(null);(0,D.useEffect)(()=>{let o=t.getRootElement();o&&x(o)},[t]);let m=(0,D.useCallback)(()=>{if(!l)return;let o=window.getSelection();if(!o||o.rangeCount===0||o.isCollapsed){h(null);return}try{let y=o.getRangeAt(0);if(!l.contains(y.commonAncestorContainer)){h(null);return}let u=y.getBoundingClientRect();u&&u.width>0&&u.height>0?t.getEditorState().read(()=>{let T=(0,v.$getSelection)();T&&(0,v.$isRangeSelection)(T)&&!T.isCollapsed()?h({x:u.left+u.width/2,y:u.top-40}):h(null)}):h(null)}catch{h(null)}},[t,l]);(0,D.useEffect)(()=>{if(!l)return;let o=t.registerUpdateListener(()=>{setTimeout(()=>m(),10)});return()=>{o()}},[t,l,m]),(0,D.useEffect)(()=>{let o=()=>{setTimeout(()=>m(),50)},y=()=>{setTimeout(()=>m(),50)},u=()=>{setTimeout(()=>m(),50)};return document.addEventListener("mouseup",o),document.addEventListener("keyup",y),document.addEventListener("selectionchange",u),()=>{document.removeEventListener("mouseup",o),document.removeEventListener("keyup",y),document.removeEventListener("selectionchange",u)}},[m]);let c=(0,D.useCallback)((o,y)=>{let{type:u}=o;if(u==="textColor"&&y){t.update(()=>{let T=(0,v.$getSelection)();(0,v.$isRangeSelection)(T)&&(0,q.$patchStyleText)(T,{color:y})});return}if(u==="backgroundColor"&&y){t.update(()=>{let T=(0,v.$getSelection)();(0,v.$isRangeSelection)(T)&&(0,q.$patchStyleText)(T,{"background-color":y})});return}if(u==="bold"||u==="italic"||u==="underline"||u==="strikethrough"){t.dispatchCommand(v.FORMAT_TEXT_COMMAND,u);return}if(u.startsWith("heading")){let a=`h${parseInt(u.replace("heading",""))}`;t.update(()=>{let b=(0,v.$getSelection)();if((0,v.$isRangeSelection)(b)){let g=b.anchor.getNode(),H=g.getKey()==="root"?g:g.getTopLevelElementOrThrow(),L=H.getKey();if(t.getElementByKey(L)!==null&&(0,v.$isElementNode)(H)){let K=(0,j.$createHeadingNode)(a),p=H.getChildren();K.append(...p),H.replace(K),K.selectEnd()}}});return}if(u==="paragraph"){t.update(()=>{let T=(0,v.$getSelection)();if((0,v.$isRangeSelection)(T)){let a=T.anchor.getNode(),b=a.getKey()==="root"?a:a.getTopLevelElementOrThrow(),g=b.getKey();if(t.getElementByKey(g)!==null&&(0,j.$isHeadingNode)(b)&&(0,v.$isElementNode)(b)){let L=(0,v.$createParagraphNode)(),w=b.getChildren();L.append(...w),b.replace(L),L.selectEnd()}}});return}},[t]);return!e||!r||r.length===0||!d?null:(0,ne.createPortal)((0,z.jsx)("div",{className:"luxe-floating-toolbar",style:{position:"fixed",top:`${d.y}px`,left:`${d.x}px`,transform:"translateX(-50%)",display:"flex",gap:"4px",background:"white",border:"1px solid #e5e7eb",borderRadius:"6px",padding:"4px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1)",zIndex:1e3},children:r.map((o,y)=>{let u=o.label||U(o.type),a=o.type.startsWith("heading")?parseInt(o.type.replace("heading","")):null;if(o.type==="textColor"||o.type==="backgroundColor"){let b=o.colors||Z.slice(0,6);return(0,z.jsx)("div",{style:{display:"flex",gap:"2px"},children:o.color?(0,z.jsx)("button",{onClick:()=>c(o,o.color),title:`${o.type==="textColor"?"Text":"Background"} Color`,style:{padding:"4px 8px",border:"1px solid #e5e7eb",background:o.type==="backgroundColor"?o.color:"white",color:o.type==="textColor"?o.color:"#000",cursor:"pointer",borderRadius:"4px",minWidth:"28px",height:"28px"},children:o.type==="textColor"?"A":"\u25A0"}):b.map(g=>(0,z.jsx)("button",{onClick:()=>c(o,g),title:g,style:{width:"24px",height:"24px",border:o.type==="textColor"?`3px solid ${g}`:"1px solid #e5e7eb",background:o.type==="backgroundColor"?g:"white",color:o.type==="textColor"?"#000":"inherit",cursor:"pointer",borderRadius:"3px",fontSize:"10px",display:"flex",alignItems:"center",justifyContent:"center"},children:o.type==="textColor"&&(0,z.jsx)("span",{style:{color:g,fontSize:"12px",fontWeight:"bold",lineHeight:"1"},children:"A"})},g))},`${o.type}-${y}`)}return(0,z.jsx)("button",{onClick:()=>c(o),title:o.type.charAt(0).toUpperCase()+o.type.slice(1),style:{padding:"6px 12px",border:"none",background:"transparent",cursor:"pointer",borderRadius:"4px",fontWeight:o.type==="bold"?"bold":"normal",fontStyle:o.type==="italic"?"italic":"normal",textDecoration:o.type==="underline"?"underline":o.type==="strikethrough"?"line-through":"none",fontSize:a?`${18-a*2}px`:"14px",minWidth:"32px",display:"flex",alignItems:"center",justifyContent:"center",transition:"background-color 0.2s"},onMouseEnter:b=>{b.currentTarget.style.background="#f3f4f6"},onMouseLeave:b=>{b.currentTarget.style.background="transparent"},children:o.icon||u},`${o.type}-${y}`)})}),document.body)}var M=require("react/jsx-runtime"),re={paragraph:"luxe-paragraph",heading:{h1:"luxe-heading-h1",h2:"luxe-heading-h2",h3:"luxe-heading-h3",h4:"luxe-heading-h4",h5:"luxe-heading-h5",h6:"luxe-heading-h6"},text:{bold:"luxe-bold",italic:"luxe-italic",underline:"luxe-underline",strikethrough:"luxe-strikethrough"}};function we({initialConfig:e,showFloatingToolbar:s=!0,showToolbar:r=!1,toolbarItems:t,floatingToolbarItems:d,children:h}){let[l,x]=Q.default.useState(!1),m=[ce.HeadingNode,J.ParagraphNode,J.TextNode,X.LinkNode,X.AutoLinkNode],c=e.theme?{...re,...e.theme}:re,{theme:o,...y}=e,u={namespace:"LuxeEditor",theme:c,nodes:m,onError:g=>console.error(g),...y},a=t||[{type:"bold"},{type:"italic"}],b=Q.default.useCallback(()=>{x(g=>!g)},[]);return(0,M.jsx)(ae.LexicalComposer,{initialConfig:u,children:(0,M.jsxs)("div",{className:`luxe-editor-container ${l?"luxe-editor-fullscreen":""}`,children:[r&&a&&a.length>0&&(0,M.jsx)(B,{items:a,onFullscreenToggle:b,isFullscreen:l}),(0,M.jsx)(le.RichTextPlugin,{contentEditable:(0,M.jsx)(ie.ContentEditable,{className:"luxe-input"}),placeholder:(0,M.jsx)("div",{className:"luxe-placeholder",children:"Start writing..."}),ErrorBoundary:de.LexicalErrorBoundary}),(0,M.jsx)(se.HistoryPlugin,{}),(0,M.jsx)(pe.LinkPlugin,{}),s&&(0,M.jsx)(G,{enabled:!0,items:d||a}),h]})})}0&&(module.exports={FloatingToolbarPlugin,LuxeEditor,Toolbar});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import pe from"react";import{LexicalComposer as $e}from"@lexical/react/LexicalComposer";import{RichTextPlugin as De}from"@lexical/react/LexicalRichTextPlugin";import{ContentEditable as Ae}from"@lexical/react/LexicalContentEditable";import{HistoryPlugin as Oe}from"@lexical/react/LexicalHistoryPlugin";import{LexicalErrorBoundary as Ke}from"@lexical/react/LexicalErrorBoundary";import{LinkPlugin as Pe}from"@lexical/react/LexicalLinkPlugin";import{HeadingNode as We}from"@lexical/rich-text";import{LinkNode as ze,AutoLinkNode as Fe}from"@lexical/link";import{ParagraphNode as Ue,TextNode as _e}from"lexical";import{useLexicalComposerContext as Ee}from"@lexical/react/LexicalComposerContext";import{$getSelection as U,$isRangeSelection as _,FORMAT_TEXT_COMMAND as Ie,$createParagraphNode as Le,$isElementNode as le}from"lexical";import{$patchStyleText as ie}from"@lexical/selection";import{$createHeadingNode as we,$isHeadingNode as Re}from"@lexical/rich-text";import{useCallback as se,useEffect as Q,useState as de}from"react";import{createPortal as Se}from"react-dom";import{useLexicalComposerContext as ge}from"@lexical/react/LexicalComposerContext";import{mergeRegister as fe}from"@lexical/utils";import{$getSelection as D,$isRangeSelection as A,$createParagraphNode as ee,$isElementNode as B,CAN_REDO_COMMAND as he,CAN_UNDO_COMMAND as be,COMMAND_PRIORITY_LOW as G,FORMAT_ELEMENT_COMMAND as j,FORMAT_TEXT_COMMAND as xe,REDO_COMMAND as me,SELECTION_CHANGE_COMMAND as ae,UNDO_COMMAND as ye}from"lexical";import{$patchStyleText as te}from"@lexical/selection";import{$createHeadingNode as oe,$isHeadingNode as J}from"@lexical/rich-text";import{$isLinkNode as ne,TOGGLE_LINK_COMMAND as Y}from"@lexical/link";import{useCallback as re,useEffect as z,useState as N,useRef as X}from"react";import{jsx as c,jsxs as M}from"react/jsx-runtime";var Z=["#000000","#ffffff","#ff0000","#00ff00","#0000ff","#ffff00","#ff00ff","#00ffff","#808080","#800000","#008000","#000080","#808000","#800080","#008080"];function F(e){return{undo:"\u21B6",redo:"\u21B7",divider:"",bold:"B",italic:"I",underline:"U",strikethrough:"S",heading1:"H1",heading2:"H2",heading3:"H3",heading4:"H4",heading5:"H5",heading6:"H6",paragraph:"P",alignLeft:"\u2B05",alignCenter:"\u2B0C",alignRight:"\u27A1",alignJustify:"\u2B0C",textColor:"A",backgroundColor:"\u2B1B",fullscreen:"\u26F6",headingDropdown:"Normal",link:"\u{1F517}"}[e]||e}function Ce(){return c("div",{style:{width:"1px",height:"24px",background:"#e5e7eb",margin:"0 4px"}})}function Te({item:e,onAction:f}){let[r,t]=N(!1),p=X(null),u=e.colors||Z;return z(()=>{let a=h=>{p.current&&!p.current.contains(h.target)&&t(!1)};if(r)return document.addEventListener("mousedown",a),()=>document.removeEventListener("mousedown",a)},[r]),e.color?c("button",{onClick:()=>f(e,e.color),title:`${e.type==="textColor"?"Text":"Background"} Color: ${e.color}`,style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:e.type==="backgroundColor"?e.color:"white",color:e.type==="textColor"?e.color:"#000",cursor:"pointer",borderRadius:"4px",minWidth:"40px",height:"32px",display:"flex",alignItems:"center",justifyContent:"center"},children:e.icon||F(e.type)}):M("div",{style:{position:"relative"},ref:p,children:[M("button",{onClick:()=>t(!r),title:`${e.type==="textColor"?"Text":"Background"} Color`,style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:"white",cursor:"pointer",borderRadius:"4px",minWidth:"40px",height:"32px",display:"flex",alignItems:"center",justifyContent:"center",position:"relative"},children:[e.icon||c("span",{style:{display:"block",width:"20px",height:"20px",background:e.type==="backgroundColor"?"linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%)":"currentColor",backgroundSize:e.type==="backgroundColor"?"8px 8px":"auto",backgroundPosition:e.type==="backgroundColor"?"0 0, 0 4px, 4px -4px, -4px 0px":"auto"},children:e.type==="textColor"&&c("span",{style:{color:"#000",fontSize:"12px"},children:"A"})}),c("span",{style:{marginLeft:"4px",fontSize:"10px"},children:"\u25BC"})]}),r&&M("div",{style:{position:"absolute",top:"100%",left:0,marginTop:"4px",background:"white",border:"1px solid #e5e7eb",borderRadius:"6px",padding:"8px",display:"grid",gridTemplateColumns:"repeat(5, 1fr)",gap:"4px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1)",zIndex:1e3,minWidth:"160px"},children:[u.map(a=>M("button",{onClick:()=>{f(e,a),t(!1)},title:a,style:{width:"24px",height:"24px",borderRadius:"4px",border:e.type==="textColor"?`3px solid ${a}`:"1px solid #e5e7eb",background:e.type==="backgroundColor"?a:"white",color:e.type==="textColor"?"#000":"inherit",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",fontSize:"12px",fontWeight:"bold",position:"relative"},children:[e.type==="textColor"&&c("span",{style:{color:a,fontSize:"14px",fontWeight:"bold",lineHeight:"1"},children:"A"}),e.type==="backgroundColor"&&a==="#ffffff"&&c("span",{style:{color:"#000",fontSize:"10px",border:"1px solid #ccc",width:"12px",height:"12px",display:"block"},children:"\u25A1"})]},a)),c("input",{type:"color",onChange:a=>{f(e,a.target.value),t(!1)},style:{gridColumn:"1 / -1",width:"100%",height:"32px",border:"1px solid #e5e7eb",borderRadius:"4px",cursor:"pointer"}})]})]})}function ve({item:e,onAction:f,currentBlockType:r="paragraph"}){let[t,p]=N(!1),u=X(null);z(()=>{let i=o=>{u.current&&!u.current.contains(o.target)&&p(!1)};if(t)return document.addEventListener("mousedown",i),()=>document.removeEventListener("mousedown",i)},[t]);let a=()=>r==="paragraph"?"Normal":r.startsWith("h")?`Heading ${r.replace("h","")}`:"Normal",h=i=>{f(e,void 0,i),p(!1)},b=[{value:"paragraph",label:"Normal"},{value:"h1",label:"Heading 1"},{value:"h2",label:"Heading 2"},{value:"h3",label:"Heading 3"},{value:"h4",label:"Heading 4"},{value:"h5",label:"Heading 5"},{value:"h6",label:"Heading 6"}];return M("div",{style:{position:"relative"},ref:u,children:[M("button",{onClick:()=>p(!t),title:"Heading",style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:"white",cursor:"pointer",borderRadius:"4px",minWidth:"100px",height:"32px",display:"flex",alignItems:"center",justifyContent:"space-between",position:"relative",fontSize:r==="paragraph"?"14px":r==="h1"?"20px":r==="h2"?"18px":r==="h3"?"16px":"14px",fontWeight:r!=="paragraph"?"bold":"normal"},children:[c("span",{children:e.label||a()}),c("span",{style:{marginLeft:"8px",fontSize:"10px"},children:"\u25BC"})]}),t&&c("div",{style:{position:"absolute",top:"100%",left:0,marginTop:"4px",background:"white",border:"1px solid #e5e7eb",borderRadius:"6px",padding:"4px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1)",zIndex:1e3,minWidth:"150px"},children:b.map(i=>c("button",{onClick:()=>h(i.value),style:{width:"100%",padding:"8px 12px",border:"none",background:r===i.value?"#e5e7eb":"transparent",cursor:"pointer",borderRadius:"4px",textAlign:"left",fontSize:i.value==="paragraph"?"14px":i.value==="h1"?"20px":i.value==="h2"?"18px":i.value==="h3"?"16px":"14px",fontWeight:i.value!=="paragraph"?"bold":"normal",display:"flex",alignItems:"center"},onMouseEnter:o=>{r!==i.value&&(o.currentTarget.style.background="#f3f4f6")},onMouseLeave:o=>{r!==i.value?o.currentTarget.style.background="transparent":o.currentTarget.style.background="#e5e7eb"},children:i.label},i.value))})]})}function ke({item:e,onAction:f,editor:r}){let[t,p]=N(!1),[u,a]=N(""),[h,b]=N(!1),i=X(null),o=X(null);z(()=>{let n=()=>{r.getEditorState().read(()=>{let R=D();if(A(R)){let E=R.getNodes(),I=null;for(let K of E){let l=K.getParent();for(;l!==null;){if(ne(l)){I=l;break}l=l.getParent()}if(I)break}I&&ne(I)?(b(!0),a(I.getURL())):(b(!1),a(""))}else b(!1),a("")})},g=r.registerUpdateListener(()=>{n()}),d=r.registerCommand(ae,()=>(n(),!1),G);return n(),()=>{g(),d()}},[r]),z(()=>{let n=g=>{i.current&&!i.current.contains(g.target)&&p(!1)};if(t)return document.addEventListener("mousedown",n),setTimeout(()=>o.current?.focus(),0),()=>document.removeEventListener("mousedown",n)},[t,h,u]);let x=()=>{if(!u.trim()){r.dispatchCommand(Y,null),p(!1),a("");return}let n=u.trim();!n.startsWith("http://")&&!n.startsWith("https://")&&!n.startsWith("mailto:")&&!n.startsWith("#")&&!n.startsWith("/")&&(n="https://"+n),r.dispatchCommand(Y,n),p(!1),a("")},s=()=>{r.dispatchCommand(Y,null),p(!1),a("")},y=n=>{n.key==="Enter"?(n.preventDefault(),x()):n.key==="Escape"&&(p(!1),a(""))};return M("div",{style:{position:"relative"},ref:i,children:[c("button",{onClick:()=>{p(!t)},title:h?"Edit Link":"Insert Link",style:{padding:"6px 12px",border:"none",background:h?"#e5e7eb":"transparent",cursor:"pointer",borderRadius:"4px",minWidth:"32px",display:"flex",alignItems:"center",justifyContent:"center",transition:"background-color 0.2s"},onMouseEnter:n=>{h||(n.currentTarget.style.background="#f3f4f6")},onMouseLeave:n=>{h?n.currentTarget.style.background="#e5e7eb":n.currentTarget.style.background="transparent"},children:e.icon||F(e.type)}),t&&M("div",{style:{position:"absolute",top:"100%",left:0,marginTop:"4px",background:"white",border:"1px solid #e5e7eb",borderRadius:"6px",padding:"12px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1)",zIndex:1e3,minWidth:"300px"},children:[c("input",{ref:o,type:"text",placeholder:"Enter URL (e.g., https://example.com)",value:u,onChange:n=>a(n.target.value),onKeyDown:y,style:{width:"100%",padding:"8px",border:"1px solid #e5e7eb",borderRadius:"4px",fontSize:"14px",marginBottom:"8px"}}),M("div",{style:{display:"flex",gap:"8px",justifyContent:"flex-end"},children:[h&&c("button",{onClick:s,style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:"white",cursor:"pointer",borderRadius:"4px",fontSize:"14px",color:"#dc2626"},children:"Remove"}),c("button",{onClick:()=>p(!1),style:{padding:"6px 12px",border:"1px solid #e5e7eb",background:"white",cursor:"pointer",borderRadius:"4px",fontSize:"14px"},children:"Cancel"}),c("button",{onClick:x,style:{padding:"6px 12px",border:"none",background:"#3b82f6",color:"white",cursor:"pointer",borderRadius:"4px",fontSize:"14px"},children:h?"Update":"Insert"})]})]})]})}function Ne({item:e,active:f=!1,disabled:r=!1,onAction:t,currentBlockType:p}){let a=e.type.startsWith("heading")&&e.type!=="headingDropdown"?parseInt(e.type.replace("heading","")):null,h=e.label||F(e.type);return e.type==="divider"?c(Ce,{}):e.type==="headingDropdown"?c(ve,{item:e,onAction:t,currentBlockType:p}):e.type==="textColor"||e.type==="backgroundColor"?c(Te,{item:e,onAction:t}):c("button",{onClick:()=>t(e),disabled:r,title:e.type.charAt(0).toUpperCase()+e.type.slice(1).replace(/([A-Z])/g," $1").trim(),style:{padding:"6px 12px",border:"none",background:f?"#e5e7eb":"transparent",cursor:r?"not-allowed":"pointer",borderRadius:"4px",fontWeight:e.type==="bold"?"bold":"normal",fontStyle:e.type==="italic"?"italic":"normal",textDecoration:e.type==="underline"?"underline":e.type==="strikethrough"?"line-through":"none",fontSize:a?`${18-a*2}px`:"14px",minWidth:"32px",display:"flex",alignItems:"center",justifyContent:"center",transition:"background-color 0.2s",opacity:r?.5:1},onMouseEnter:b=>{!r&&!f&&(b.currentTarget.style.background="#f3f4f6")},onMouseLeave:b=>{f?b.currentTarget.style.background="#e5e7eb":b.currentTarget.style.background="transparent"},children:e.icon||h})}function q({items:e,onFullscreenToggle:f,isFullscreen:r=!1}){let[t]=ge(),[p,u]=N(!1),[a,h]=N(!1),[b,i]=N(!1),[o,x]=N(!1),[s,y]=N(!1),[n,g]=N(!1),[d,R]=N("paragraph"),E=re(()=>{let l=D();if(A(l)){i(l.hasFormat("bold")),x(l.hasFormat("italic")),y(l.hasFormat("underline")),g(l.hasFormat("strikethrough"));let L=l.anchor.getNode(),w=L.getKey()==="root"?L:L.getTopLevelElementOrThrow(),m=w.getKey();if(t.getElementByKey(m)!==null){let v=J(w)?w.getTag():w.getType();R(v)}}},[t]);z(()=>fe(t.registerUpdateListener(({editorState:l})=>{l.read(()=>{E()})}),t.registerCommand(ae,()=>(E(),!1),G),t.registerCommand(be,l=>(u(l),!1),G),t.registerCommand(he,l=>(h(l),!1),G)),[t,E]);let I=re((l,L,w)=>{let{type:m}=l;if(m==="fullscreen"){f?.();return}if(m==="undo"){t.dispatchCommand(ye,void 0);return}if(m==="redo"){t.dispatchCommand(me,void 0);return}if(m==="textColor"&&L){t.update(()=>{let T=D();A(T)&&te(T,{color:L})});return}if(m==="backgroundColor"&&L){t.update(()=>{let T=D();A(T)&&te(T,{"background-color":L})});return}if(m==="bold"||m==="italic"||m==="underline"||m==="strikethrough"){t.dispatchCommand(xe,m);return}if(m==="alignLeft"){t.dispatchCommand(j,"left");return}if(m==="alignCenter"){t.dispatchCommand(j,"center");return}if(m==="alignRight"){t.dispatchCommand(j,"right");return}if(m==="alignJustify"){t.dispatchCommand(j,"justify");return}if(m==="headingDropdown"&&w){if(w==="paragraph")t.update(()=>{let T=D();if(A(T)){let v=T.anchor.getNode(),C=v.getKey()==="root"?v:v.getTopLevelElementOrThrow(),k=C.getKey();if(t.getElementByKey(k)!==null&&J(C)&&B(C)){let S=ee(),$=C.getChildren();S.append(...$),C.replace(S),S.selectEnd()}}});else{let T=w;t.update(()=>{let v=D();if(A(v)){let C=v.anchor.getNode(),k=C.getKey()==="root"?C:C.getTopLevelElementOrThrow(),H=k.getKey();if(t.getElementByKey(H)!==null&&B(k)){let $=oe(T),W=k.getChildren();$.append(...W),k.replace($),$.selectEnd()}}})}return}if(m.startsWith("heading")&&m!=="headingDropdown"){let v=`h${parseInt(m.replace("heading",""))}`;t.update(()=>{let C=D();if(A(C)){let k=C.anchor.getNode(),H=k.getKey()==="root"?k:k.getTopLevelElementOrThrow(),S=H.getKey();if(t.getElementByKey(S)!==null&&B(H)){let W=oe(v),ue=H.getChildren();W.append(...ue),H.replace(W),W.selectEnd()}}});return}if(m==="paragraph"){t.update(()=>{let T=D();if(A(T)){let v=T.anchor.getNode(),C=v.getKey()==="root"?v:v.getTopLevelElementOrThrow(),k=C.getKey();if(t.getElementByKey(k)!==null&&J(C)&&B(C)){let S=ee(),$=C.getChildren();S.append(...$),C.replace(S),S.selectEnd()}}});return}},[t,f]),K=l=>{switch(l){case"undo":return{disabled:!p};case"redo":return{disabled:!a};case"bold":return{active:b};case"italic":return{active:o};case"underline":return{active:s};case"strikethrough":return{active:n};case"fullscreen":return{active:r};case"heading1":return{active:d==="h1"};case"heading2":return{active:d==="h2"};case"heading3":return{active:d==="h3"};case"heading4":return{active:d==="h4"};case"heading5":return{active:d==="h5"};case"heading6":return{active:d==="h6"};case"paragraph":return{active:d==="paragraph"};default:return{}}};return c("div",{className:"luxe-toolbar",style:{display:"flex",gap:"4px",alignItems:"center",background:"white",borderBottom:"1px solid #e5e7eb",borderRadius:"8px 8px 0 0",padding:"8px",flexWrap:"wrap"},children:e.map((l,L)=>{let w=K(l.type);return l.type==="link"?c(ke,{item:l,onAction:I,editor:t},`${l.type}-${L}`):c(Ne,{item:l,active:w.active,disabled:w.disabled,onAction:I,currentBlockType:d},`${l.type}-${L}`)})})}import{jsx as P}from"react/jsx-runtime";var Me=[{type:"bold"},{type:"italic"},{type:"underline"}];function He(e){let f=["bold","italic","underline","strikethrough","textColor","backgroundColor"];return e.filter(r=>f.includes(r.type))}function V({enabled:e=!0,items:f}){let r=f?He(f).slice(0,4):Me,[t]=Ee(),[p,u]=de(null),[a,h]=de(null);Q(()=>{let o=t.getRootElement();o&&h(o)},[t]);let b=se(()=>{if(!a)return;let o=window.getSelection();if(!o||o.rangeCount===0||o.isCollapsed){u(null);return}try{let x=o.getRangeAt(0);if(!a.contains(x.commonAncestorContainer)){u(null);return}let s=x.getBoundingClientRect();s&&s.width>0&&s.height>0?t.getEditorState().read(()=>{let y=U();y&&_(y)&&!y.isCollapsed()?u({x:s.left+s.width/2,y:s.top-40}):u(null)}):u(null)}catch{u(null)}},[t,a]);Q(()=>{if(!a)return;let o=t.registerUpdateListener(()=>{setTimeout(()=>b(),10)});return()=>{o()}},[t,a,b]),Q(()=>{let o=()=>{setTimeout(()=>b(),50)},x=()=>{setTimeout(()=>b(),50)},s=()=>{setTimeout(()=>b(),50)};return document.addEventListener("mouseup",o),document.addEventListener("keyup",x),document.addEventListener("selectionchange",s),()=>{document.removeEventListener("mouseup",o),document.removeEventListener("keyup",x),document.removeEventListener("selectionchange",s)}},[b]);let i=se((o,x)=>{let{type:s}=o;if(s==="textColor"&&x){t.update(()=>{let y=U();_(y)&&ie(y,{color:x})});return}if(s==="backgroundColor"&&x){t.update(()=>{let y=U();_(y)&&ie(y,{"background-color":x})});return}if(s==="bold"||s==="italic"||s==="underline"||s==="strikethrough"){t.dispatchCommand(Ie,s);return}if(s.startsWith("heading")){let n=`h${parseInt(s.replace("heading",""))}`;t.update(()=>{let g=U();if(_(g)){let d=g.anchor.getNode(),R=d.getKey()==="root"?d:d.getTopLevelElementOrThrow(),E=R.getKey();if(t.getElementByKey(E)!==null&&le(R)){let K=we(n),l=R.getChildren();K.append(...l),R.replace(K),K.selectEnd()}}});return}if(s==="paragraph"){t.update(()=>{let y=U();if(_(y)){let n=y.anchor.getNode(),g=n.getKey()==="root"?n:n.getTopLevelElementOrThrow(),d=g.getKey();if(t.getElementByKey(d)!==null&&Re(g)&&le(g)){let E=Le(),I=g.getChildren();E.append(...I),g.replace(E),E.selectEnd()}}});return}},[t]);return!e||!r||r.length===0||!p?null:Se(P("div",{className:"luxe-floating-toolbar",style:{position:"fixed",top:`${p.y}px`,left:`${p.x}px`,transform:"translateX(-50%)",display:"flex",gap:"4px",background:"white",border:"1px solid #e5e7eb",borderRadius:"6px",padding:"4px",boxShadow:"0 4px 6px -1px rgba(0, 0, 0, 0.1)",zIndex:1e3},children:r.map((o,x)=>{let s=o.label||F(o.type),n=o.type.startsWith("heading")?parseInt(o.type.replace("heading","")):null;if(o.type==="textColor"||o.type==="backgroundColor"){let g=o.colors||Z.slice(0,6);return P("div",{style:{display:"flex",gap:"2px"},children:o.color?P("button",{onClick:()=>i(o,o.color),title:`${o.type==="textColor"?"Text":"Background"} Color`,style:{padding:"4px 8px",border:"1px solid #e5e7eb",background:o.type==="backgroundColor"?o.color:"white",color:o.type==="textColor"?o.color:"#000",cursor:"pointer",borderRadius:"4px",minWidth:"28px",height:"28px"},children:o.type==="textColor"?"A":"\u25A0"}):g.map(d=>P("button",{onClick:()=>i(o,d),title:d,style:{width:"24px",height:"24px",border:o.type==="textColor"?`3px solid ${d}`:"1px solid #e5e7eb",background:o.type==="backgroundColor"?d:"white",color:o.type==="textColor"?"#000":"inherit",cursor:"pointer",borderRadius:"3px",fontSize:"10px",display:"flex",alignItems:"center",justifyContent:"center"},children:o.type==="textColor"&&P("span",{style:{color:d,fontSize:"12px",fontWeight:"bold",lineHeight:"1"},children:"A"})},d))},`${o.type}-${x}`)}return P("button",{onClick:()=>i(o),title:o.type.charAt(0).toUpperCase()+o.type.slice(1),style:{padding:"6px 12px",border:"none",background:"transparent",cursor:"pointer",borderRadius:"4px",fontWeight:o.type==="bold"?"bold":"normal",fontStyle:o.type==="italic"?"italic":"normal",textDecoration:o.type==="underline"?"underline":o.type==="strikethrough"?"line-through":"none",fontSize:n?`${18-n*2}px`:"14px",minWidth:"32px",display:"flex",alignItems:"center",justifyContent:"center",transition:"background-color 0.2s"},onMouseEnter:g=>{g.currentTarget.style.background="#f3f4f6"},onMouseLeave:g=>{g.currentTarget.style.background="transparent"},children:o.icon||s},`${o.type}-${x}`)})}),document.body)}import{jsx as O,jsxs as Be}from"react/jsx-runtime";var ce={paragraph:"luxe-paragraph",heading:{h1:"luxe-heading-h1",h2:"luxe-heading-h2",h3:"luxe-heading-h3",h4:"luxe-heading-h4",h5:"luxe-heading-h5",h6:"luxe-heading-h6"},text:{bold:"luxe-bold",italic:"luxe-italic",underline:"luxe-underline",strikethrough:"luxe-strikethrough"}};function Nt({initialConfig:e,showFloatingToolbar:f=!0,showToolbar:r=!1,toolbarItems:t,floatingToolbarItems:p,children:u}){let[a,h]=pe.useState(!1),b=[We,Ue,_e,ze,Fe],i=e.theme?{...ce,...e.theme}:ce,{theme:o,...x}=e,s={namespace:"LuxeEditor",theme:i,nodes:b,onError:d=>console.error(d),...x},n=t||[{type:"bold"},{type:"italic"}],g=pe.useCallback(()=>{h(d=>!d)},[]);return O($e,{initialConfig:s,children:Be("div",{className:`luxe-editor-container ${a?"luxe-editor-fullscreen":""}`,children:[r&&n&&n.length>0&&O(q,{items:n,onFullscreenToggle:g,isFullscreen:a}),O(De,{contentEditable:O(Ae,{className:"luxe-input"}),placeholder:O("div",{className:"luxe-placeholder",children:"Start writing..."}),ErrorBoundary:Ke}),O(Oe,{}),O(Pe,{}),f&&O(V,{enabled:!0,items:p||n}),u]})})}export{V as FloatingToolbarPlugin,Nt as LuxeEditor,q as Toolbar};
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "luxe-edit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A beautiful, customizable rich text editor for React built on Lexical with customizable toolbars and floating toolbar support",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"editor",
|
|
8
|
+
"lexical",
|
|
9
|
+
"rich-text",
|
|
10
|
+
"wysiwyg",
|
|
11
|
+
"toolbar",
|
|
12
|
+
"text-editor",
|
|
13
|
+
"content-editable"
|
|
14
|
+
],
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"module": "./dist/index.mjs",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.mjs",
|
|
22
|
+
"require": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./dist/index.css": "./dist/index.css",
|
|
25
|
+
"./index.css": "./dist/index.css"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsup",
|
|
33
|
+
"prepublishOnly": "yarn build"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/amide-init/luxe-edit.git"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/amide-init/luxe-edit#readme",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/amide-init/luxe-edit/issues"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
49
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@lexical/code": "^0.39.0",
|
|
53
|
+
"@lexical/link": "^0.39.0",
|
|
54
|
+
"@lexical/list": "^0.39.0",
|
|
55
|
+
"@lexical/react": "^0.39.0",
|
|
56
|
+
"@lexical/rich-text": "^0.39.0",
|
|
57
|
+
"@lexical/selection": "^0.39.0",
|
|
58
|
+
"@lexical/utils": "^0.39.0",
|
|
59
|
+
"lexical": "^0.39.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/react": "^19.2.7",
|
|
63
|
+
"@types/react-dom": "^19.2.3",
|
|
64
|
+
"react": "^19.2.3",
|
|
65
|
+
"react-dom": "^19.2.3",
|
|
66
|
+
"tsup": "^8.5.1",
|
|
67
|
+
"typescript": "^5.9.3"
|
|
68
|
+
}
|
|
69
|
+
}
|