forge-edit 0.1.0-beta.4 → 0.1.0-beta.6
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/dist/index.js +1215 -607
- package/package.json +3 -2
- package/README.md +0 -216
- package/dist/index.css +0 -2
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forge-edit",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.6",
|
|
4
4
|
"description": "A lightweight WYSIWYG editor built with Preact",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": "./dist/index.js",
|
|
10
|
-
"./style.css": "./dist/
|
|
10
|
+
"./style.css": "./dist/index.css"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist"
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"vite": "^8.2.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
32
33
|
"preact": "^10.29.8",
|
|
33
34
|
"sweetalert2": "^11.26.25"
|
|
34
35
|
}
|
package/README.md
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
# Forge Editor
|
|
2
|
-
|
|
3
|
-
A lightweight WYSIWYG editor built with Preact.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install forge-edit
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Usage
|
|
12
|
-
|
|
13
|
-
### Basic HTML Usage
|
|
14
|
-
|
|
15
|
-
```html
|
|
16
|
-
<!DOCTYPE html>
|
|
17
|
-
<html lang="en">
|
|
18
|
-
<head>
|
|
19
|
-
<meta charset="UTF-8">
|
|
20
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
21
|
-
<title>Forge Editor</title>
|
|
22
|
-
</head>
|
|
23
|
-
<body>
|
|
24
|
-
<forge-editor
|
|
25
|
-
type="light"
|
|
26
|
-
placeholder="Write something..."
|
|
27
|
-
width="628px"
|
|
28
|
-
height="200px"
|
|
29
|
-
lang="en"
|
|
30
|
-
dir="ltr"></forge-editor>
|
|
31
|
-
|
|
32
|
-
<script type="module">
|
|
33
|
-
import ForgeEditor from 'forge-edit'
|
|
34
|
-
|
|
35
|
-
const element = document.querySelector('forge-editor')
|
|
36
|
-
const editor = ForgeEditor(element)
|
|
37
|
-
|
|
38
|
-
// Get HTML content
|
|
39
|
-
const html = editor.getHTML()
|
|
40
|
-
console.log(html)
|
|
41
|
-
|
|
42
|
-
// Set HTML content
|
|
43
|
-
editor.setHTML('<p>New content</p>')
|
|
44
|
-
|
|
45
|
-
// Get text content
|
|
46
|
-
const text = editor.getText()
|
|
47
|
-
console.log(text)
|
|
48
|
-
|
|
49
|
-
// Get selected text
|
|
50
|
-
const selection = editor.getSelection()
|
|
51
|
-
console.log(selection)
|
|
52
|
-
</script>
|
|
53
|
-
</body>
|
|
54
|
-
</html>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### React Usage
|
|
58
|
-
|
|
59
|
-
Create a wrapper component:
|
|
60
|
-
|
|
61
|
-
```jsx
|
|
62
|
-
import { useEffect, useRef, forwardRef, useImperativeHandle } from 'react'
|
|
63
|
-
|
|
64
|
-
const ReactForgeEditor = forwardRef(({
|
|
65
|
-
placeholder = 'Write something...',
|
|
66
|
-
width = '628px',
|
|
67
|
-
height = '200px',
|
|
68
|
-
lang = 'en',
|
|
69
|
-
dir = 'ltr',
|
|
70
|
-
onChange,
|
|
71
|
-
onInit
|
|
72
|
-
}, ref) => {
|
|
73
|
-
const containerRef = useRef(null)
|
|
74
|
-
const editorRef = useRef(null)
|
|
75
|
-
const apiRef = useRef(null)
|
|
76
|
-
|
|
77
|
-
useImperativeHandle(ref, () => ({
|
|
78
|
-
getHTML: () => apiRef.current?.getHTML?.() || '',
|
|
79
|
-
setHTML: (html) => apiRef.current?.setHTML?.(html),
|
|
80
|
-
getText: () => apiRef.current?.getText?.() || '',
|
|
81
|
-
getSelection: () => apiRef.current?.getSelection?.() || '',
|
|
82
|
-
getEditorElement: () => editorRef.current
|
|
83
|
-
}))
|
|
84
|
-
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
if (!containerRef.current) return
|
|
87
|
-
|
|
88
|
-
const customElement = document.createElement('forge-editor')
|
|
89
|
-
customElement.setAttribute('type', 'light')
|
|
90
|
-
customElement.setAttribute('placeholder', placeholder)
|
|
91
|
-
customElement.setAttribute('width', width)
|
|
92
|
-
customElement.setAttribute('height', height)
|
|
93
|
-
customElement.setAttribute('lang', lang)
|
|
94
|
-
customElement.setAttribute('dir', dir)
|
|
95
|
-
|
|
96
|
-
containerRef.current.appendChild(customElement)
|
|
97
|
-
|
|
98
|
-
const initEditor = async () => {
|
|
99
|
-
try {
|
|
100
|
-
const ForgeEditor = await import('forge-edit')
|
|
101
|
-
const instance = ForgeEditor.default(customElement)
|
|
102
|
-
|
|
103
|
-
editorRef.current = instance.element
|
|
104
|
-
apiRef.current = {
|
|
105
|
-
getHTML: instance.getHTML,
|
|
106
|
-
setHTML: instance.setHTML,
|
|
107
|
-
getText: instance.getText,
|
|
108
|
-
getSelection: instance.getSelection
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (onInit) {
|
|
112
|
-
onInit(apiRef.current)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const contentElement = instance.element.querySelector('.forge-editor__content')
|
|
116
|
-
if (contentElement && onChange) {
|
|
117
|
-
const observer = new MutationObserver(() => {
|
|
118
|
-
onChange(apiRef.current?.getHTML?.() || '')
|
|
119
|
-
})
|
|
120
|
-
observer.observe(contentElement, {
|
|
121
|
-
childList: true,
|
|
122
|
-
subtree: true,
|
|
123
|
-
characterData: true
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
return () => observer.disconnect()
|
|
127
|
-
}
|
|
128
|
-
} catch (error) {
|
|
129
|
-
console.error('Failed to initialize forge-edit:', error)
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
initEditor()
|
|
134
|
-
|
|
135
|
-
return () => {
|
|
136
|
-
if (containerRef.current && customElement) {
|
|
137
|
-
containerRef.current.removeChild(customElement)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}, [placeholder, width, height, lang, dir, onChange, onInit])
|
|
141
|
-
|
|
142
|
-
return <div ref={containerRef} />
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
ReactForgeEditor.displayName = 'ReactForgeEditor'
|
|
146
|
-
|
|
147
|
-
export default ReactForgeEditor
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
Use it in your app:
|
|
151
|
-
|
|
152
|
-
```jsx
|
|
153
|
-
import React, { useRef } from 'react'
|
|
154
|
-
import ReactForgeEditor from './ReactForgeEditor'
|
|
155
|
-
|
|
156
|
-
function App() {
|
|
157
|
-
const editorRef = useRef(null)
|
|
158
|
-
|
|
159
|
-
const handleInit = (api) => {
|
|
160
|
-
api.setHTML('<p>Hello from React!</p>')
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return (
|
|
164
|
-
<div>
|
|
165
|
-
<ReactForgeEditor
|
|
166
|
-
ref={editorRef}
|
|
167
|
-
placeholder="Write something..."
|
|
168
|
-
width="628px"
|
|
169
|
-
height="200px"
|
|
170
|
-
onInit={handleInit}
|
|
171
|
-
onChange={(html) => console.log(html)}
|
|
172
|
-
/>
|
|
173
|
-
</div>
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## API
|
|
179
|
-
|
|
180
|
-
### Attributes
|
|
181
|
-
|
|
182
|
-
| Attribute | Type | Default | Description |
|
|
183
|
-
|-----------|------|---------|-------------|
|
|
184
|
-
| `type` | string | `'light'` | Editor type |
|
|
185
|
-
| `placeholder` | string | `'Write something...'` | Placeholder text |
|
|
186
|
-
| `width` | string | `'628px'` | Editor width |
|
|
187
|
-
| `height` | string | `'200px'` | Editor height |
|
|
188
|
-
| `lang` | string | `'en'` | Language code |
|
|
189
|
-
| `dir` | string | `'ltr'` | Text direction (`'ltr'` or `'rtl'`) |
|
|
190
|
-
|
|
191
|
-
### Methods
|
|
192
|
-
|
|
193
|
-
| Method | Description |
|
|
194
|
-
|--------|-------------|
|
|
195
|
-
| `getHTML()` | Get editor HTML content |
|
|
196
|
-
| `setHTML(html)` | Set editor HTML content |
|
|
197
|
-
| `getText()` | Get plain text content |
|
|
198
|
-
| `getSelection()` | Get selected text |
|
|
199
|
-
|
|
200
|
-
## Features
|
|
201
|
-
|
|
202
|
-
- Lightweight WYSIWYG editor
|
|
203
|
-
- Built with Preact
|
|
204
|
-
- Custom web component
|
|
205
|
-
- Easy to integrate
|
|
206
|
-
- Supports multiple languages
|
|
207
|
-
- RTL support
|
|
208
|
-
- Rich text formatting
|
|
209
|
-
- Color picker
|
|
210
|
-
- Font selection
|
|
211
|
-
- Image insertion
|
|
212
|
-
- Table insertion
|
|
213
|
-
|
|
214
|
-
## License
|
|
215
|
-
|
|
216
|
-
MIT
|
package/dist/index.css
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
.forge-editor{vertical-align:top;box-sizing:border-box;display:inline-block}.forge-editor--light{background:#fff;border:1px solid #ddd;border-radius:3px;flex-direction:column;display:flex;overflow:hidden}.forge-editor__content{box-sizing:border-box;outline:none;flex:auto;min-height:0;padding:10px;overflow:auto}.forge-editor__toolbar{color:#333;background-color:#f5f5f5;border-bottom:1px solid #ddd;border-radius:3px 3px 0 0;flex-wrap:wrap;flex-shrink:0;align-items:center;gap:4px;margin:0;padding:5px;display:flex;position:relative}.forge-toolbar-group{align-items:center;gap:2px;display:flex;position:relative}.forge-toolbar-button{cursor:pointer;box-sizing:border-box;background:#fff;border:1px solid #ccc;justify-content:center;align-items:center;height:28px;padding:4px 7px;font-size:14px;line-height:1;display:flex;position:relative}.forge-toolbar-button:hover{background:#f0f0f0}.forge-toolbar-button:active{transform:translateY(1px)}.forge-toolbar-dropdown{z-index:10;background:#fff;border:1px solid #ccc;min-width:100px;display:none;position:absolute;top:100%;left:0}.forge-dropdown-item{color:#333;white-space:nowrap;padding:4px 8px;text-decoration:none;display:block}.forge-toolbar-dropdown.is-open{display:block}.forge-dropdown-item:hover{background:#f0f0f0}.forge-editor__toolbar .forge-toolbar-button,.forge-editor__toolbar .forge-color-button-group{box-sizing:border-box;height:28px}.forge-toolbar-icon{text-align:center;min-width:16px;font-size:14px;font-weight:500;line-height:1;display:inline-block}.forge-tooltip{color:#000;white-space:nowrap;opacity:0;visibility:hidden;pointer-events:none;z-index:30;background:#ffffe1;border:1px solid #333;border-radius:2px;padding:2px 8px;font-size:13px;line-height:1.6;transition:opacity .15s;position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);box-shadow:1px 1px 3px #0000004d}.forge-tooltip:before{content:"";border:5px solid #0000;border-top-width:0;border-bottom-color:#333;position:absolute;bottom:100%;left:50%;transform:translate(-50%)}.forge-tooltip:after{content:"";border:4px solid #0000;border-top-width:0;border-bottom-color:#ffffe1;position:absolute;bottom:100%;left:50%;transform:translate(-50%)translateY(1px)}.forge-toolbar-button:hover .forge-tooltip{opacity:1;visibility:visible}.forge-toolbar-button.is-active .forge-tooltip{opacity:0;visibility:hidden}[dir=rtl] .forge-toolbar-dropdown{left:auto;right:0}[dir=rtl] .forge-toolbar-dropdown .forge-dropdown-item{text-align:right}[dir=rtl] .forge-tooltip{left:50%;transform:translate(-50%)}.forge-toolbar-style .forge-toolbar-button{padding:0 8px}.forge-dropdown-style{z-index:20;border-radius:2px;min-width:90px;max-height:96px;padding:4px 0;top:calc(100% + 4px);overflow-y:auto;box-shadow:0 2px 6px #00000026}.forge-dropdown-style.is-open{display:block}.forge-dropdown-item{cursor:pointer;padding:4px 12px;transition:background .1s}.forge-dropdown-item p,.forge-dropdown-item blockquote,.forge-dropdown-item pre,.forge-dropdown-item h1,.forge-dropdown-item h2,.forge-dropdown-item h3,.forge-dropdown-item h4,.forge-dropdown-item h5,.forge-dropdown-item h6{margin:0;font-weight:400;line-height:1.4}.forge-dropdown-item p,.forge-dropdown-item blockquote,.forge-dropdown-item pre{font-size:13px}.forge-dropdown-item pre{font-family:monospace}.forge-dropdown-item h1{font-size:20px}.forge-dropdown-item h2{font-size:18px}.forge-dropdown-item h3{font-size:16px}.forge-dropdown-item h4{font-size:15px}.forge-dropdown-item h5{font-size:14px}.forge-dropdown-item h6{font-size:13px}[dir=rtl] .forge-dropdown-style{left:auto;right:0}[dir=rtl] .forge-dropdown-item{text-align:right}.forge-toolbar-color{align-items:center;gap:4px;display:flex}.forge-color-item{z-index:10;align-items:center;display:flex;position:relative}.forge-color-button-group{background:0 0;border:1px solid #ccc;border-radius:2px;align-items:center;height:28px;display:flex;overflow:visible}.forge-color-button-group:hover{background:#0000000d;border-color:#aaa}.forge-color-main{cursor:pointer;background:0 0;border:none;min-width:28px;padding:0;font-size:14px}.forge-color-main:hover{background:#00000014}.forge-color-dropdown-btn{cursor:pointer;color:#666;background:0 0;border:none;border-left:1px solid #ccc;min-width:18px;padding:0 4px;font-size:10px}.forge-color-dropdown-btn:hover{background:#00000014}.forge-recent-color{border:1px solid #ccc;border-radius:2px;flex-shrink:0;justify-content:center;align-items:center;width:20px;height:20px;font-size:14px;font-weight:700;display:flex}.forge-toolbar-dropdown.forge-dropdown-color{border-radius:3px;min-width:160px;max-height:200px;margin-top:4px;padding:6px;overflow-y:auto;box-shadow:0 2px 6px #00000026}.forge-toolbar-dropdown.forge-dropdown-color.is-open{display:block}[dir=rtl] .forge-toolbar-dropdown.forge-dropdown-color{left:auto;right:0}.forge-color-section{margin-bottom:6px}.forge-color-section:last-child{margin-bottom:0}.forge-color-section-header{justify-content:space-between;align-items:center;margin-bottom:4px;display:flex}.forge-color-title{color:#333;font-size:12px;font-weight:700}.forge-color-reset{color:#333;cursor:pointer;background:#f5f5f5;border:1px solid #ccc;border-radius:2px;padding:2px 8px;font-size:11px;font-weight:500;transition:all .15s}.forge-color-reset:hover{background:#e6e6e6;border-color:#999}.forge-color-reset:active{background:#d0d0d0;border-color:#666;transform:translateY(1px)}.forge-color-palette{flex-direction:column;gap:2px;display:flex}.forge-color-row{gap:2px;display:flex}.forge-color-button{cursor:pointer;border:1px solid #ccc;border-radius:2px;width:20px;height:20px;padding:0}.forge-color-button:hover{border-color:#000;transform:scale(1.1)}.forge-toolbar-color .forge-toolbar-button .forge-tooltip{padding:2px 7px}.forge-toolbar-button{gap:2px}.note-popover{z-index:1000;background:#fff;border:1px solid #ccc;border-radius:4px;min-width:200px;padding:6px;display:none;position:absolute;box-shadow:0 2px 8px #00000026}.note-popover.bottom .note-popover-arrow{border-bottom:8px solid #ccc;border-left:8px solid #0000;border-right:8px solid #0000;position:absolute;top:-8px;left:50%;transform:translate(-50%)}.note-popover.bottom .note-popover-arrow:after{content:"";border-bottom:7px solid #fff;border-left:7px solid #0000;border-right:7px solid #0000;position:absolute;top:1px;left:-7px}.popover-content{flex-wrap:wrap;align-items:center;gap:4px;display:flex}.note-btn-group{border-right:1px solid #ddd;gap:2px;padding-right:4px;display:flex}.note-btn-group:last-child{border-right:none;padding-right:0}.note-btn{cursor:pointer;background:#f5f5f5;border:1px solid #ccc;border-radius:2px;padding:4px 8px;font-size:12px;line-height:1.4;transition:all .1s}.note-btn:hover{background:#e6e6e6;border-color:#999}.note-btn:active{background:#d0d0d0;transform:translateY(1px)}.note-fontsize-10{font-size:10px}.note-icon-float-left,.note-icon-float-right,.note-icon-rollback,.note-icon-trash{font-size:14px;font-style:normal;line-height:1}[dir=rtl] .note-popover.bottom .note-popover-arrow{left:50%;transform:translate(-50%)}.forge-toolbar-paragraph .forge-toolbar-button{width:28px;padding:0}.forge-toolbar-paragraph .forge-toolbar-icon{width:16px;height:16px}.forge-toolbar-paragraph .forge-toolbar-icon svg{width:16px;height:16px;display:block}.forge-toolbar-paragraph .forge-toolbar-icon svg rect,.forge-toolbar-paragraph .forge-toolbar-icon svg circle,.forge-toolbar-paragraph .forge-toolbar-icon svg text{fill:#000!important;stroke:none!important}.forge-toolbar-paragraph .forge-toolbar-icon svg line,.forge-toolbar-paragraph .forge-toolbar-icon svg polyline{stroke:#000!important}.forge-dropdown-paragraph{min-width:130px;padding:4px}.forge-dropdown-paragraph .forge-toolbar-group{gap:2px;padding:2px 0}.forge-dropdown-paragraph .forge-toolbar-group:not(:last-child){border-bottom:1px solid #eee;margin-bottom:2px}.forge-dropdown-paragraph .forge-toolbar-button{width:28px;padding:0}.forge-editor__content table{border-collapse:collapse;border:1px solid #ddd;width:100%;margin:8px 0}.forge-editor__content table td{vertical-align:top;border:1px solid #ddd;min-width:30px;padding:8px}.forge-editor__content table td:focus{outline:none}.forge-dropdown-table{padding:8px}.note-dimension-picker{cursor:pointer;background:#f5f5f5;border:1px solid #ccc;border-radius:3px;width:160px;height:160px;margin:0 auto;position:relative;overflow:hidden}.note-dimension-picker-mousecatcher{z-index:5;width:100%;height:100%;position:absolute;top:0;left:0}.note-dimension-picker-highlighted{z-index:3;pointer-events:none;background:#4a90d966;border:2px solid #4a90d9;transition:width 50ms,height 50ms;position:absolute;top:0;left:0}.note-dimension-picker-unhighlighted{z-index:2;pointer-events:none;background:#ffffff4d;width:100%;height:100%;position:absolute;top:0;left:0}.note-dimension-display{text-align:center;color:#333;padding:6px 0 2px;font-size:13px;font-weight:600}.note-dimension-picker:before{content:"";z-index:1;pointer-events:none;background-image:linear-gradient(#0000000d 1px,#0000 1px),linear-gradient(90deg,#0000000d 1px,#0000 1px);background-size:16px 16px;width:100%;height:100%;position:absolute;top:0;left:0}.forge-toolbar-view .forge-toolbar-button{padding:4px 2px}.forge-fontname-button{text-align:left;min-width:80px}.forge-toolbar-group.forge-toolbar-fontname .forge-toolbar-dropdown.forge-dropdown-fontname{z-index:10!important;background:#fff!important;border:1px solid #ccc!important;min-width:120px!important;max-height:100px!important;padding:0!important;display:none!important;position:absolute!important;top:100%!important;left:0!important;overflow:hidden auto!important}.forge-toolbar-group.forge-toolbar-fontname .forge-toolbar-dropdown.forge-dropdown-fontname.is-open{display:block!important}.forge-toolbar-group.forge-toolbar-fontname .forge-toolbar-dropdown.forge-dropdown-fontname .forge-dropdown-item{white-space:nowrap!important;color:#333!important;box-sizing:border-box!important;border-bottom:1px solid #f0f0f0!important;height:30px!important;padding:8px 12px!important;line-height:14px!important;text-decoration:none!important;display:block!important}.forge-toolbar-group.forge-toolbar-fontname .forge-toolbar-dropdown.forge-dropdown-fontname .forge-dropdown-item:last-child{border-bottom:none!important}.forge-toolbar-font .forge-toolbar-button{text-align:center;border-radius:2px;min-width:32px;padding:4px 6px;font-size:16px;transition:all .15s}.forge-toolbar-font .forge-toolbar-button:hover{background:#e6e6e6;border-color:#999;box-shadow:inset 0 1px 2px #0000001a}.forge-toolbar-font .forge-toolbar-button:active{background:#d0d0d0;border-color:#666;box-shadow:inset 0 2px 4px #0003}.forge-toolbar-font .forge-toolbar-button strong{color:#333;font-size:16px;font-weight:900;line-height:1}.forge-toolbar-font .forge-toolbar-button u{text-underline-offset:2px;color:#333;font-size:16px;line-height:1;text-decoration:underline}.forge-toolbar-font .forge-toolbar-button span{color:#333;font-size:18px;line-height:1}.forge-toolbar-font .forge-toolbar-button .forge-tooltip{font-size:13px}.forge-toolbar-font .forge-toolbar-button.is-active{background:#d4e6f7;border-color:#8ab3d6;box-shadow:inset 0 1px 3px #0003}.forge-statusbar{cursor:s-resize;box-sizing:border-box;background-color:#f0f0f0;border-top:1px solid #ccc;border-radius:0 0 3px 3px;flex-shrink:0;justify-content:center;align-items:center;width:100%;height:10px;display:flex}.forge-resizebar{flex-direction:column;align-items:center;gap:1px;display:flex}.forge-icon-bar{background-color:#888;border-radius:1px;width:12px;height:1px}
|
|
2
|
-
/*$vite$:1*/
|