md-editor-lite 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 +175 -0
- package/dist/index.css +181 -0
- package/dist/index.d.mts +81 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +410 -0
- package/dist/index.mjs +371 -0
- package/package.json +30 -0
- package/playground/App.tsx +19 -0
- package/playground/index.html +12 -0
- package/playground/main.tsx +9 -0
- package/playground/package-lock.json +970 -0
- package/playground/package.json +14 -0
- package/playground/tsconfig.app.json +31 -0
- package/playground/tsconfig.json +7 -0
- package/playground/tsconfig.node.json +24 -0
- package/playground/vite.config.ts +6 -0
- package/src/components/EditorHeader.tsx +21 -0
- package/src/components/EditorTab.tsx +27 -0
- package/src/components/EditorTextarea.tsx +39 -0
- package/src/components/IconDropdown.tsx +90 -0
- package/src/components/MarkdownEditor.tsx +42 -0
- package/src/components/Preview.tsx +16 -0
- package/src/components/Toolbar.tsx +25 -0
- package/src/components/ToolbarDropdown.tsx +35 -0
- package/src/components/index.ts +7 -0
- package/src/constants/index.ts +1 -0
- package/src/constants/toolbar.ts +36 -0
- package/src/css/dropdown.css +101 -0
- package/src/css/editor.css +67 -0
- package/src/css/preview.css +11 -0
- package/src/css/toolbar.css +25 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useMarkdownEditor.ts +39 -0
- package/src/index.ts +4 -0
- package/src/utils/cx.ts +3 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/markdown.ts +89 -0
- package/tsconfig.build.json +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# md-editor-lite
|
|
2
|
+
|
|
3
|
+
A lightweight React markdown editor focused on the **core editing experience**.
|
|
4
|
+
Built with **TypeScript**, designed for **library-friendly usage**, and has **no runtime dependency other than React**.
|
|
5
|
+
|
|
6
|
+
> Minimal. Predictable. Easy to integrate.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## ✨ Features
|
|
11
|
+
|
|
12
|
+
- ⚡ **Minimal dependencies**
|
|
13
|
+
→ No heavy editor engines, no unnecessary packages
|
|
14
|
+
|
|
15
|
+
- 🔁 **Controlled & Uncontrolled modes**
|
|
16
|
+
→ Works well with forms and external state management
|
|
17
|
+
|
|
18
|
+
- 🧩 **Customizable toolbar**
|
|
19
|
+
→ Enable only the features you need
|
|
20
|
+
|
|
21
|
+
- 🎨 **No CSS framework dependency**
|
|
22
|
+
→ No Tailwind, no opinionated styles
|
|
23
|
+
→ Fully styleable with plain CSS
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 🧠 Supported Markdown Syntax
|
|
28
|
+
|
|
29
|
+
- **Bold**
|
|
30
|
+
- _Italic_
|
|
31
|
+
- `Inline code`
|
|
32
|
+
- > Blockquote
|
|
33
|
+
- Headings (`#`, `##`, `###`)
|
|
34
|
+
- Ordered / Unordered lists
|
|
35
|
+
- Images: ``
|
|
36
|
+
- Links: `[text](url)`
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 📦 Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install md-editor-lite
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 🚀 Basic Usage (Uncontrolled)
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import { MarkdownEditor } from "md-editor-lite";
|
|
52
|
+
|
|
53
|
+
function App() {
|
|
54
|
+
return <MarkdownEditor />;
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 🎛 Controlled Usage
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { useState } from "react";
|
|
64
|
+
import { MarkdownEditor } from "md-editor-lite";
|
|
65
|
+
|
|
66
|
+
function App() {
|
|
67
|
+
const [value, setValue] = useState("");
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<MarkdownEditor
|
|
71
|
+
value={value}
|
|
72
|
+
onChange={setValue}
|
|
73
|
+
placeholder="Write your markdown here..."
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> Controlled mode is recommended when:
|
|
80
|
+
>
|
|
81
|
+
> - Integrating with forms
|
|
82
|
+
> - Saving content externally
|
|
83
|
+
> - Syncing editor state with other UI
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 🧩 Props API
|
|
88
|
+
|
|
89
|
+
### `MarkdownEditor`
|
|
90
|
+
|
|
91
|
+
| Prop | Type | Description |
|
|
92
|
+
| -------------- | ------------------------- | ---------------------------------- |
|
|
93
|
+
| `value` | `string` | Markdown content (controlled mode) |
|
|
94
|
+
| `onChange` | `(value: string) => void` | Called when content changes |
|
|
95
|
+
| `defaultValue` | `string` | Initial value (uncontrolled mode) |
|
|
96
|
+
| `placeholder` | `string` | Placeholder text for the editor |
|
|
97
|
+
| `readOnly` | `boolean` | Disable editing |
|
|
98
|
+
| `toolbar` | `ToolbarItem[]` | Customize visible toolbar items |
|
|
99
|
+
| `className` | `string` | Custom class for root container |
|
|
100
|
+
|
|
101
|
+
> If `value` is provided, the editor automatically works in **controlled mode**.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 📱 Responsive Behavior
|
|
106
|
+
|
|
107
|
+
This library relies on the **browser viewport** for responsive layouts.
|
|
108
|
+
|
|
109
|
+
Make sure the following meta tag exists in your HTML document:
|
|
110
|
+
|
|
111
|
+
```html
|
|
112
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> ⚠️ This library does **not** inject meta tags automatically
|
|
116
|
+
> → Host applications should manage viewport settings themselves
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
<details>
|
|
121
|
+
<summary>🇰🇷 한국어 설명</summary>
|
|
122
|
+
|
|
123
|
+
## 소개
|
|
124
|
+
|
|
125
|
+
**md-editor-lite**는
|
|
126
|
+
“필요한 기능만 제공하고, 나머지는 개발자에게 맡긴다”는 철학으로 만든
|
|
127
|
+
**경량 React 마크다운 에디터 라이브러리**입니다.
|
|
128
|
+
|
|
129
|
+
대형 에디터들이 흔히 가지는
|
|
130
|
+
|
|
131
|
+
- 과도한 번들 사이즈
|
|
132
|
+
- 복잡한 설정
|
|
133
|
+
- 강제되는 스타일 구조
|
|
134
|
+
|
|
135
|
+
이런 문제를 피하고,
|
|
136
|
+
**폼 / CMS / 관리자 페이지 / 사이드 프로젝트** 어디에든
|
|
137
|
+
부담 없이 사용할 수 있도록 설계되었습니다.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 주요 특징
|
|
142
|
+
|
|
143
|
+
### ⚡ 가볍고 예측 가능한 구조
|
|
144
|
+
|
|
145
|
+
- 런타임 의존성은 **React만 필요**
|
|
146
|
+
- 외부 에디터 엔진 없이 동작
|
|
147
|
+
- 라이브러리·디자인 시스템 내부에서도 안전하게 사용 가능
|
|
148
|
+
|
|
149
|
+
### 🎛 Controlled / Uncontrolled 모두 지원
|
|
150
|
+
|
|
151
|
+
- 단순 textarea처럼 빠르게 사용 가능
|
|
152
|
+
- 상태를 외부에서 완전히 제어하는 구조도 지원
|
|
153
|
+
- React Hook Form 등과 호환 가능
|
|
154
|
+
|
|
155
|
+
### 🎨 스타일 독립성
|
|
156
|
+
|
|
157
|
+
- Tailwind / CSS Modules / styled-components 등
|
|
158
|
+
**어떤 스타일링 방식과도 충돌하지 않음**
|
|
159
|
+
- 기본 스타일은 최소한만 제공
|
|
160
|
+
|
|
161
|
+
### 📦 라이브러리 배포를 고려한 설계
|
|
162
|
+
|
|
163
|
+
- 전역 CSS 주입 없음
|
|
164
|
+
- meta tag 자동 삽입 없음
|
|
165
|
+
- 호스트 애플리케이션의 환경을 침범하지 않음
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 이런 경우에 잘 어울려요
|
|
170
|
+
|
|
171
|
+
- “에디터 하나 때문에 라이브러리가 무거워지는 게 싫을 때”
|
|
172
|
+
- 관리자 페이지에 **심플한 마크다운 입력 UI**가 필요할 때
|
|
173
|
+
- 디자인 시스템 안에 자연스럽게 녹아드는 에디터가 필요할 때
|
|
174
|
+
|
|
175
|
+
</details>
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/* src/css/editor.css */
|
|
2
|
+
.editor {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
width: 100%;
|
|
6
|
+
border: 1px solid #e5e7eb;
|
|
7
|
+
border-radius: 8px;
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
}
|
|
11
|
+
.editor-header {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
justify-content: space-evenly;
|
|
15
|
+
height: 88px;
|
|
16
|
+
padding: 0 16px;
|
|
17
|
+
background-color: #f9fafb;
|
|
18
|
+
border-bottom: 1px solid #e5e7eb;
|
|
19
|
+
border-top-left-radius: 8px;
|
|
20
|
+
border-top-right-radius: 8px;
|
|
21
|
+
}
|
|
22
|
+
@media (min-width: 768px) {
|
|
23
|
+
.editor-header {
|
|
24
|
+
flex-direction: row;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
height: 48px;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
.editor-tab-container {
|
|
31
|
+
display: flex;
|
|
32
|
+
gap: 1rem;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
}
|
|
35
|
+
.editor-tab {
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
padding: 0.25rem 0.5rem;
|
|
38
|
+
font-size: small;
|
|
39
|
+
font-weight: 500;
|
|
40
|
+
transition: color 0.2s;
|
|
41
|
+
color: #4b5563;
|
|
42
|
+
&:hover {
|
|
43
|
+
color: #1f2937;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
.editor-tab--active {
|
|
47
|
+
color: #111827;
|
|
48
|
+
border-bottom: 2px solid #111827;
|
|
49
|
+
}
|
|
50
|
+
.editor-textarea {
|
|
51
|
+
width: 100%;
|
|
52
|
+
min-height: 200px;
|
|
53
|
+
margin: 0;
|
|
54
|
+
padding: 16px;
|
|
55
|
+
border: none;
|
|
56
|
+
resize: none;
|
|
57
|
+
outline: none;
|
|
58
|
+
box-sizing: border-box;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* src/css/preview.css */
|
|
62
|
+
.preview {
|
|
63
|
+
color: #111827;
|
|
64
|
+
width: 100%;
|
|
65
|
+
min-height: 200px;
|
|
66
|
+
padding: 16px;
|
|
67
|
+
border: none;
|
|
68
|
+
resize: none;
|
|
69
|
+
outline: none;
|
|
70
|
+
box-sizing: border-box;
|
|
71
|
+
list-style: decimal inside;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* src/css/toolbar.css */
|
|
75
|
+
.toolbar-menu {
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
margin: 0;
|
|
79
|
+
padding: 0;
|
|
80
|
+
gap: 16px;
|
|
81
|
+
box-sizing: border-box;
|
|
82
|
+
}
|
|
83
|
+
.toolbar-button {
|
|
84
|
+
background: none;
|
|
85
|
+
width: 28px;
|
|
86
|
+
height: 28px;
|
|
87
|
+
border: none;
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
transition: background-color 0.2s;
|
|
90
|
+
&:hover {
|
|
91
|
+
background-color: #f3f4f6;
|
|
92
|
+
}
|
|
93
|
+
&:active {
|
|
94
|
+
background-color: #e5e7eb;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* src/css/dropdown.css */
|
|
99
|
+
.md-dropdown {
|
|
100
|
+
position: relative;
|
|
101
|
+
display: inline-flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
}
|
|
104
|
+
.md-dropdown__trigger {
|
|
105
|
+
display: flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
justify-content: center;
|
|
108
|
+
width: 28px;
|
|
109
|
+
height: 28px;
|
|
110
|
+
background: transparent;
|
|
111
|
+
border: none;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
transition: background-color 0.15s ease;
|
|
114
|
+
}
|
|
115
|
+
.md-dropdown__trigger:hover {
|
|
116
|
+
background-color: #f3f4f6;
|
|
117
|
+
}
|
|
118
|
+
.md-dropdown__trigger--disabled {
|
|
119
|
+
cursor: not-allowed;
|
|
120
|
+
opacity: 0.5;
|
|
121
|
+
}
|
|
122
|
+
.md-dropdown__menu {
|
|
123
|
+
position: absolute;
|
|
124
|
+
top: 0;
|
|
125
|
+
left: -35%;
|
|
126
|
+
z-index: 50;
|
|
127
|
+
margin-top: 4px;
|
|
128
|
+
min-width: 40px;
|
|
129
|
+
max-height: 240px;
|
|
130
|
+
overflow-y: auto;
|
|
131
|
+
background: #ffffff;
|
|
132
|
+
border: 1px solid #e5e7eb;
|
|
133
|
+
border-radius: 8px;
|
|
134
|
+
padding: 4px 0;
|
|
135
|
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
|
136
|
+
}
|
|
137
|
+
.md-dropdown__item {
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
gap: 8px;
|
|
141
|
+
padding: 10px 12px;
|
|
142
|
+
font-size: 14px;
|
|
143
|
+
cursor: pointer;
|
|
144
|
+
user-select: none;
|
|
145
|
+
transition: background-color 0.15s ease;
|
|
146
|
+
}
|
|
147
|
+
.md-dropdown__item:hover {
|
|
148
|
+
background-color: #f3f4f6;
|
|
149
|
+
}
|
|
150
|
+
.md-dropdown__item--selected {
|
|
151
|
+
background-color: #fefce8;
|
|
152
|
+
color: #a16207;
|
|
153
|
+
font-weight: 500;
|
|
154
|
+
}
|
|
155
|
+
.md-dropdown__icon {
|
|
156
|
+
display: flex;
|
|
157
|
+
color: #9ca3af;
|
|
158
|
+
}
|
|
159
|
+
.md-dropdown__label {
|
|
160
|
+
white-space: nowrap;
|
|
161
|
+
}
|
|
162
|
+
.dropdown-item {
|
|
163
|
+
color: #374151;
|
|
164
|
+
background-color: #f3f4f6;
|
|
165
|
+
position: relative;
|
|
166
|
+
display: flex;
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
align-items: center;
|
|
169
|
+
gap: 0.5rem;
|
|
170
|
+
padding-left: 0.75rem;
|
|
171
|
+
padding-right: 0.75rem;
|
|
172
|
+
padding-top: 0.625rem;
|
|
173
|
+
padding-bottom: 0.625rem;
|
|
174
|
+
font-size: 0.875rem;
|
|
175
|
+
transition: all ease-in-out;
|
|
176
|
+
}
|
|
177
|
+
.dropdown-item--selected {
|
|
178
|
+
background-color: #fefce8;
|
|
179
|
+
color: #a16207;
|
|
180
|
+
font-weight: 500;
|
|
181
|
+
}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import react__default from 'react';
|
|
4
|
+
import * as lucide_react from 'lucide-react';
|
|
5
|
+
|
|
6
|
+
interface EditorHeaderProps {
|
|
7
|
+
mode: "write" | "preview";
|
|
8
|
+
setMode: (mode: "write" | "preview") => void;
|
|
9
|
+
insertMarkdown: (before: string, after?: string) => void;
|
|
10
|
+
}
|
|
11
|
+
declare function EditorHeader({ mode, setMode, insertMarkdown, }: EditorHeaderProps): react_jsx_runtime.JSX.Element;
|
|
12
|
+
|
|
13
|
+
interface EditorTabProps {
|
|
14
|
+
mode: string;
|
|
15
|
+
setMode: (mode: "write" | "preview") => void;
|
|
16
|
+
}
|
|
17
|
+
declare function EditorTab({ mode, setMode }: EditorTabProps): react_jsx_runtime.JSX.Element;
|
|
18
|
+
|
|
19
|
+
interface EditorTextareaProps {
|
|
20
|
+
value: string;
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
setValue: (value: string) => void;
|
|
23
|
+
onImageUpload?: (file: File) => Promise<string>;
|
|
24
|
+
}
|
|
25
|
+
declare const EditorTextarea: react.ForwardRefExoticComponent<EditorTextareaProps & react.RefAttributes<HTMLTextAreaElement>>;
|
|
26
|
+
|
|
27
|
+
interface MarkdownEditorProps {
|
|
28
|
+
value: string;
|
|
29
|
+
onChange: (v: string) => void;
|
|
30
|
+
onImageUpload?: (file: File) => Promise<string>;
|
|
31
|
+
}
|
|
32
|
+
declare function MarkdownEditor({ value, onChange: setValue, onImageUpload, }: MarkdownEditorProps): react_jsx_runtime.JSX.Element;
|
|
33
|
+
|
|
34
|
+
interface PreviewProps {
|
|
35
|
+
value: string;
|
|
36
|
+
}
|
|
37
|
+
declare function Preview({ value }: PreviewProps): react_jsx_runtime.JSX.Element;
|
|
38
|
+
|
|
39
|
+
interface ToolbarProps {
|
|
40
|
+
insertMarkdown: (before: string, after?: string) => void;
|
|
41
|
+
}
|
|
42
|
+
declare function Toolbar({ insertMarkdown }: ToolbarProps): react_jsx_runtime.JSX.Element;
|
|
43
|
+
|
|
44
|
+
interface ToolbarDropdownProps {
|
|
45
|
+
insertMarkdown: (before: string, after?: string) => void;
|
|
46
|
+
}
|
|
47
|
+
declare function ToolbarDropdownHeading({ insertMarkdown, }: ToolbarDropdownProps): react_jsx_runtime.JSX.Element;
|
|
48
|
+
declare function ToolbarDropdownList({ insertMarkdown }: ToolbarDropdownProps): react_jsx_runtime.JSX.Element;
|
|
49
|
+
|
|
50
|
+
type DropdownOption = {
|
|
51
|
+
value: string;
|
|
52
|
+
label?: string;
|
|
53
|
+
Icon?: react__default.ComponentType<react__default.SVGProps<SVGSVGElement>>;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
type ToolbarDropdownOption = DropdownOption & {
|
|
57
|
+
before: string;
|
|
58
|
+
};
|
|
59
|
+
declare const TOOLBAR_BUTTONS: {
|
|
60
|
+
key: string;
|
|
61
|
+
before: string;
|
|
62
|
+
after: string;
|
|
63
|
+
Icon: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
64
|
+
}[];
|
|
65
|
+
declare const headingOptions: ToolbarDropdownOption[];
|
|
66
|
+
declare const listOptions: ToolbarDropdownOption[];
|
|
67
|
+
|
|
68
|
+
interface UseMarkdownEditorProps {
|
|
69
|
+
value: string;
|
|
70
|
+
setValue: (v: string) => void;
|
|
71
|
+
}
|
|
72
|
+
declare function useMarkdownEditor({ value, setValue }: UseMarkdownEditorProps): {
|
|
73
|
+
textareaRef: react.RefObject<HTMLTextAreaElement | null>;
|
|
74
|
+
insertMarkdown: (before: string, after?: string) => void;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
declare function cx(...classes: (string | false | undefined)[]): string;
|
|
78
|
+
|
|
79
|
+
declare function markdownToHtml(markdown: string): string;
|
|
80
|
+
|
|
81
|
+
export { EditorHeader, EditorTab, EditorTextarea, MarkdownEditor, Preview, TOOLBAR_BUTTONS, Toolbar, ToolbarDropdownHeading, ToolbarDropdownList, cx, headingOptions, listOptions, markdownToHtml, useMarkdownEditor };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import react__default from 'react';
|
|
4
|
+
import * as lucide_react from 'lucide-react';
|
|
5
|
+
|
|
6
|
+
interface EditorHeaderProps {
|
|
7
|
+
mode: "write" | "preview";
|
|
8
|
+
setMode: (mode: "write" | "preview") => void;
|
|
9
|
+
insertMarkdown: (before: string, after?: string) => void;
|
|
10
|
+
}
|
|
11
|
+
declare function EditorHeader({ mode, setMode, insertMarkdown, }: EditorHeaderProps): react_jsx_runtime.JSX.Element;
|
|
12
|
+
|
|
13
|
+
interface EditorTabProps {
|
|
14
|
+
mode: string;
|
|
15
|
+
setMode: (mode: "write" | "preview") => void;
|
|
16
|
+
}
|
|
17
|
+
declare function EditorTab({ mode, setMode }: EditorTabProps): react_jsx_runtime.JSX.Element;
|
|
18
|
+
|
|
19
|
+
interface EditorTextareaProps {
|
|
20
|
+
value: string;
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
setValue: (value: string) => void;
|
|
23
|
+
onImageUpload?: (file: File) => Promise<string>;
|
|
24
|
+
}
|
|
25
|
+
declare const EditorTextarea: react.ForwardRefExoticComponent<EditorTextareaProps & react.RefAttributes<HTMLTextAreaElement>>;
|
|
26
|
+
|
|
27
|
+
interface MarkdownEditorProps {
|
|
28
|
+
value: string;
|
|
29
|
+
onChange: (v: string) => void;
|
|
30
|
+
onImageUpload?: (file: File) => Promise<string>;
|
|
31
|
+
}
|
|
32
|
+
declare function MarkdownEditor({ value, onChange: setValue, onImageUpload, }: MarkdownEditorProps): react_jsx_runtime.JSX.Element;
|
|
33
|
+
|
|
34
|
+
interface PreviewProps {
|
|
35
|
+
value: string;
|
|
36
|
+
}
|
|
37
|
+
declare function Preview({ value }: PreviewProps): react_jsx_runtime.JSX.Element;
|
|
38
|
+
|
|
39
|
+
interface ToolbarProps {
|
|
40
|
+
insertMarkdown: (before: string, after?: string) => void;
|
|
41
|
+
}
|
|
42
|
+
declare function Toolbar({ insertMarkdown }: ToolbarProps): react_jsx_runtime.JSX.Element;
|
|
43
|
+
|
|
44
|
+
interface ToolbarDropdownProps {
|
|
45
|
+
insertMarkdown: (before: string, after?: string) => void;
|
|
46
|
+
}
|
|
47
|
+
declare function ToolbarDropdownHeading({ insertMarkdown, }: ToolbarDropdownProps): react_jsx_runtime.JSX.Element;
|
|
48
|
+
declare function ToolbarDropdownList({ insertMarkdown }: ToolbarDropdownProps): react_jsx_runtime.JSX.Element;
|
|
49
|
+
|
|
50
|
+
type DropdownOption = {
|
|
51
|
+
value: string;
|
|
52
|
+
label?: string;
|
|
53
|
+
Icon?: react__default.ComponentType<react__default.SVGProps<SVGSVGElement>>;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
type ToolbarDropdownOption = DropdownOption & {
|
|
57
|
+
before: string;
|
|
58
|
+
};
|
|
59
|
+
declare const TOOLBAR_BUTTONS: {
|
|
60
|
+
key: string;
|
|
61
|
+
before: string;
|
|
62
|
+
after: string;
|
|
63
|
+
Icon: react.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & react.RefAttributes<SVGSVGElement>>;
|
|
64
|
+
}[];
|
|
65
|
+
declare const headingOptions: ToolbarDropdownOption[];
|
|
66
|
+
declare const listOptions: ToolbarDropdownOption[];
|
|
67
|
+
|
|
68
|
+
interface UseMarkdownEditorProps {
|
|
69
|
+
value: string;
|
|
70
|
+
setValue: (v: string) => void;
|
|
71
|
+
}
|
|
72
|
+
declare function useMarkdownEditor({ value, setValue }: UseMarkdownEditorProps): {
|
|
73
|
+
textareaRef: react.RefObject<HTMLTextAreaElement | null>;
|
|
74
|
+
insertMarkdown: (before: string, after?: string) => void;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
declare function cx(...classes: (string | false | undefined)[]): string;
|
|
78
|
+
|
|
79
|
+
declare function markdownToHtml(markdown: string): string;
|
|
80
|
+
|
|
81
|
+
export { EditorHeader, EditorTab, EditorTextarea, MarkdownEditor, Preview, TOOLBAR_BUTTONS, Toolbar, ToolbarDropdownHeading, ToolbarDropdownList, cx, headingOptions, listOptions, markdownToHtml, useMarkdownEditor };
|