md-editor-lite 0.1.4 → 0.1.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/components/EditorHeader.d.ts +8 -0
- package/dist/components/EditorTab.d.ts +7 -0
- package/dist/components/EditorTextarea.d.ts +9 -0
- package/dist/components/IconDropdown.d.ts +17 -0
- package/dist/components/MarkdownEditor.d.ts +8 -0
- package/dist/components/Preview.d.ts +6 -0
- package/dist/components/Toolbar.d.ts +6 -0
- package/dist/components/ToolbarDropdown.d.ts +6 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/toolbar.d.ts +13 -0
- package/dist/dropdown-JYZ5KVXG.css +101 -0
- package/dist/editor-AUU3A4EA.css +67 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useMarkdownEditor.d.ts +9 -0
- package/dist/index.d.ts +4 -81
- package/dist/index.js +104 -109
- package/dist/index.mjs +109 -110
- package/dist/preview-FACEHC73.css +11 -0
- package/dist/toolbar-YQKH6EMS.css +25 -0
- package/dist/utils/cx.d.ts +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/markdown.d.ts +1 -0
- package/package.json +6 -5
- package/dist/index.css +0 -181
- package/dist/index.d.mts +0 -81
package/dist/index.mjs
CHANGED
|
@@ -1,42 +1,36 @@
|
|
|
1
1
|
// src/components/EditorHeader.tsx
|
|
2
|
-
import
|
|
2
|
+
import "./editor-AUU3A4EA.css";
|
|
3
3
|
function EditorHeader({
|
|
4
4
|
mode,
|
|
5
5
|
setMode,
|
|
6
6
|
insertMarkdown
|
|
7
7
|
}) {
|
|
8
|
-
return /* @__PURE__ */
|
|
9
|
-
/* @__PURE__ */ jsx(EditorTab, { mode, setMode }),
|
|
10
|
-
mode === "write" && /* @__PURE__ */ jsx(Toolbar, { insertMarkdown })
|
|
11
|
-
] });
|
|
8
|
+
return /* @__PURE__ */ React.createElement("header", { className: "editor-header" }, /* @__PURE__ */ React.createElement(EditorTab, { mode, setMode }), mode === "write" && /* @__PURE__ */ React.createElement(Toolbar, { insertMarkdown }));
|
|
12
9
|
}
|
|
13
10
|
|
|
14
11
|
// src/components/EditorTab.tsx
|
|
15
|
-
import
|
|
12
|
+
import "./editor-AUU3A4EA.css";
|
|
16
13
|
function EditorTab({ mode, setMode }) {
|
|
17
|
-
return /* @__PURE__ */
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
)
|
|
34
|
-
] });
|
|
14
|
+
return /* @__PURE__ */ React.createElement("div", { className: "editor-tab-container" }, /* @__PURE__ */ React.createElement(
|
|
15
|
+
"div",
|
|
16
|
+
{
|
|
17
|
+
className: `editor-tab ${mode === "write" ? "editor-tab--active" : ""}`,
|
|
18
|
+
onClick: () => setMode("write")
|
|
19
|
+
},
|
|
20
|
+
"Write"
|
|
21
|
+
), /* @__PURE__ */ React.createElement(
|
|
22
|
+
"div",
|
|
23
|
+
{
|
|
24
|
+
className: `editor-tab ${mode === "preview" ? "editor-tab--active" : ""}`,
|
|
25
|
+
onClick: () => setMode("preview")
|
|
26
|
+
},
|
|
27
|
+
"Preview"
|
|
28
|
+
));
|
|
35
29
|
}
|
|
36
30
|
|
|
37
31
|
// src/components/EditorTextarea.tsx
|
|
38
32
|
import { forwardRef } from "react";
|
|
39
|
-
import
|
|
33
|
+
import "./editor-AUU3A4EA.css";
|
|
40
34
|
var EditorTextarea = forwardRef(({ value, placeholder, setValue, onImageUpload }, ref) => {
|
|
41
35
|
const handleDrop = async (e) => {
|
|
42
36
|
e.preventDefault();
|
|
@@ -51,7 +45,7 @@ var EditorTextarea = forwardRef(({ value, placeholder, setValue, onImageUpload }
|
|
|
51
45
|
`);
|
|
52
46
|
}
|
|
53
47
|
};
|
|
54
|
-
return /* @__PURE__ */
|
|
48
|
+
return /* @__PURE__ */ React.createElement(
|
|
55
49
|
"textarea",
|
|
56
50
|
{
|
|
57
51
|
ref,
|
|
@@ -98,7 +92,7 @@ function useMarkdownEditor({ value, setValue }) {
|
|
|
98
92
|
}
|
|
99
93
|
|
|
100
94
|
// src/components/MarkdownEditor.tsx
|
|
101
|
-
import
|
|
95
|
+
import "./editor-AUU3A4EA.css";
|
|
102
96
|
function MarkdownEditor({
|
|
103
97
|
value,
|
|
104
98
|
onChange: setValue,
|
|
@@ -109,25 +103,22 @@ function MarkdownEditor({
|
|
|
109
103
|
setValue
|
|
110
104
|
});
|
|
111
105
|
const [mode, setMode] = useState("write");
|
|
112
|
-
return /* @__PURE__ */
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
) : /* @__PURE__ */ jsx4(Preview, { value })
|
|
130
|
-
] });
|
|
106
|
+
return /* @__PURE__ */ React.createElement("div", { className: "editor" }, /* @__PURE__ */ React.createElement(
|
|
107
|
+
EditorHeader,
|
|
108
|
+
{
|
|
109
|
+
mode,
|
|
110
|
+
setMode,
|
|
111
|
+
insertMarkdown
|
|
112
|
+
}
|
|
113
|
+
), mode === "write" ? /* @__PURE__ */ React.createElement(
|
|
114
|
+
EditorTextarea,
|
|
115
|
+
{
|
|
116
|
+
ref: textareaRef,
|
|
117
|
+
value,
|
|
118
|
+
setValue,
|
|
119
|
+
onImageUpload
|
|
120
|
+
}
|
|
121
|
+
) : /* @__PURE__ */ React.createElement(Preview, { value }));
|
|
131
122
|
}
|
|
132
123
|
|
|
133
124
|
// src/utils/markdown.ts
|
|
@@ -135,7 +126,7 @@ function parseBold(text) {
|
|
|
135
126
|
return text.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
|
|
136
127
|
}
|
|
137
128
|
function parseItalic(text) {
|
|
138
|
-
return text.replace(
|
|
129
|
+
return text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<em>$1</em>");
|
|
139
130
|
}
|
|
140
131
|
function parseInlineCode(text) {
|
|
141
132
|
return text.replace(/`(.+?)`/g, "<code>$1</code>");
|
|
@@ -143,6 +134,15 @@ function parseInlineCode(text) {
|
|
|
143
134
|
function parseBlockquote(text) {
|
|
144
135
|
return text.replace(/^> (.+)$/gm, "<blockquote>$1</blockquote>");
|
|
145
136
|
}
|
|
137
|
+
function parseStrikethrough(text) {
|
|
138
|
+
return text.replace(/~~(.+?)~~/g, "<del>$1</del>");
|
|
139
|
+
}
|
|
140
|
+
function parseUnderline(text) {
|
|
141
|
+
return text.replace(/__(.+?)__/g, "<u>$1</u>");
|
|
142
|
+
}
|
|
143
|
+
function parseHr(text) {
|
|
144
|
+
return text.replace(/^---$/gm, "<hr />");
|
|
145
|
+
}
|
|
146
146
|
function parseImages(text) {
|
|
147
147
|
return text.replace(
|
|
148
148
|
/!\[(.*?)\]\(([^)]*?)\)/g,
|
|
@@ -181,23 +181,26 @@ function parseLineBreaks(text) {
|
|
|
181
181
|
}
|
|
182
182
|
function markdownToHtml(markdown) {
|
|
183
183
|
let html = markdown;
|
|
184
|
+
html = parseHr(html);
|
|
185
|
+
html = parseHeadings(html);
|
|
186
|
+
html = parseBlockquote(html);
|
|
187
|
+
html = parseUnorderedList(html);
|
|
188
|
+
html = parseOrderedList(html);
|
|
184
189
|
html = parseBold(html);
|
|
190
|
+
html = parseUnderline(html);
|
|
191
|
+
html = parseStrikethrough(html);
|
|
185
192
|
html = parseItalic(html);
|
|
186
193
|
html = parseInlineCode(html);
|
|
187
|
-
html = parseBlockquote(html);
|
|
188
194
|
html = parseImages(html);
|
|
189
195
|
html = parseLinks(html);
|
|
190
|
-
html = parseHeadings(html);
|
|
191
|
-
html = parseUnorderedList(html);
|
|
192
|
-
html = parseOrderedList(html);
|
|
193
196
|
html = parseLineBreaks(html);
|
|
194
197
|
return html;
|
|
195
198
|
}
|
|
196
199
|
|
|
197
200
|
// src/components/Preview.tsx
|
|
198
|
-
import
|
|
201
|
+
import "./preview-FACEHC73.css";
|
|
199
202
|
function Preview({ value }) {
|
|
200
|
-
return /* @__PURE__ */
|
|
203
|
+
return /* @__PURE__ */ React.createElement(
|
|
201
204
|
"div",
|
|
202
205
|
{
|
|
203
206
|
className: "preview",
|
|
@@ -218,13 +221,19 @@ import {
|
|
|
218
221
|
Heading3Icon,
|
|
219
222
|
ListOrderedIcon,
|
|
220
223
|
ListIcon,
|
|
221
|
-
QuoteIcon
|
|
224
|
+
QuoteIcon,
|
|
225
|
+
StrikethroughIcon,
|
|
226
|
+
UnderlineIcon,
|
|
227
|
+
ListEndIcon
|
|
222
228
|
} from "lucide-react";
|
|
223
229
|
var TOOLBAR_BUTTONS = [
|
|
224
230
|
{ key: "bold", before: "**", after: "**", Icon: BoldIcon },
|
|
225
231
|
{ key: "italic", before: "*", after: "*", Icon: ItalicIcon },
|
|
226
232
|
{ key: "code", before: "`", after: "`", Icon: CodeIcon },
|
|
227
233
|
{ key: "blockquote", before: "> ", after: "", Icon: QuoteIcon },
|
|
234
|
+
{ key: "strikethrough", before: "~~", after: "~~", Icon: StrikethroughIcon },
|
|
235
|
+
{ key: "underline", before: "__", after: "__", Icon: UnderlineIcon },
|
|
236
|
+
{ key: "horizontal rule", before: "\n---\n", after: "", Icon: ListEndIcon },
|
|
228
237
|
{ key: "link", before: "[", after: "]()", Icon: LinkIcon }
|
|
229
238
|
];
|
|
230
239
|
var headingOptions = [
|
|
@@ -238,25 +247,21 @@ var listOptions = [
|
|
|
238
247
|
];
|
|
239
248
|
|
|
240
249
|
// src/components/Toolbar.tsx
|
|
241
|
-
import
|
|
250
|
+
import "./toolbar-YQKH6EMS.css";
|
|
242
251
|
function Toolbar({ insertMarkdown }) {
|
|
243
|
-
return /* @__PURE__ */
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
)),
|
|
253
|
-
/* @__PURE__ */ jsx6(ToolbarDropdownHeading, { insertMarkdown }),
|
|
254
|
-
/* @__PURE__ */ jsx6(ToolbarDropdownList, { insertMarkdown })
|
|
255
|
-
] });
|
|
252
|
+
return /* @__PURE__ */ React.createElement("menu", { className: "toolbar-menu" }, TOOLBAR_BUTTONS.map(({ key, before, after, Icon }) => /* @__PURE__ */ React.createElement(
|
|
253
|
+
"button",
|
|
254
|
+
{
|
|
255
|
+
key,
|
|
256
|
+
className: "toolbar-button",
|
|
257
|
+
onClick: () => insertMarkdown(before, after)
|
|
258
|
+
},
|
|
259
|
+
/* @__PURE__ */ React.createElement(Icon, { size: 18 })
|
|
260
|
+
)), /* @__PURE__ */ React.createElement(ToolbarDropdownHeading, { insertMarkdown }), /* @__PURE__ */ React.createElement(ToolbarDropdownList, { insertMarkdown }));
|
|
256
261
|
}
|
|
257
262
|
|
|
258
263
|
// src/components/IconDropdown.tsx
|
|
259
|
-
import
|
|
264
|
+
import React2 from "react";
|
|
260
265
|
|
|
261
266
|
// src/utils/cx.ts
|
|
262
267
|
function cx(...classes) {
|
|
@@ -264,7 +269,7 @@ function cx(...classes) {
|
|
|
264
269
|
}
|
|
265
270
|
|
|
266
271
|
// src/components/IconDropdown.tsx
|
|
267
|
-
import
|
|
272
|
+
import "./dropdown-JYZ5KVXG.css";
|
|
268
273
|
function IconDropdown({
|
|
269
274
|
className,
|
|
270
275
|
disabled,
|
|
@@ -273,12 +278,12 @@ function IconDropdown({
|
|
|
273
278
|
triggerIcon,
|
|
274
279
|
onChange
|
|
275
280
|
}) {
|
|
276
|
-
const [isOpen, setIsOpen] =
|
|
277
|
-
const dropdownRef =
|
|
281
|
+
const [isOpen, setIsOpen] = React2.useState(false);
|
|
282
|
+
const dropdownRef = React2.useRef(null);
|
|
278
283
|
const toggle = () => {
|
|
279
284
|
if (!disabled) setIsOpen((prev) => !prev);
|
|
280
285
|
};
|
|
281
|
-
|
|
286
|
+
React2.useEffect(() => {
|
|
282
287
|
const handleClickOutside = (e) => {
|
|
283
288
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
284
289
|
setIsOpen(false);
|
|
@@ -287,52 +292,46 @@ function IconDropdown({
|
|
|
287
292
|
document.addEventListener("mousedown", handleClickOutside);
|
|
288
293
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
289
294
|
}, []);
|
|
290
|
-
return /* @__PURE__ */
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
295
|
+
return /* @__PURE__ */ React2.createElement("div", { ref: dropdownRef, className: cx("md-dropdown", className) }, /* @__PURE__ */ React2.createElement(
|
|
296
|
+
"button",
|
|
297
|
+
{
|
|
298
|
+
type: "button",
|
|
299
|
+
onClick: toggle,
|
|
300
|
+
disabled,
|
|
301
|
+
className: cx(
|
|
302
|
+
"md-dropdown__trigger",
|
|
303
|
+
disabled && "md-dropdown__trigger--disabled"
|
|
304
|
+
)
|
|
305
|
+
},
|
|
306
|
+
triggerIcon
|
|
307
|
+
), isOpen && /* @__PURE__ */ React2.createElement("ul", { className: "md-dropdown__menu" }, options.map((option) => /* @__PURE__ */ React2.createElement(
|
|
308
|
+
"li",
|
|
309
|
+
{
|
|
310
|
+
key: option.value,
|
|
311
|
+
className: cx(
|
|
312
|
+
"md-dropdown__item",
|
|
313
|
+
selected && "md-dropdown__item--selected"
|
|
314
|
+
),
|
|
315
|
+
onClick: () => {
|
|
316
|
+
onChange(option.value);
|
|
317
|
+
setIsOpen(false);
|
|
302
318
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
className: cx(
|
|
308
|
-
"md-dropdown__item",
|
|
309
|
-
selected && "md-dropdown__item--selected"
|
|
310
|
-
),
|
|
311
|
-
onClick: () => {
|
|
312
|
-
onChange(option.value);
|
|
313
|
-
setIsOpen(false);
|
|
314
|
-
},
|
|
315
|
-
children: [
|
|
316
|
-
option.Icon && /* @__PURE__ */ jsx7("span", { className: "md-dropdown__icon", children: /* @__PURE__ */ jsx7(option.Icon, {}) }),
|
|
317
|
-
option.label && /* @__PURE__ */ jsx7("span", { className: "md-dropdown__label", children: option.label })
|
|
318
|
-
]
|
|
319
|
-
},
|
|
320
|
-
option.value
|
|
321
|
-
)) })
|
|
322
|
-
] });
|
|
319
|
+
},
|
|
320
|
+
option.Icon && /* @__PURE__ */ React2.createElement("span", { className: "md-dropdown__icon" }, /* @__PURE__ */ React2.createElement(option.Icon, null)),
|
|
321
|
+
option.label && /* @__PURE__ */ React2.createElement("span", { className: "md-dropdown__label" }, option.label)
|
|
322
|
+
))));
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
// src/components/ToolbarDropdown.tsx
|
|
326
326
|
import { Heading1Icon as Heading1Icon2, ListIcon as ListIcon2 } from "lucide-react";
|
|
327
|
-
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
328
327
|
function ToolbarDropdownHeading({
|
|
329
328
|
insertMarkdown
|
|
330
329
|
}) {
|
|
331
|
-
return /* @__PURE__ */
|
|
330
|
+
return /* @__PURE__ */ React.createElement(
|
|
332
331
|
IconDropdown,
|
|
333
332
|
{
|
|
334
333
|
options: headingOptions,
|
|
335
|
-
triggerIcon: /* @__PURE__ */
|
|
334
|
+
triggerIcon: /* @__PURE__ */ React.createElement(Heading1Icon2, null),
|
|
336
335
|
onChange: (value) => {
|
|
337
336
|
const option = headingOptions.find((o) => o.value === value);
|
|
338
337
|
if (option) insertMarkdown(option.before);
|
|
@@ -341,11 +340,11 @@ function ToolbarDropdownHeading({
|
|
|
341
340
|
);
|
|
342
341
|
}
|
|
343
342
|
function ToolbarDropdownList({ insertMarkdown }) {
|
|
344
|
-
return /* @__PURE__ */
|
|
343
|
+
return /* @__PURE__ */ React.createElement(
|
|
345
344
|
IconDropdown,
|
|
346
345
|
{
|
|
347
346
|
options: listOptions,
|
|
348
|
-
triggerIcon: /* @__PURE__ */
|
|
347
|
+
triggerIcon: /* @__PURE__ */ React.createElement(ListIcon2, null),
|
|
349
348
|
onChange: (value) => {
|
|
350
349
|
const option = listOptions.find((o) => o.value === value);
|
|
351
350
|
if (option) insertMarkdown(option.before);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.toolbar-menu {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
gap: 16px;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.toolbar-button {
|
|
11
|
+
background: none;
|
|
12
|
+
width: 28px;
|
|
13
|
+
height: 28px;
|
|
14
|
+
border: none;
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
transition: background-color 0.2s;
|
|
17
|
+
|
|
18
|
+
&:hover {
|
|
19
|
+
background-color: #f3f4f6;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&:active {
|
|
23
|
+
background-color: #e5e7eb;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cx(...classes: (string | false | undefined)[]): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function markdownToHtml(markdown: string): string;
|
package/package.json
CHANGED
|
@@ -10,17 +10,17 @@
|
|
|
10
10
|
"lightweight",
|
|
11
11
|
"textarea"
|
|
12
12
|
],
|
|
13
|
-
"version": "0.1.
|
|
13
|
+
"version": "0.1.6",
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
16
17
|
"import": "./dist/index.mjs",
|
|
17
|
-
"require": "./dist/index.js"
|
|
18
|
-
"types": "./dist/index.d.ts"
|
|
18
|
+
"require": "./dist/index.js"
|
|
19
19
|
},
|
|
20
20
|
"./style.css": "./dist/style.css"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
-
"build": "tsup
|
|
23
|
+
"build": "tsup && tsc -p tsconfig.build.json"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"react": ">=18"
|
|
@@ -40,5 +40,6 @@
|
|
|
40
40
|
],
|
|
41
41
|
"sideEffects": [
|
|
42
42
|
"*.css"
|
|
43
|
-
]
|
|
43
|
+
],
|
|
44
|
+
"style": "dist/style.css"
|
|
44
45
|
}
|
package/dist/index.css
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
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
|
-
}
|