@elixpo/lixeditor 2.2.0 → 2.5.2
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.cjs +912 -886
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +905 -883
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -18,14 +18,18 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
20
20
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
25
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
26
|
mod
|
|
23
27
|
));
|
|
24
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
29
|
|
|
26
30
|
// src/index.js
|
|
27
|
-
var
|
|
28
|
-
__export(
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
29
33
|
BlockEquation: () => BlockEquation,
|
|
30
34
|
ButtonBlock: () => ButtonBlock,
|
|
31
35
|
DateInline: () => DateInline,
|
|
@@ -44,7 +48,7 @@ __export(src_exports, {
|
|
|
44
48
|
useLinkPreview: () => useLinkPreview,
|
|
45
49
|
useLixTheme: () => useLixTheme
|
|
46
50
|
});
|
|
47
|
-
module.exports = __toCommonJS(
|
|
51
|
+
module.exports = __toCommonJS(index_exports);
|
|
48
52
|
|
|
49
53
|
// src/editor/LixEditor.jsx
|
|
50
54
|
var import_core = require("@blocknote/core");
|
|
@@ -54,7 +58,7 @@ var import_react19 = require("react");
|
|
|
54
58
|
|
|
55
59
|
// src/hooks/useLixTheme.js
|
|
56
60
|
var import_react = require("react");
|
|
57
|
-
|
|
61
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
58
62
|
var LixThemeContext = (0, import_react.createContext)(null);
|
|
59
63
|
function LixThemeProvider({ children, defaultTheme = "light", storageKey = "lixeditor_theme" }) {
|
|
60
64
|
const [theme, setTheme] = (0, import_react.useState)(defaultTheme);
|
|
@@ -62,26 +66,22 @@ function LixThemeProvider({ children, defaultTheme = "light", storageKey = "lixe
|
|
|
62
66
|
(0, import_react.useEffect)(() => {
|
|
63
67
|
if (storageKey) {
|
|
64
68
|
const saved = localStorage.getItem(storageKey);
|
|
65
|
-
if (saved === "dark" || saved === "light")
|
|
66
|
-
setTheme(saved);
|
|
69
|
+
if (saved === "dark" || saved === "light") setTheme(saved);
|
|
67
70
|
}
|
|
68
71
|
setMounted(true);
|
|
69
72
|
}, [storageKey]);
|
|
70
73
|
(0, import_react.useEffect)(() => {
|
|
71
|
-
if (!mounted)
|
|
72
|
-
return;
|
|
74
|
+
if (!mounted) return;
|
|
73
75
|
document.documentElement.setAttribute("data-theme", theme);
|
|
74
|
-
if (storageKey)
|
|
75
|
-
localStorage.setItem(storageKey, theme);
|
|
76
|
+
if (storageKey) localStorage.setItem(storageKey, theme);
|
|
76
77
|
}, [theme, mounted, storageKey]);
|
|
77
78
|
const toggleTheme = () => setTheme((t) => t === "dark" ? "light" : "dark");
|
|
78
79
|
const isDark = theme === "dark";
|
|
79
|
-
return
|
|
80
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LixThemeContext.Provider, { value: { theme, setTheme, toggleTheme, isDark, mounted }, children });
|
|
80
81
|
}
|
|
81
82
|
function useLixTheme() {
|
|
82
83
|
const ctx = (0, import_react.useContext)(LixThemeContext);
|
|
83
|
-
if (ctx)
|
|
84
|
-
return ctx;
|
|
84
|
+
if (ctx) return ctx;
|
|
85
85
|
const isDark = typeof document !== "undefined" && document.documentElement.getAttribute("data-theme") === "dark";
|
|
86
86
|
return { theme: isDark ? "dark" : "light", isDark, toggleTheme: () => {
|
|
87
87
|
}, setTheme: () => {
|
|
@@ -92,17 +92,13 @@ function useLixTheme() {
|
|
|
92
92
|
var import_react2 = require("@blocknote/react");
|
|
93
93
|
var import_react3 = require("react");
|
|
94
94
|
var import_katex = __toESM(require("katex"));
|
|
95
|
-
|
|
95
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
96
96
|
function stripDelimiters(raw) {
|
|
97
97
|
let s = raw.trim();
|
|
98
|
-
if (s.startsWith("\\[") && s.endsWith("\\]"))
|
|
99
|
-
|
|
100
|
-
if (s.startsWith("
|
|
101
|
-
|
|
102
|
-
if (s.startsWith("\\(") && s.endsWith("\\)"))
|
|
103
|
-
return s.slice(2, -2).trim();
|
|
104
|
-
if (s.startsWith("$") && s.endsWith("$") && s.length > 2)
|
|
105
|
-
return s.slice(1, -1).trim();
|
|
98
|
+
if (s.startsWith("\\[") && s.endsWith("\\]")) return s.slice(2, -2).trim();
|
|
99
|
+
if (s.startsWith("$$") && s.endsWith("$$")) return s.slice(2, -2).trim();
|
|
100
|
+
if (s.startsWith("\\(") && s.endsWith("\\)")) return s.slice(2, -2).trim();
|
|
101
|
+
if (s.startsWith("$") && s.endsWith("$") && s.length > 2) return s.slice(1, -1).trim();
|
|
106
102
|
return s;
|
|
107
103
|
}
|
|
108
104
|
function renderKaTeX(latex, displayMode = true) {
|
|
@@ -128,8 +124,7 @@ var BlockEquation = (0, import_react2.createReactBlockSpec)(
|
|
|
128
124
|
const inputRef = (0, import_react3.useRef)(null);
|
|
129
125
|
const debounceRef = (0, import_react3.useRef)(null);
|
|
130
126
|
(0, import_react3.useEffect)(() => {
|
|
131
|
-
if (editing)
|
|
132
|
-
inputRef.current?.focus();
|
|
127
|
+
if (editing) inputRef.current?.focus();
|
|
133
128
|
}, [editing]);
|
|
134
129
|
const handleCodeChange = (0, import_react3.useCallback)((e) => {
|
|
135
130
|
const v = e.target.value;
|
|
@@ -145,60 +140,70 @@ var BlockEquation = (0, import_react2.createReactBlockSpec)(
|
|
|
145
140
|
setEditing(false);
|
|
146
141
|
};
|
|
147
142
|
if (editing) {
|
|
148
|
-
return
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
143
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mermaid-block mermaid-block--editing", children: [
|
|
144
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mermaid-block-header", children: [
|
|
145
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "#c4b5fd", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z" }) }),
|
|
146
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "LaTeX Equation" }),
|
|
147
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { marginLeft: "auto", fontSize: "10px", color: "var(--text-faint)" }, children: "Shift+Enter to save" })
|
|
148
|
+
] }),
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
150
|
+
"textarea",
|
|
151
|
+
{
|
|
152
|
+
ref: inputRef,
|
|
153
|
+
value,
|
|
154
|
+
onChange: handleCodeChange,
|
|
155
|
+
onKeyDown: (e) => {
|
|
156
|
+
if (e.key === "Enter" && e.shiftKey) {
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
save();
|
|
159
|
+
}
|
|
160
|
+
if (e.key === "Escape") {
|
|
161
|
+
setEditing(false);
|
|
162
|
+
setValue(block.props.latex || "");
|
|
163
|
+
setLivePreview(block.props.latex || "");
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
placeholder: "E = mc^2",
|
|
167
|
+
rows: 4,
|
|
168
|
+
className: "mermaid-block-textarea"
|
|
169
|
+
}
|
|
170
|
+
),
|
|
171
|
+
livePreview.trim() && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "latex-live-preview", children: [
|
|
172
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "latex-live-preview-label", children: "Preview" }),
|
|
173
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { dangerouslySetInnerHTML: { __html: renderKaTeX(livePreview) } })
|
|
174
|
+
] }),
|
|
175
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mermaid-block-actions", children: [
|
|
176
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: () => {
|
|
179
177
|
setEditing(false);
|
|
180
178
|
setValue(block.props.latex || "");
|
|
181
179
|
setLivePreview(block.props.latex || "");
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
180
|
+
}, className: "mermaid-btn-cancel", children: "Cancel" }),
|
|
181
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: save, className: "mermaid-btn-save", disabled: !value.trim(), children: "Done" })
|
|
182
|
+
] })
|
|
183
|
+
] });
|
|
186
184
|
}
|
|
187
185
|
const latex = block.props.latex;
|
|
188
186
|
if (!latex) {
|
|
189
|
-
return
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
188
|
+
"div",
|
|
189
|
+
{
|
|
190
|
+
onClick: () => setEditing(true),
|
|
191
|
+
className: "mermaid-block mermaid-block--empty",
|
|
192
|
+
children: [
|
|
193
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z" }) }),
|
|
194
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Click to add a block equation" })
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
);
|
|
196
198
|
}
|
|
197
|
-
return
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
200
|
+
"div",
|
|
201
|
+
{
|
|
202
|
+
onClick: () => setEditing(true),
|
|
203
|
+
className: "editor-block-equation",
|
|
204
|
+
dangerouslySetInnerHTML: { __html: renderKaTeX(latex) }
|
|
205
|
+
}
|
|
206
|
+
);
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
);
|
|
@@ -206,7 +211,7 @@ var BlockEquation = (0, import_react2.createReactBlockSpec)(
|
|
|
206
211
|
// src/blocks/MermaidBlock.jsx
|
|
207
212
|
var import_react4 = require("@blocknote/react");
|
|
208
213
|
var import_react5 = require("react");
|
|
209
|
-
|
|
214
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
210
215
|
var darkConfig = {
|
|
211
216
|
startOnLoad: false,
|
|
212
217
|
securityLevel: "loose",
|
|
@@ -321,12 +326,10 @@ function MermaidPreview({ diagram, isDark, interactive }) {
|
|
|
321
326
|
let cancelled = false;
|
|
322
327
|
const id = `mermaid-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
323
328
|
queueRender(async () => {
|
|
324
|
-
if (cancelled)
|
|
325
|
-
return;
|
|
329
|
+
if (cancelled) return;
|
|
326
330
|
try {
|
|
327
331
|
const mermaid = await getMermaid(isDark);
|
|
328
|
-
if (cancelled)
|
|
329
|
-
return;
|
|
332
|
+
if (cancelled) return;
|
|
330
333
|
let diagramText = diagram.trim();
|
|
331
334
|
diagramText = diagramText.replace(/^\s*gitgraph/i, "gitGraph");
|
|
332
335
|
diagramText = diagramText.replace(/^\s*sequencediagram/i, "sequenceDiagram");
|
|
@@ -373,11 +376,9 @@ function MermaidPreview({ diagram, isDark, interactive }) {
|
|
|
373
376
|
};
|
|
374
377
|
}, [diagram, isDark]);
|
|
375
378
|
(0, import_react5.useEffect)(() => {
|
|
376
|
-
if (!interactive)
|
|
377
|
-
return;
|
|
379
|
+
if (!interactive) return;
|
|
378
380
|
const el = containerRef.current;
|
|
379
|
-
if (!el)
|
|
380
|
-
return;
|
|
381
|
+
if (!el) return;
|
|
381
382
|
const handleWheel = (e) => {
|
|
382
383
|
e.preventDefault();
|
|
383
384
|
e.stopPropagation();
|
|
@@ -390,16 +391,14 @@ function MermaidPreview({ diagram, isDark, interactive }) {
|
|
|
390
391
|
return () => el.removeEventListener("wheel", handleWheel);
|
|
391
392
|
}, [svgHTML, interactive]);
|
|
392
393
|
const handleMouseDown = (0, import_react5.useCallback)((e) => {
|
|
393
|
-
if (!interactive || e.button !== 0)
|
|
394
|
-
return;
|
|
394
|
+
if (!interactive || e.button !== 0) return;
|
|
395
395
|
e.preventDefault();
|
|
396
396
|
dragging.current = true;
|
|
397
397
|
dragStart.current = { x: e.clientX, y: e.clientY };
|
|
398
398
|
panStart.current = { ...pan };
|
|
399
399
|
}, [pan, interactive]);
|
|
400
400
|
const handleMouseMove = (0, import_react5.useCallback)((e) => {
|
|
401
|
-
if (!dragging.current)
|
|
402
|
-
return;
|
|
401
|
+
if (!dragging.current) return;
|
|
403
402
|
const dx = e.clientX - dragStart.current.x;
|
|
404
403
|
const dy = e.clientY - dragStart.current.y;
|
|
405
404
|
setPan({ x: panStart.current.x + dx, y: panStart.current.y + dy });
|
|
@@ -408,8 +407,7 @@ function MermaidPreview({ diagram, isDark, interactive }) {
|
|
|
408
407
|
dragging.current = false;
|
|
409
408
|
}, []);
|
|
410
409
|
(0, import_react5.useEffect)(() => {
|
|
411
|
-
if (!interactive)
|
|
412
|
-
return;
|
|
410
|
+
if (!interactive) return;
|
|
413
411
|
window.addEventListener("mousemove", handleMouseMove);
|
|
414
412
|
window.addEventListener("mouseup", handleMouseUp);
|
|
415
413
|
return () => {
|
|
@@ -422,64 +420,83 @@ function MermaidPreview({ diagram, isDark, interactive }) {
|
|
|
422
420
|
setPan({ x: 0, y: 0 });
|
|
423
421
|
}, []);
|
|
424
422
|
if (error) {
|
|
425
|
-
return
|
|
423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mermaid-viewport mermaid-viewport--compact", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("pre", { style: { color: "#f87171", fontSize: "12px", whiteSpace: "pre-wrap", padding: "16px", margin: 0 }, children: error }) });
|
|
426
424
|
}
|
|
427
425
|
if (!diagram?.trim()) {
|
|
428
|
-
return
|
|
426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mermaid-viewport mermaid-viewport--compact", style: { display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "var(--text-faint)", fontSize: "12px" }, children: "Preview will appear here..." }) });
|
|
429
427
|
}
|
|
430
428
|
if (!svgHTML) {
|
|
431
|
-
return
|
|
429
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mermaid-viewport mermaid-viewport--compact", style: { display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "var(--text-faint)", fontSize: "13px" }, children: "Rendering..." }) });
|
|
432
430
|
}
|
|
433
|
-
return
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
431
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
432
|
+
"div",
|
|
433
|
+
{
|
|
434
|
+
ref: containerRef,
|
|
435
|
+
className: interactive ? "mermaid-viewport" : "mermaid-viewport mermaid-viewport--compact",
|
|
436
|
+
onMouseDown: handleMouseDown,
|
|
437
|
+
children: [
|
|
438
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
439
|
+
"div",
|
|
440
|
+
{
|
|
441
|
+
className: "mermaid-block-svg",
|
|
442
|
+
style: {
|
|
443
|
+
transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
|
|
444
|
+
transformOrigin: "center center"
|
|
445
|
+
},
|
|
446
|
+
dangerouslySetInnerHTML: { __html: svgHTML }
|
|
447
|
+
}
|
|
448
|
+
),
|
|
449
|
+
interactive && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mermaid-zoom-controls", children: [
|
|
450
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
451
|
+
"button",
|
|
452
|
+
{
|
|
453
|
+
onClick: (e) => {
|
|
454
|
+
e.stopPropagation();
|
|
455
|
+
setZoom((z) => Math.min(3, z + 0.2));
|
|
456
|
+
},
|
|
457
|
+
className: "mermaid-zoom-btn",
|
|
458
|
+
title: "Zoom in",
|
|
459
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
461
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
462
|
+
] })
|
|
463
|
+
}
|
|
464
|
+
),
|
|
465
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "mermaid-zoom-label", children: [
|
|
466
|
+
Math.round(zoom * 100),
|
|
467
|
+
"%"
|
|
468
|
+
] }),
|
|
469
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
470
|
+
"button",
|
|
471
|
+
{
|
|
472
|
+
onClick: (e) => {
|
|
473
|
+
e.stopPropagation();
|
|
474
|
+
setZoom((z) => Math.max(0.3, z - 0.2));
|
|
475
|
+
},
|
|
476
|
+
className: "mermaid-zoom-btn",
|
|
477
|
+
title: "Zoom out",
|
|
478
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) })
|
|
479
|
+
}
|
|
480
|
+
),
|
|
481
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
482
|
+
"button",
|
|
483
|
+
{
|
|
484
|
+
onClick: (e) => {
|
|
485
|
+
e.stopPropagation();
|
|
486
|
+
resetView();
|
|
487
|
+
},
|
|
488
|
+
className: "mermaid-zoom-btn",
|
|
489
|
+
title: "Reset view",
|
|
490
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
491
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M3.51 15a9 9 0 1 0 2.13-9.36L1 10" }),
|
|
492
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polyline", { points: "1 4 1 10 7 10" })
|
|
493
|
+
] })
|
|
494
|
+
}
|
|
495
|
+
)
|
|
496
|
+
] })
|
|
497
|
+
]
|
|
498
|
+
}
|
|
499
|
+
);
|
|
483
500
|
}
|
|
484
501
|
var MermaidBlock = (0, import_react4.createReactBlockSpec)(
|
|
485
502
|
{
|
|
@@ -498,8 +515,7 @@ var MermaidBlock = (0, import_react4.createReactBlockSpec)(
|
|
|
498
515
|
const inputRef = (0, import_react5.useRef)(null);
|
|
499
516
|
const debounceRef = (0, import_react5.useRef)(null);
|
|
500
517
|
(0, import_react5.useEffect)(() => {
|
|
501
|
-
if (editing && inputRef.current)
|
|
502
|
-
inputRef.current.focus();
|
|
518
|
+
if (editing && inputRef.current) inputRef.current.focus();
|
|
503
519
|
}, [editing]);
|
|
504
520
|
const handleCodeChange = (0, import_react5.useCallback)((e) => {
|
|
505
521
|
const v = e.target.value;
|
|
@@ -521,93 +537,96 @@ var MermaidBlock = (0, import_react4.createReactBlockSpec)(
|
|
|
521
537
|
}
|
|
522
538
|
}, [editor, block.id]);
|
|
523
539
|
if (editing) {
|
|
524
|
-
return
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
540
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mermaid-block mermaid-block--editing", children: [
|
|
541
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mermaid-block-header", children: [
|
|
542
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "#c4b5fd", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 3l1.912 5.813a2 2 0 001.275 1.275L21 12l-5.813 1.912a2 2 0 00-1.275 1.275L12 21l-1.912-5.813a2 2 0 00-1.275-1.275L3 12l5.813-1.912a2 2 0 001.275-1.275L12 3z" }) }),
|
|
543
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Mermaid Diagram" }),
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { marginLeft: "auto", fontSize: "10px", color: "var(--text-faint)" }, children: "Shift+Enter to save" })
|
|
545
|
+
] }),
|
|
546
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
547
|
+
"textarea",
|
|
548
|
+
{
|
|
549
|
+
ref: inputRef,
|
|
550
|
+
value,
|
|
551
|
+
onChange: handleCodeChange,
|
|
552
|
+
onKeyDown: (e) => {
|
|
553
|
+
if (e.key === "Enter" && e.shiftKey) {
|
|
554
|
+
e.preventDefault();
|
|
555
|
+
save();
|
|
556
|
+
}
|
|
557
|
+
if (e.key === "Escape") {
|
|
558
|
+
setEditing(false);
|
|
559
|
+
setValue(block.props.diagram || "");
|
|
560
|
+
setLivePreview(block.props.diagram || "");
|
|
561
|
+
}
|
|
562
|
+
if (e.key === "Tab") {
|
|
563
|
+
e.preventDefault();
|
|
564
|
+
const start = e.target.selectionStart;
|
|
565
|
+
const end = e.target.selectionEnd;
|
|
566
|
+
const newVal = value.substring(0, start) + " " + value.substring(end);
|
|
567
|
+
setValue(newVal);
|
|
568
|
+
setLivePreview(newVal);
|
|
569
|
+
requestAnimationFrame(() => {
|
|
570
|
+
e.target.selectionStart = e.target.selectionEnd = start + 4;
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
placeholder: `graph TD
|
|
557
575
|
A[Start] --> B{Decision}
|
|
558
576
|
B -->|Yes| C[OK]
|
|
559
|
-
B -->|No| D[End]
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
577
|
+
B -->|No| D[End]`,
|
|
578
|
+
rows: 8,
|
|
579
|
+
className: "mermaid-block-textarea"
|
|
580
|
+
}
|
|
581
|
+
),
|
|
582
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mermaid-live-preview", children: [
|
|
583
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mermaid-live-preview-label", children: "Preview" }),
|
|
584
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MermaidPreview, { diagram: livePreview, isDark, interactive: false })
|
|
585
|
+
] }),
|
|
586
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mermaid-block-actions", children: [
|
|
587
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { onClick: () => {
|
|
569
588
|
setEditing(false);
|
|
570
589
|
setValue(block.props.diagram || "");
|
|
571
590
|
setLivePreview(block.props.diagram || "");
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
591
|
+
}, className: "mermaid-btn-cancel", children: "Cancel" }),
|
|
592
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { onClick: save, className: "mermaid-btn-save", disabled: !value.trim(), children: "Done" })
|
|
593
|
+
] })
|
|
594
|
+
] });
|
|
576
595
|
}
|
|
577
596
|
if (!block.props.diagram) {
|
|
578
|
-
return
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { onClick: () => setEditing(true), className: "mermaid-block mermaid-block--empty", children: [
|
|
598
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
599
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1.5" }),
|
|
600
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1.5" }),
|
|
601
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "8.5", y: "14", width: "7", height: "7", rx: "1.5" }),
|
|
602
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "6.5", y1: "10", x2: "6.5", y2: "14" }),
|
|
603
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "17.5", y1: "10", x2: "17.5", y2: "14" }),
|
|
604
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "6.5", y1: "14", x2: "8.5", y2: "14" }),
|
|
605
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "17.5", y1: "14", x2: "15.5", y2: "14" })
|
|
606
|
+
] }),
|
|
607
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Click to add a Mermaid diagram" })
|
|
608
|
+
] });
|
|
590
609
|
}
|
|
591
|
-
return
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
610
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mermaid-block mermaid-block--rendered group", onDoubleClick: () => setEditing(true), children: [
|
|
611
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MermaidPreview, { diagram: block.props.diagram, isDark, interactive: true }),
|
|
612
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mermaid-block-hover", children: [
|
|
613
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { onClick: () => setEditing(true), className: "mermaid-hover-btn", title: "Edit diagram", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
614
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" }),
|
|
615
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" })
|
|
616
|
+
] }) }),
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { onClick: handleDelete, className: "mermaid-hover-btn mermaid-hover-delete", title: "Delete", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polyline", { points: "3 6 5 6 21 6" }),
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" })
|
|
620
|
+
] }) })
|
|
621
|
+
] })
|
|
622
|
+
] });
|
|
604
623
|
}
|
|
605
624
|
}
|
|
606
625
|
);
|
|
607
626
|
|
|
608
627
|
// src/blocks/TableOfContents.jsx
|
|
609
628
|
var import_react6 = require("@blocknote/react");
|
|
610
|
-
|
|
629
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
611
630
|
var TableOfContents = (0, import_react6.createReactBlockSpec)(
|
|
612
631
|
{
|
|
613
632
|
type: "tableOfContents",
|
|
@@ -619,19 +638,23 @@ var TableOfContents = (0, import_react6.createReactBlockSpec)(
|
|
|
619
638
|
const headings = editor.document.filter(
|
|
620
639
|
(b) => b.type === "heading" && b.content?.length > 0
|
|
621
640
|
);
|
|
622
|
-
return
|
|
623
|
-
|
|
624
|
-
|
|
641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "toc-block border border-[var(--border-default)] rounded-xl bg-[var(--bg-surface)] px-5 py-4 my-2 select-none", children: [
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-[11px] uppercase tracking-wider text-[var(--text-muted)] font-bold mb-3", children: "Table of Contents" }),
|
|
643
|
+
headings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-[13px] text-[var(--text-faint)] italic", children: "Add headings to see the outline here." }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "space-y-1.5", children: headings.map((h) => {
|
|
625
644
|
const level = h.props?.level || 1;
|
|
626
645
|
const text = h.content.map((c) => c.text || "").join("");
|
|
627
|
-
return
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
646
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
647
|
+
"li",
|
|
648
|
+
{
|
|
649
|
+
className: "text-[13px] text-[#9b7bf7] hover:text-[#b69aff] cursor-pointer transition-colors",
|
|
650
|
+
style: { paddingLeft: `${(level - 1) * 16}px` },
|
|
651
|
+
onClick: () => editor.setTextCursorPosition(h.id),
|
|
652
|
+
children: text
|
|
653
|
+
},
|
|
654
|
+
h.id
|
|
655
|
+
);
|
|
656
|
+
}) })
|
|
657
|
+
] });
|
|
635
658
|
}
|
|
636
659
|
}
|
|
637
660
|
);
|
|
@@ -640,17 +663,13 @@ var TableOfContents = (0, import_react6.createReactBlockSpec)(
|
|
|
640
663
|
var import_react7 = require("@blocknote/react");
|
|
641
664
|
var import_react8 = require("react");
|
|
642
665
|
var import_katex2 = __toESM(require("katex"));
|
|
643
|
-
|
|
666
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
644
667
|
function stripDelimiters2(raw) {
|
|
645
668
|
let s = raw.trim();
|
|
646
|
-
if (s.startsWith("\\(") && s.endsWith("\\)"))
|
|
647
|
-
|
|
648
|
-
if (s.startsWith("
|
|
649
|
-
|
|
650
|
-
if (s.startsWith("$$") && s.endsWith("$$"))
|
|
651
|
-
return s.slice(2, -2).trim();
|
|
652
|
-
if (s.startsWith("$") && s.endsWith("$") && s.length > 2)
|
|
653
|
-
return s.slice(1, -1).trim();
|
|
669
|
+
if (s.startsWith("\\(") && s.endsWith("\\)")) return s.slice(2, -2).trim();
|
|
670
|
+
if (s.startsWith("\\[") && s.endsWith("\\]")) return s.slice(2, -2).trim();
|
|
671
|
+
if (s.startsWith("$$") && s.endsWith("$$")) return s.slice(2, -2).trim();
|
|
672
|
+
if (s.startsWith("$") && s.endsWith("$") && s.length > 2) return s.slice(1, -1).trim();
|
|
654
673
|
return s;
|
|
655
674
|
}
|
|
656
675
|
function renderKaTeXInline(latex) {
|
|
@@ -666,12 +685,10 @@ function InlineEquationChip({ inlineContent }) {
|
|
|
666
685
|
const inputRef = (0, import_react8.useRef)(null);
|
|
667
686
|
const popupRef = (0, import_react8.useRef)(null);
|
|
668
687
|
(0, import_react8.useEffect)(() => {
|
|
669
|
-
if (editing && inputRef.current)
|
|
670
|
-
inputRef.current.focus();
|
|
688
|
+
if (editing && inputRef.current) inputRef.current.focus();
|
|
671
689
|
}, [editing]);
|
|
672
690
|
(0, import_react8.useEffect)(() => {
|
|
673
|
-
if (!editing)
|
|
674
|
-
return;
|
|
691
|
+
if (!editing) return;
|
|
675
692
|
function handleClick(e) {
|
|
676
693
|
if (popupRef.current && !popupRef.current.contains(e.target)) {
|
|
677
694
|
setEditing(false);
|
|
@@ -688,47 +705,57 @@ function InlineEquationChip({ inlineContent }) {
|
|
|
688
705
|
}, [value, inlineContent]);
|
|
689
706
|
const html = renderKaTeXInline(inlineContent.props.latex);
|
|
690
707
|
const previewHtml = value.trim() ? renderKaTeXInline(value) : "";
|
|
691
|
-
return
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
e
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
ref
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
708
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "relative inline-flex items-center", children: [
|
|
709
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
710
|
+
"span",
|
|
711
|
+
{
|
|
712
|
+
onClick: (e) => {
|
|
713
|
+
e.preventDefault();
|
|
714
|
+
e.stopPropagation();
|
|
715
|
+
setValue(inlineContent.props.latex || "");
|
|
716
|
+
setEditing(!editing);
|
|
717
|
+
},
|
|
718
|
+
className: "inline-equation-chip",
|
|
719
|
+
dangerouslySetInnerHTML: { __html: html },
|
|
720
|
+
title: inlineContent.props.latex
|
|
721
|
+
}
|
|
722
|
+
),
|
|
723
|
+
editing && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
724
|
+
"div",
|
|
725
|
+
{
|
|
726
|
+
ref: popupRef,
|
|
727
|
+
className: "inline-equation-editor",
|
|
728
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
729
|
+
children: [
|
|
730
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
731
|
+
"input",
|
|
732
|
+
{
|
|
733
|
+
ref: inputRef,
|
|
734
|
+
type: "text",
|
|
735
|
+
className: "inline-equation-editor-input",
|
|
736
|
+
value,
|
|
737
|
+
onChange: (e) => setValue(e.target.value),
|
|
738
|
+
onKeyDown: (e) => {
|
|
739
|
+
if (e.key === "Enter") {
|
|
740
|
+
e.preventDefault();
|
|
741
|
+
save();
|
|
742
|
+
}
|
|
743
|
+
if (e.key === "Escape") {
|
|
744
|
+
setEditing(false);
|
|
745
|
+
}
|
|
746
|
+
},
|
|
747
|
+
placeholder: "E = mc^2"
|
|
748
|
+
}
|
|
749
|
+
),
|
|
750
|
+
previewHtml && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "inline-equation-editor-preview", dangerouslySetInnerHTML: { __html: previewHtml } }),
|
|
751
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "inline-equation-editor-actions", children: [
|
|
752
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "mermaid-btn-cancel", onClick: () => setEditing(false), children: "Cancel" }),
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: "mermaid-btn-save", disabled: !value.trim(), onClick: save, children: "Save" })
|
|
754
|
+
] })
|
|
755
|
+
]
|
|
756
|
+
}
|
|
757
|
+
)
|
|
758
|
+
] });
|
|
732
759
|
}
|
|
733
760
|
var InlineEquation = (0, import_react7.createReactInlineContentSpec)(
|
|
734
761
|
{
|
|
@@ -739,32 +766,30 @@ var InlineEquation = (0, import_react7.createReactInlineContentSpec)(
|
|
|
739
766
|
content: "none"
|
|
740
767
|
},
|
|
741
768
|
{
|
|
742
|
-
render: (props) =>
|
|
769
|
+
render: (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InlineEquationChip, { ...props })
|
|
743
770
|
}
|
|
744
771
|
);
|
|
745
772
|
|
|
746
773
|
// src/blocks/DateInline.jsx
|
|
747
774
|
var import_react9 = require("@blocknote/react");
|
|
748
775
|
var import_react10 = require("react");
|
|
749
|
-
|
|
776
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
750
777
|
function MiniCalendar({ selectedDate, onSelect, onClose, anchorEl }) {
|
|
751
778
|
const ref = (0, import_react10.useRef)(null);
|
|
752
779
|
const [viewDate, setViewDate] = (0, import_react10.useState)(() => {
|
|
753
|
-
const d = selectedDate ? new Date(selectedDate) : new Date();
|
|
780
|
+
const d = selectedDate ? new Date(selectedDate) : /* @__PURE__ */ new Date();
|
|
754
781
|
return { year: d.getFullYear(), month: d.getMonth() };
|
|
755
782
|
});
|
|
756
783
|
const [pos, setPos] = (0, import_react10.useState)(null);
|
|
757
784
|
(0, import_react10.useEffect)(() => {
|
|
758
785
|
function handleClick(e) {
|
|
759
|
-
if (ref.current && !ref.current.contains(e.target))
|
|
760
|
-
onClose();
|
|
786
|
+
if (ref.current && !ref.current.contains(e.target)) onClose();
|
|
761
787
|
}
|
|
762
788
|
document.addEventListener("mousedown", handleClick);
|
|
763
789
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
764
790
|
}, [onClose]);
|
|
765
791
|
(0, import_react10.useEffect)(() => {
|
|
766
|
-
if (!anchorEl)
|
|
767
|
-
return;
|
|
792
|
+
if (!anchorEl) return;
|
|
768
793
|
const rect = anchorEl.getBoundingClientRect();
|
|
769
794
|
const calWidth = 240;
|
|
770
795
|
let left = rect.left;
|
|
@@ -774,78 +799,88 @@ function MiniCalendar({ selectedDate, onSelect, onClose, anchorEl }) {
|
|
|
774
799
|
const { year, month } = viewDate;
|
|
775
800
|
const firstDay = new Date(year, month, 1).getDay();
|
|
776
801
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
777
|
-
const today = new Date();
|
|
802
|
+
const today = /* @__PURE__ */ new Date();
|
|
778
803
|
const todayStr = today.toISOString().split("T")[0];
|
|
779
804
|
const monthName = new Date(year, month).toLocaleDateString("en-US", { month: "long", year: "numeric" });
|
|
780
805
|
const days = [];
|
|
781
|
-
for (let i = 0; i < firstDay; i++)
|
|
782
|
-
|
|
783
|
-
for (let d = 1; d <= daysInMonth; d++)
|
|
784
|
-
days.push(d);
|
|
806
|
+
for (let i = 0; i < firstDay; i++) days.push(null);
|
|
807
|
+
for (let d = 1; d <= daysInMonth; d++) days.push(d);
|
|
785
808
|
const prev = () => setViewDate((v) => v.month === 0 ? { year: v.year - 1, month: 11 } : { ...v, month: v.month - 1 });
|
|
786
809
|
const next = () => setViewDate((v) => v.month === 11 ? { year: v.year + 1, month: 0 } : { ...v, month: v.month + 1 });
|
|
787
810
|
const toDateStr = (d) => `${year}-${String(month + 1).padStart(2, "0")}-${String(d).padStart(2, "0")}`;
|
|
788
|
-
if (!pos)
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
811
|
+
if (!pos) return null;
|
|
812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
813
|
+
"div",
|
|
814
|
+
{
|
|
815
|
+
ref,
|
|
816
|
+
className: "fixed z-[100] rounded-xl shadow-2xl overflow-hidden",
|
|
817
|
+
style: { backgroundColor: "var(--bg-app)", border: "1px solid var(--border-default)", width: "240px", top: pos.top, left: pos.left },
|
|
818
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
819
|
+
children: [
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between px-3 py-2", style: { borderBottom: "1px solid var(--divider)" }, children: [
|
|
821
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: prev, className: "w-6 h-6 flex items-center justify-center rounded hover:bg-[var(--bg-hover)] transition-colors", style: { color: "var(--text-muted)" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "15 18 9 12 15 6" }) }) }),
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[12px] font-semibold", style: { color: "var(--text-primary)" }, children: monthName }),
|
|
823
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: next, className: "w-6 h-6 flex items-center justify-center rounded hover:bg-[var(--bg-hover)] transition-colors", style: { color: "var(--text-muted)" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "9 18 15 12 9 6" }) }) })
|
|
824
|
+
] }),
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "grid grid-cols-7 px-2 pt-2", children: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((d) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-center text-[10px] font-medium py-1", style: { color: "var(--text-faint)" }, children: d }, d)) }),
|
|
826
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "grid grid-cols-7 px-2 pb-2 gap-0.5", children: days.map((d, i) => {
|
|
827
|
+
if (!d) return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", {}, `e${i}`);
|
|
828
|
+
const dateStr = toDateStr(d);
|
|
829
|
+
const isSelected = dateStr === selectedDate;
|
|
830
|
+
const isToday = dateStr === todayStr;
|
|
831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
832
|
+
"button",
|
|
833
|
+
{
|
|
834
|
+
onClick: () => {
|
|
835
|
+
onSelect(dateStr);
|
|
836
|
+
onClose();
|
|
837
|
+
},
|
|
838
|
+
className: "w-7 h-7 rounded-lg text-[11px] font-medium flex items-center justify-center transition-all",
|
|
839
|
+
style: {
|
|
840
|
+
backgroundColor: isSelected ? "#9b7bf7" : "transparent",
|
|
841
|
+
color: isSelected ? "white" : isToday ? "#9b7bf7" : "var(--text-body)",
|
|
842
|
+
border: isToday && !isSelected ? "1px solid #9b7bf7" : "1px solid transparent"
|
|
843
|
+
},
|
|
844
|
+
onMouseEnter: (e) => {
|
|
845
|
+
if (!isSelected) e.currentTarget.style.backgroundColor = "var(--bg-hover)";
|
|
846
|
+
},
|
|
847
|
+
onMouseLeave: (e) => {
|
|
848
|
+
if (!isSelected) e.currentTarget.style.backgroundColor = "transparent";
|
|
849
|
+
},
|
|
850
|
+
children: d
|
|
851
|
+
},
|
|
852
|
+
d
|
|
853
|
+
);
|
|
854
|
+
}) }),
|
|
855
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between px-3 py-1.5", style: { borderTop: "1px solid var(--divider)" }, children: [
|
|
856
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
857
|
+
"button",
|
|
858
|
+
{
|
|
859
|
+
onClick: () => {
|
|
860
|
+
onSelect("");
|
|
861
|
+
onClose();
|
|
862
|
+
},
|
|
863
|
+
className: "text-[10px] font-medium transition-colors",
|
|
864
|
+
style: { color: "var(--text-faint)" },
|
|
865
|
+
children: "Clear"
|
|
866
|
+
}
|
|
867
|
+
),
|
|
868
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
869
|
+
"button",
|
|
870
|
+
{
|
|
871
|
+
onClick: () => {
|
|
872
|
+
onSelect(todayStr);
|
|
873
|
+
onClose();
|
|
874
|
+
},
|
|
875
|
+
className: "text-[10px] font-medium transition-colors",
|
|
876
|
+
style: { color: "#9b7bf7" },
|
|
877
|
+
children: "Today"
|
|
878
|
+
}
|
|
879
|
+
)
|
|
880
|
+
] })
|
|
881
|
+
]
|
|
882
|
+
}
|
|
883
|
+
);
|
|
849
884
|
}
|
|
850
885
|
function DateChip({ inlineContent }) {
|
|
851
886
|
const [showPicker, setShowPicker] = (0, import_react10.useState)(false);
|
|
@@ -863,51 +898,58 @@ function DateChip({ inlineContent }) {
|
|
|
863
898
|
}
|
|
864
899
|
setShowPicker(false);
|
|
865
900
|
}, [inlineContent]);
|
|
866
|
-
return
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
e
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "relative inline-flex items-center", children: [
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
903
|
+
"span",
|
|
904
|
+
{
|
|
905
|
+
ref: chipRef,
|
|
906
|
+
onClick: (e) => {
|
|
907
|
+
e.preventDefault();
|
|
908
|
+
e.stopPropagation();
|
|
909
|
+
setShowPicker(!showPicker);
|
|
910
|
+
},
|
|
911
|
+
className: "inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-[13px] font-medium mx-0.5 cursor-pointer transition-all hover:ring-2 hover:ring-[#9b7bf7]/30",
|
|
912
|
+
style: { color: "#9b7bf7", backgroundColor: "rgba(155,123,247,0.06)", border: "1px solid rgba(155,123,247,0.15)" },
|
|
913
|
+
title: "Click to change date (Ctrl+D to insert)",
|
|
914
|
+
children: [
|
|
915
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
|
|
916
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2", strokeWidth: 2 }),
|
|
917
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "16", y1: "2", x2: "16", y2: "6", strokeWidth: 2 }),
|
|
918
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "8", y1: "2", x2: "8", y2: "6", strokeWidth: 2 }),
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "3", y1: "10", x2: "21", y2: "10", strokeWidth: 2 })
|
|
920
|
+
] }),
|
|
921
|
+
formatted
|
|
922
|
+
]
|
|
923
|
+
}
|
|
924
|
+
),
|
|
925
|
+
showPicker && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
926
|
+
MiniCalendar,
|
|
927
|
+
{
|
|
928
|
+
selectedDate: d,
|
|
929
|
+
onSelect: handleSelect,
|
|
930
|
+
onClose: () => setShowPicker(false),
|
|
931
|
+
anchorEl: chipRef.current
|
|
932
|
+
}
|
|
933
|
+
)
|
|
934
|
+
] });
|
|
893
935
|
}
|
|
894
936
|
var DateInline = (0, import_react9.createReactInlineContentSpec)(
|
|
895
937
|
{
|
|
896
938
|
type: "dateInline",
|
|
897
939
|
propSchema: {
|
|
898
|
-
date: { default: new Date().toISOString().split("T")[0] }
|
|
940
|
+
date: { default: (/* @__PURE__ */ new Date()).toISOString().split("T")[0] }
|
|
899
941
|
},
|
|
900
942
|
content: "none"
|
|
901
943
|
},
|
|
902
944
|
{
|
|
903
|
-
render: (props) =>
|
|
945
|
+
render: (props) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DateChip, { ...props })
|
|
904
946
|
}
|
|
905
947
|
);
|
|
906
948
|
|
|
907
949
|
// src/blocks/ImageBlock.jsx
|
|
908
950
|
var import_react11 = require("@blocknote/react");
|
|
909
951
|
var import_react12 = require("react");
|
|
910
|
-
|
|
952
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
911
953
|
var BlogImageBlock = (0, import_react11.createReactBlockSpec)(
|
|
912
954
|
{
|
|
913
955
|
type: "image",
|
|
@@ -921,7 +963,7 @@ var BlogImageBlock = (0, import_react11.createReactBlockSpec)(
|
|
|
921
963
|
content: "none"
|
|
922
964
|
},
|
|
923
965
|
{
|
|
924
|
-
render: (props) =>
|
|
966
|
+
render: (props) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ImageRenderer, { ...props })
|
|
925
967
|
}
|
|
926
968
|
);
|
|
927
969
|
function ImageRenderer({ block, editor }) {
|
|
@@ -937,13 +979,11 @@ function ImageRenderer({ block, editor }) {
|
|
|
937
979
|
const blockRef = (0, import_react12.useRef)(null);
|
|
938
980
|
const embedInputRef = (0, import_react12.useRef)(null);
|
|
939
981
|
(0, import_react12.useEffect)(() => {
|
|
940
|
-
if (mode === "embed")
|
|
941
|
-
setTimeout(() => embedInputRef.current?.focus(), 50);
|
|
982
|
+
if (mode === "embed") setTimeout(() => embedInputRef.current?.focus(), 50);
|
|
942
983
|
}, [mode]);
|
|
943
984
|
(0, import_react12.useEffect)(() => {
|
|
944
985
|
const el = blockRef.current;
|
|
945
|
-
if (!el)
|
|
946
|
-
return;
|
|
986
|
+
if (!el) return;
|
|
947
987
|
function handleKey(e) {
|
|
948
988
|
if ((e.key === "Backspace" || e.key === "Delete") && mode === "idle" && !url) {
|
|
949
989
|
e.preventDefault();
|
|
@@ -957,8 +997,7 @@ function ImageRenderer({ block, editor }) {
|
|
|
957
997
|
return () => el.removeEventListener("keydown", handleKey);
|
|
958
998
|
}, [editor, block.id, mode, url]);
|
|
959
999
|
const uploadFile = (0, import_react12.useCallback)(async (file) => {
|
|
960
|
-
if (!file || !file.type.startsWith("image/"))
|
|
961
|
-
return;
|
|
1000
|
+
if (!file || !file.type.startsWith("image/")) return;
|
|
962
1001
|
setMode("uploading");
|
|
963
1002
|
setUploadStatus("Processing...");
|
|
964
1003
|
try {
|
|
@@ -978,8 +1017,7 @@ function ImageRenderer({ block, editor }) {
|
|
|
978
1017
|
}, [editor, block.id]);
|
|
979
1018
|
const handlePaste = (0, import_react12.useCallback)((e) => {
|
|
980
1019
|
const items = e.clipboardData?.items;
|
|
981
|
-
if (!items)
|
|
982
|
-
return;
|
|
1020
|
+
if (!items) return;
|
|
983
1021
|
for (const item of items) {
|
|
984
1022
|
if (item.type.startsWith("image/")) {
|
|
985
1023
|
e.preventDefault();
|
|
@@ -992,13 +1030,11 @@ function ImageRenderer({ block, editor }) {
|
|
|
992
1030
|
e.preventDefault();
|
|
993
1031
|
setIsDragOver(false);
|
|
994
1032
|
const file = e.dataTransfer?.files?.[0];
|
|
995
|
-
if (file?.type.startsWith("image/"))
|
|
996
|
-
uploadFile(file);
|
|
1033
|
+
if (file?.type.startsWith("image/")) uploadFile(file);
|
|
997
1034
|
}, [uploadFile]);
|
|
998
1035
|
const handleEmbed = (0, import_react12.useCallback)(() => {
|
|
999
1036
|
const trimmed = embedUrl.trim();
|
|
1000
|
-
if (!trimmed)
|
|
1001
|
-
return;
|
|
1037
|
+
if (!trimmed) return;
|
|
1002
1038
|
if (!trimmed.startsWith("http")) {
|
|
1003
1039
|
setEmbedError("URL must start with http:// or https://");
|
|
1004
1040
|
return;
|
|
@@ -1035,137 +1071,151 @@ function ImageRenderer({ block, editor }) {
|
|
|
1035
1071
|
setEditingCaption(false);
|
|
1036
1072
|
}, [editor, block.id, captionText]);
|
|
1037
1073
|
if (!url) {
|
|
1038
|
-
return
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1074
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1075
|
+
"div",
|
|
1076
|
+
{
|
|
1077
|
+
ref: blockRef,
|
|
1078
|
+
className: "blog-img-empty",
|
|
1079
|
+
tabIndex: 0,
|
|
1080
|
+
onPaste: handlePaste,
|
|
1081
|
+
onDrop: handleDrop,
|
|
1082
|
+
onDragOver: (e) => {
|
|
1083
|
+
e.preventDefault();
|
|
1084
|
+
setIsDragOver(true);
|
|
1085
|
+
},
|
|
1086
|
+
onDragLeave: () => setIsDragOver(false),
|
|
1087
|
+
"data-drag-over": isDragOver,
|
|
1088
|
+
children: [
|
|
1089
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1090
|
+
"input",
|
|
1091
|
+
{
|
|
1092
|
+
ref: fileInputRef,
|
|
1093
|
+
type: "file",
|
|
1094
|
+
accept: "image/*",
|
|
1095
|
+
onChange: (e) => {
|
|
1096
|
+
if (e.target.files?.[0]) uploadFile(e.target.files[0]);
|
|
1097
|
+
e.target.value = "";
|
|
1098
|
+
},
|
|
1099
|
+
style: { display: "none" }
|
|
1100
|
+
}
|
|
1101
|
+
),
|
|
1102
|
+
mode === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "blog-img-status", children: [
|
|
1103
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "blog-img-spinner" }),
|
|
1104
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: uploadStatus })
|
|
1105
|
+
] }),
|
|
1106
|
+
mode === "idle" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1107
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "blog-img-actions-row", children: [
|
|
1108
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { className: "blog-img-action", onClick: () => fileInputRef.current?.click(), children: [
|
|
1109
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1110
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
|
|
1111
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "17 8 12 3 7 8" }),
|
|
1112
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
|
|
1113
|
+
] }),
|
|
1114
|
+
"Upload"
|
|
1115
|
+
] }),
|
|
1116
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("button", { className: "blog-img-action", onClick: () => setMode("embed"), children: [
|
|
1117
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1118
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" }),
|
|
1119
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" })
|
|
1120
|
+
] }),
|
|
1121
|
+
"Embed URL"
|
|
1122
|
+
] })
|
|
1123
|
+
] }),
|
|
1124
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "blog-img-hint", children: "or drag & drop / paste an image" })
|
|
1125
|
+
] }),
|
|
1126
|
+
mode === "embed" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "blog-img-input-row", children: [
|
|
1127
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1128
|
+
"input",
|
|
1129
|
+
{
|
|
1130
|
+
ref: embedInputRef,
|
|
1131
|
+
type: "url",
|
|
1132
|
+
value: embedUrl,
|
|
1133
|
+
onChange: (e) => {
|
|
1134
|
+
setEmbedUrl(e.target.value);
|
|
1135
|
+
setEmbedError("");
|
|
1136
|
+
},
|
|
1137
|
+
onKeyDown: (e) => {
|
|
1138
|
+
if (e.key === "Enter") handleEmbed();
|
|
1139
|
+
if (e.key === "Escape") {
|
|
1140
|
+
setMode("idle");
|
|
1141
|
+
setEmbedUrl("");
|
|
1142
|
+
setEmbedError("");
|
|
1143
|
+
}
|
|
1144
|
+
},
|
|
1145
|
+
placeholder: "https://example.com/image.jpg",
|
|
1146
|
+
className: "blog-img-url-input"
|
|
1147
|
+
}
|
|
1148
|
+
),
|
|
1149
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "blog-img-submit-btn", onClick: handleEmbed, disabled: !embedUrl.trim(), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "20 6 9 17 4 12" }) }) }),
|
|
1150
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "blog-img-cancel-btn", onClick: () => {
|
|
1099
1151
|
setMode("idle");
|
|
1100
1152
|
setEmbedUrl("");
|
|
1101
1153
|
setEmbedError("");
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
setEmbedError("");
|
|
1112
|
-
}}><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
|
1113
|
-
<line x1="18" y1="6" x2="6" y2="18" />
|
|
1114
|
-
<line x1="6" y1="6" x2="18" y2="18" />
|
|
1115
|
-
</svg></button>
|
|
1116
|
-
{embedError && <span className="blog-img-error">{embedError}</span>}
|
|
1117
|
-
</div>}
|
|
1118
|
-
</div>;
|
|
1154
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1155
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1156
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1157
|
+
] }) }),
|
|
1158
|
+
embedError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "blog-img-error", children: embedError })
|
|
1159
|
+
] })
|
|
1160
|
+
]
|
|
1161
|
+
}
|
|
1162
|
+
);
|
|
1119
1163
|
}
|
|
1120
|
-
return
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: blockRef, className: "blog-img-loaded", tabIndex: 0, onPaste: handlePaste, children: [
|
|
1165
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "blog-img-wrapper", children: [
|
|
1166
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: url, alt: caption || "Image", className: "blog-img-main", draggable: false }),
|
|
1167
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "blog-img-hover-overlay", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "blog-img-hover-actions", children: [
|
|
1168
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "blog-img-hover-btn", onClick: handleReplace, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1169
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
|
|
1170
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "17 8 12 3 7 8" }),
|
|
1171
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
|
|
1172
|
+
] }) }),
|
|
1173
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "blog-img-hover-btn", onClick: () => setEditingCaption(true), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1174
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" }),
|
|
1175
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" })
|
|
1176
|
+
] }) }),
|
|
1177
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "blog-img-hover-btn blog-img-hover-delete", onClick: handleDelete, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1178
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("polyline", { points: "3 6 5 6 21 6" }),
|
|
1179
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" })
|
|
1180
|
+
] }) })
|
|
1181
|
+
] }) })
|
|
1182
|
+
] }),
|
|
1183
|
+
editingCaption ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1184
|
+
"input",
|
|
1185
|
+
{
|
|
1186
|
+
type: "text",
|
|
1187
|
+
value: captionText,
|
|
1188
|
+
onChange: (e) => setCaptionText(e.target.value),
|
|
1189
|
+
onKeyDown: (e) => {
|
|
1190
|
+
if (e.key === "Enter") handleCaptionSave();
|
|
1191
|
+
if (e.key === "Escape") {
|
|
1192
|
+
setEditingCaption(false);
|
|
1193
|
+
setCaptionText(caption || "");
|
|
1194
|
+
}
|
|
1195
|
+
},
|
|
1196
|
+
onBlur: handleCaptionSave,
|
|
1197
|
+
placeholder: "Add a caption...",
|
|
1198
|
+
className: "blog-img-caption-input",
|
|
1199
|
+
autoFocus: true
|
|
1200
|
+
}
|
|
1201
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1202
|
+
"p",
|
|
1203
|
+
{
|
|
1204
|
+
className: `blog-img-caption ${caption ? "" : "blog-img-caption--empty"}`,
|
|
1205
|
+
onClick: () => {
|
|
1148
1206
|
setCaptionText(caption || "");
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
/> : <p
|
|
1156
|
-
className={`blog-img-caption ${caption ? "" : "blog-img-caption--empty"}`}
|
|
1157
|
-
onClick={() => {
|
|
1158
|
-
setCaptionText(caption || "");
|
|
1159
|
-
setEditingCaption(true);
|
|
1160
|
-
}}
|
|
1161
|
-
>{caption || "Add a caption..."}</p>}
|
|
1162
|
-
</div>;
|
|
1207
|
+
setEditingCaption(true);
|
|
1208
|
+
},
|
|
1209
|
+
children: caption || "Add a caption..."
|
|
1210
|
+
}
|
|
1211
|
+
)
|
|
1212
|
+
] });
|
|
1163
1213
|
}
|
|
1164
1214
|
|
|
1165
1215
|
// src/blocks/ButtonBlock.jsx
|
|
1166
1216
|
var import_react13 = require("@blocknote/react");
|
|
1167
1217
|
var import_react14 = require("react");
|
|
1168
|
-
|
|
1218
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1169
1219
|
var BUTTON_ACTIONS = [
|
|
1170
1220
|
{ value: "link", label: "Open Link" },
|
|
1171
1221
|
{ value: "copy", label: "Copy Text" },
|
|
@@ -1200,34 +1250,40 @@ var ButtonBlock = (0, import_react13.createReactBlockSpec)(
|
|
|
1200
1250
|
setEditing(false);
|
|
1201
1251
|
};
|
|
1202
1252
|
if (editing) {
|
|
1203
|
-
return
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1253
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "border border-[var(--border-default)] rounded-xl bg-[var(--bg-surface)] p-4 my-2 space-y-3", children: [
|
|
1254
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-[var(--text-muted)] font-medium", children: "Button Block" }),
|
|
1255
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1256
|
+
"input",
|
|
1257
|
+
{
|
|
1258
|
+
type: "text",
|
|
1259
|
+
value: label,
|
|
1260
|
+
onChange: (e) => setLabel(e.target.value),
|
|
1261
|
+
placeholder: "Button label",
|
|
1262
|
+
className: "w-full bg-[var(--bg-app)] border border-[var(--border-default)] rounded-lg px-3 py-2 text-[13px] text-[var(--text-primary)] outline-none focus:border-[var(--border-hover)] placeholder-[#6b7a8d]"
|
|
1263
|
+
}
|
|
1264
|
+
),
|
|
1265
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex gap-2", children: [
|
|
1266
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("select", { value: action, onChange: (e) => setAction(e.target.value), className: "bg-[var(--bg-app)] border border-[var(--border-default)] rounded-lg px-3 py-2 text-[13px] text-[var(--text-primary)] outline-none flex-1", children: BUTTON_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: a.value, children: a.label }, a.value)) }),
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("select", { value: variant, onChange: (e) => setVariant(e.target.value), className: "bg-[var(--bg-app)] border border-[var(--border-default)] rounded-lg px-3 py-2 text-[13px] text-[var(--text-primary)] outline-none", children: BUTTON_VARIANTS.map((v) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: v.value, children: v.label }, v.value)) })
|
|
1268
|
+
] }),
|
|
1269
|
+
(action === "link" || action === "copy") && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1270
|
+
"input",
|
|
1271
|
+
{
|
|
1272
|
+
type: "text",
|
|
1273
|
+
value: actionValue,
|
|
1274
|
+
onChange: (e) => setActionValue(e.target.value),
|
|
1275
|
+
placeholder: action === "link" ? "https://..." : "Text to copy",
|
|
1276
|
+
className: "w-full bg-[var(--bg-app)] border border-[var(--border-default)] rounded-lg px-3 py-2 text-[13px] text-[var(--text-primary)] outline-none focus:border-[var(--border-hover)] placeholder-[#6b7a8d]"
|
|
1277
|
+
}
|
|
1278
|
+
),
|
|
1279
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex justify-end gap-2", children: [
|
|
1280
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { onClick: () => setEditing(false), className: "px-3 py-1 text-[12px] text-[#888] hover:text-[var(--text-primary)] transition-colors", children: "Cancel" }),
|
|
1281
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { onClick: save, className: "px-3 py-1 text-[12px] bg-[#9b7bf7] text-[var(--text-primary)] rounded-md font-medium hover:bg-[#b69aff] transition-colors", children: "Done" })
|
|
1282
|
+
] })
|
|
1283
|
+
] });
|
|
1228
1284
|
}
|
|
1229
1285
|
const variantCls = BUTTON_VARIANTS.find((v) => v.value === variant)?.cls || BUTTON_VARIANTS[0].cls;
|
|
1230
|
-
return
|
|
1286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "my-2", onDoubleClick: () => setEditing(true), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { className: `px-5 py-2 rounded-lg text-[13px] font-medium transition-colors ${variantCls}`, children: label }) });
|
|
1231
1287
|
}
|
|
1232
1288
|
}
|
|
1233
1289
|
);
|
|
@@ -1235,7 +1291,7 @@ var ButtonBlock = (0, import_react13.createReactBlockSpec)(
|
|
|
1235
1291
|
// src/blocks/PDFEmbedBlock.jsx
|
|
1236
1292
|
var import_react15 = require("@blocknote/react");
|
|
1237
1293
|
var import_react16 = require("react");
|
|
1238
|
-
|
|
1294
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1239
1295
|
var PDFEmbedBlock = (0, import_react15.createReactBlockSpec)(
|
|
1240
1296
|
{
|
|
1241
1297
|
type: "pdfEmbed",
|
|
@@ -1254,8 +1310,7 @@ var PDFEmbedBlock = (0, import_react15.createReactBlockSpec)(
|
|
|
1254
1310
|
const [loading, setLoading] = (0, import_react16.useState)(false);
|
|
1255
1311
|
const handleSubmit = () => {
|
|
1256
1312
|
const trimmed = inputUrl.trim();
|
|
1257
|
-
if (!trimmed)
|
|
1258
|
-
return;
|
|
1313
|
+
if (!trimmed) return;
|
|
1259
1314
|
setLoading(true);
|
|
1260
1315
|
const fileName = decodeURIComponent(trimmed.split("/").pop()?.split("?")[0] || "document.pdf");
|
|
1261
1316
|
editor.updateBlock(block, {
|
|
@@ -1277,90 +1332,100 @@ var PDFEmbedBlock = (0, import_react15.createReactBlockSpec)(
|
|
|
1277
1332
|
editor.removeBlocks([block]);
|
|
1278
1333
|
};
|
|
1279
1334
|
if (!url) {
|
|
1280
|
-
return
|
|
1335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: {
|
|
1281
1336
|
background: "rgba(155, 123, 247, 0.04)",
|
|
1282
1337
|
border: "1.5px dashed rgba(155, 123, 247, 0.25)",
|
|
1283
1338
|
borderRadius: "12px",
|
|
1284
1339
|
padding: "24px"
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1340
|
+
}, children: [
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "12px" }, children: [
|
|
1342
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "#9b7bf7", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1343
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" }),
|
|
1344
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "14 2 14 8 20 8" }),
|
|
1345
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
|
|
1346
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
|
|
1347
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "10 9 9 9 8 9" })
|
|
1348
|
+
] }),
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: "14px", fontWeight: 600, color: "var(--text-primary)" }, children: "Embed PDF" })
|
|
1350
|
+
] }),
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
1352
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1353
|
+
"input",
|
|
1354
|
+
{
|
|
1355
|
+
type: "text",
|
|
1356
|
+
value: inputUrl,
|
|
1357
|
+
onChange: (e) => setInputUrl(e.target.value),
|
|
1358
|
+
onKeyDown: (e) => e.key === "Enter" && handleSubmit(),
|
|
1359
|
+
placeholder: "Paste PDF link...",
|
|
1360
|
+
style: {
|
|
1361
|
+
flex: 1,
|
|
1362
|
+
background: "var(--bg-app)",
|
|
1363
|
+
color: "var(--text-primary)",
|
|
1364
|
+
border: "1px solid #232d3f",
|
|
1365
|
+
borderRadius: "8px",
|
|
1366
|
+
padding: "8px 12px",
|
|
1367
|
+
fontSize: "13px",
|
|
1368
|
+
outline: "none"
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
),
|
|
1372
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1373
|
+
"button",
|
|
1374
|
+
{
|
|
1375
|
+
onClick: handleSubmit,
|
|
1376
|
+
disabled: !inputUrl.trim() || loading,
|
|
1377
|
+
style: {
|
|
1378
|
+
padding: "8px 16px",
|
|
1379
|
+
background: "#9b7bf7",
|
|
1380
|
+
color: "white",
|
|
1381
|
+
border: "none",
|
|
1382
|
+
borderRadius: "8px",
|
|
1383
|
+
fontSize: "13px",
|
|
1384
|
+
fontWeight: 600,
|
|
1385
|
+
cursor: "pointer",
|
|
1386
|
+
opacity: !inputUrl.trim() || loading ? 0.4 : 1
|
|
1387
|
+
},
|
|
1388
|
+
children: loading ? "..." : "Embed"
|
|
1389
|
+
}
|
|
1390
|
+
)
|
|
1391
|
+
] })
|
|
1392
|
+
] });
|
|
1331
1393
|
}
|
|
1332
|
-
return
|
|
1394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: {
|
|
1333
1395
|
display: "flex",
|
|
1334
1396
|
borderRadius: "12px",
|
|
1335
1397
|
overflow: "hidden",
|
|
1336
1398
|
border: "1px solid #232d3f",
|
|
1337
1399
|
background: "var(--bg-surface)"
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1400
|
+
}, children: [
|
|
1401
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: {
|
|
1340
1402
|
width: "200px",
|
|
1341
1403
|
minHeight: "160px",
|
|
1342
1404
|
flexShrink: 0,
|
|
1343
1405
|
background: "#0d1117",
|
|
1344
1406
|
position: "relative",
|
|
1345
1407
|
overflow: "hidden"
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1408
|
+
}, children: [
|
|
1409
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1410
|
+
"iframe",
|
|
1411
|
+
{
|
|
1412
|
+
src: `${url}#toolbar=0&navpanes=0&scrollbar=0&view=FitH`,
|
|
1413
|
+
title: title || "PDF",
|
|
1414
|
+
style: {
|
|
1415
|
+
width: "100%",
|
|
1416
|
+
height: "100%",
|
|
1417
|
+
border: "none",
|
|
1418
|
+
pointerEvents: "none"
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
),
|
|
1422
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
1358
1423
|
position: "absolute",
|
|
1359
1424
|
inset: 0,
|
|
1360
1425
|
background: "linear-gradient(135deg, rgba(155,123,247,0.08) 0%, transparent 60%)",
|
|
1361
1426
|
pointerEvents: "none"
|
|
1362
|
-
}}
|
|
1363
|
-
|
|
1427
|
+
} }),
|
|
1428
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: {
|
|
1364
1429
|
position: "absolute",
|
|
1365
1430
|
bottom: "8px",
|
|
1366
1431
|
left: "8px",
|
|
@@ -1373,50 +1438,54 @@ var PDFEmbedBlock = (0, import_react15.createReactBlockSpec)(
|
|
|
1373
1438
|
color: "#c4b5fd",
|
|
1374
1439
|
letterSpacing: "0.5px",
|
|
1375
1440
|
textTransform: "uppercase"
|
|
1376
|
-
}}
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1441
|
+
}, children: "PDF" })
|
|
1442
|
+
] }),
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, padding: "16px", display: "flex", flexDirection: "column", justifyContent: "space-between" }, children: [
|
|
1444
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
1445
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "8px" }, children: [
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#9b7bf7", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" }),
|
|
1448
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "14 2 14 8 20 8" })
|
|
1449
|
+
] }),
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { fontSize: "14px", fontWeight: 600, color: "var(--text-primary)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: title || "Document" })
|
|
1451
|
+
] }),
|
|
1452
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: "12px", flexWrap: "wrap" }, children: [
|
|
1453
|
+
fileSize && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: { fontSize: "12px", color: "var(--text-muted)", display: "flex", alignItems: "center", gap: "4px" }, children: [
|
|
1454
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3" }) }),
|
|
1455
|
+
fileSize
|
|
1456
|
+
] }),
|
|
1457
|
+
pageCount && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: { fontSize: "12px", color: "var(--text-muted)", display: "flex", alignItems: "center", gap: "4px" }, children: [
|
|
1458
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1459
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M4 19.5A2.5 2.5 0 016.5 17H20" }),
|
|
1460
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z" })
|
|
1461
|
+
] }),
|
|
1462
|
+
pageCount,
|
|
1463
|
+
" pages"
|
|
1464
|
+
] })
|
|
1465
|
+
] })
|
|
1466
|
+
] }),
|
|
1467
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", gap: "8px", marginTop: "12px" }, children: [
|
|
1468
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1469
|
+
"a",
|
|
1470
|
+
{
|
|
1471
|
+
href: url,
|
|
1472
|
+
target: "_blank",
|
|
1473
|
+
rel: "noopener noreferrer",
|
|
1474
|
+
style: {
|
|
1475
|
+
padding: "6px 12px",
|
|
1476
|
+
background: "rgba(155,123,247,0.1)",
|
|
1477
|
+
border: "1px solid rgba(155,123,247,0.25)",
|
|
1478
|
+
borderRadius: "6px",
|
|
1479
|
+
fontSize: "12px",
|
|
1480
|
+
color: "#a78bfa",
|
|
1481
|
+
fontWeight: 500,
|
|
1482
|
+
textDecoration: "none",
|
|
1483
|
+
cursor: "pointer"
|
|
1484
|
+
},
|
|
1485
|
+
children: "Open PDF"
|
|
1486
|
+
}
|
|
1487
|
+
),
|
|
1488
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { onClick: handleReplace, style: {
|
|
1420
1489
|
padding: "6px 12px",
|
|
1421
1490
|
background: "rgba(255,255,255,0.04)",
|
|
1422
1491
|
border: "1px solid #232d3f",
|
|
@@ -1424,8 +1493,8 @@ var PDFEmbedBlock = (0, import_react15.createReactBlockSpec)(
|
|
|
1424
1493
|
fontSize: "12px",
|
|
1425
1494
|
color: "var(--text-muted)",
|
|
1426
1495
|
cursor: "pointer"
|
|
1427
|
-
}}
|
|
1428
|
-
|
|
1496
|
+
}, children: "Replace" }),
|
|
1497
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { onClick: handleDelete, style: {
|
|
1429
1498
|
padding: "6px 12px",
|
|
1430
1499
|
background: "rgba(248,113,113,0.06)",
|
|
1431
1500
|
border: "1px solid rgba(248,113,113,0.2)",
|
|
@@ -1433,29 +1502,27 @@ var PDFEmbedBlock = (0, import_react15.createReactBlockSpec)(
|
|
|
1433
1502
|
fontSize: "12px",
|
|
1434
1503
|
color: "#f87171",
|
|
1435
1504
|
cursor: "pointer"
|
|
1436
|
-
}}
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1505
|
+
}, children: "Delete" })
|
|
1506
|
+
] })
|
|
1507
|
+
] })
|
|
1508
|
+
] });
|
|
1440
1509
|
}
|
|
1441
1510
|
}
|
|
1442
1511
|
);
|
|
1443
1512
|
|
|
1444
1513
|
// src/editor/LinkPreviewTooltip.jsx
|
|
1445
1514
|
var import_react17 = require("react");
|
|
1446
|
-
|
|
1515
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1447
1516
|
var previewCache = /* @__PURE__ */ new Map();
|
|
1448
1517
|
var linkPreviewEndpoint = "/api/link-preview";
|
|
1449
1518
|
function setLinkPreviewEndpoint(endpoint) {
|
|
1450
1519
|
linkPreviewEndpoint = endpoint;
|
|
1451
1520
|
}
|
|
1452
1521
|
async function fetchPreview(url) {
|
|
1453
|
-
if (previewCache.has(url))
|
|
1454
|
-
return previewCache.get(url);
|
|
1522
|
+
if (previewCache.has(url)) return previewCache.get(url);
|
|
1455
1523
|
try {
|
|
1456
1524
|
const res = await fetch(`${linkPreviewEndpoint}?url=${encodeURIComponent(url)}`);
|
|
1457
|
-
if (!res.ok)
|
|
1458
|
-
throw new Error("fetch failed");
|
|
1525
|
+
if (!res.ok) throw new Error("fetch failed");
|
|
1459
1526
|
const data = await res.json();
|
|
1460
1527
|
previewCache.set(url, data);
|
|
1461
1528
|
return data;
|
|
@@ -1472,8 +1539,7 @@ function LinkPreviewTooltip({ anchorEl, url, onClose }) {
|
|
|
1472
1539
|
const hoverRef = (0, import_react17.useRef)(false);
|
|
1473
1540
|
const hideTimerRef = (0, import_react17.useRef)(null);
|
|
1474
1541
|
(0, import_react17.useEffect)(() => {
|
|
1475
|
-
if (!url)
|
|
1476
|
-
return;
|
|
1542
|
+
if (!url) return;
|
|
1477
1543
|
setLoading(true);
|
|
1478
1544
|
fetchPreview(url).then((d) => {
|
|
1479
1545
|
setData(d);
|
|
@@ -1497,13 +1563,11 @@ function LinkPreviewTooltip({ anchorEl, url, onClose }) {
|
|
|
1497
1563
|
const scheduleHide = (0, import_react17.useCallback)(() => {
|
|
1498
1564
|
clearTimeout(hideTimerRef.current);
|
|
1499
1565
|
hideTimerRef.current = setTimeout(() => {
|
|
1500
|
-
if (!hoverRef.current)
|
|
1501
|
-
onClose();
|
|
1566
|
+
if (!hoverRef.current) onClose();
|
|
1502
1567
|
}, 200);
|
|
1503
1568
|
}, [onClose]);
|
|
1504
1569
|
(0, import_react17.useEffect)(() => {
|
|
1505
|
-
if (!anchorEl)
|
|
1506
|
-
return;
|
|
1570
|
+
if (!anchorEl) return;
|
|
1507
1571
|
const onEnter = () => {
|
|
1508
1572
|
hoverRef.current = true;
|
|
1509
1573
|
clearTimeout(hideTimerRef.current);
|
|
@@ -1530,34 +1594,37 @@ function LinkPreviewTooltip({ anchorEl, url, onClose }) {
|
|
|
1530
1594
|
(0, import_react17.useEffect)(() => {
|
|
1531
1595
|
return () => clearTimeout(hideTimerRef.current);
|
|
1532
1596
|
}, []);
|
|
1533
|
-
if (!url || !posRef.current)
|
|
1534
|
-
return null;
|
|
1597
|
+
if (!url || !posRef.current) return null;
|
|
1535
1598
|
const style = posRef.current.useBottom ? { bottom: posRef.current.bottom, left: posRef.current.left } : { top: posRef.current.top, left: posRef.current.left };
|
|
1536
|
-
return
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
<div className="link-preview-body">
|
|
1551
|
-
<div className="link-preview-title">{data.title}</div>
|
|
1552
|
-
{data.description && <div className="link-preview-desc">{data.description.length > 120 ? data.description.slice(0, 120) + "..." : data.description}</div>}
|
|
1553
|
-
<div className="link-preview-domain">
|
|
1554
|
-
{data.favicon && <img src={data.favicon} alt="" className="link-preview-favicon" onError={(e) => {
|
|
1599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1600
|
+
"div",
|
|
1601
|
+
{
|
|
1602
|
+
ref: tooltipRef,
|
|
1603
|
+
className: "link-preview-tooltip",
|
|
1604
|
+
style,
|
|
1605
|
+
onMouseEnter: onTooltipEnter,
|
|
1606
|
+
onMouseLeave: onTooltipLeave,
|
|
1607
|
+
children: loading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "link-preview-loading", children: [
|
|
1608
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "link-preview-skeleton", style: { width: "60%", height: 12 } }),
|
|
1609
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "link-preview-skeleton", style: { width: "90%", height: 10, marginTop: 8 } }),
|
|
1610
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "link-preview-skeleton", style: { width: "40%", height: 10, marginTop: 4 } })
|
|
1611
|
+
] }) : data ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "link-preview-card", children: [
|
|
1612
|
+
data.image && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "link-preview-image", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("img", { src: data.image, alt: "", onError: (e) => {
|
|
1555
1613
|
e.target.style.display = "none";
|
|
1556
|
-
}}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1614
|
+
} }) }),
|
|
1615
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "link-preview-body", children: [
|
|
1616
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "link-preview-title", children: data.title }),
|
|
1617
|
+
data.description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "link-preview-desc", children: data.description.length > 120 ? data.description.slice(0, 120) + "..." : data.description }),
|
|
1618
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "link-preview-domain", children: [
|
|
1619
|
+
data.favicon && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("img", { src: data.favicon, alt: "", className: "link-preview-favicon", onError: (e) => {
|
|
1620
|
+
e.target.style.display = "none";
|
|
1621
|
+
} }),
|
|
1622
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: data.domain })
|
|
1623
|
+
] })
|
|
1624
|
+
] })
|
|
1625
|
+
] }) : null
|
|
1626
|
+
}
|
|
1627
|
+
);
|
|
1561
1628
|
}
|
|
1562
1629
|
function useLinkPreview() {
|
|
1563
1630
|
const [preview, setPreview] = (0, import_react17.useState)(null);
|
|
@@ -1582,7 +1649,7 @@ function useLinkPreview() {
|
|
|
1582
1649
|
}
|
|
1583
1650
|
|
|
1584
1651
|
// src/editor/LixEditor.jsx
|
|
1585
|
-
|
|
1652
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1586
1653
|
var DEFAULT_LANGUAGES = {
|
|
1587
1654
|
text: { name: "Text" },
|
|
1588
1655
|
javascript: { name: "JavaScript", aliases: ["js"] },
|
|
@@ -1658,38 +1725,26 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1658
1725
|
}) : void 0;
|
|
1659
1726
|
const schema = (0, import_react19.useMemo)(() => {
|
|
1660
1727
|
const blockSpecs = { ...import_core.defaultBlockSpecs };
|
|
1661
|
-
if (codeBlock)
|
|
1662
|
-
|
|
1663
|
-
if (f.
|
|
1664
|
-
|
|
1665
|
-
if (f.
|
|
1666
|
-
|
|
1667
|
-
if (f.
|
|
1668
|
-
blockSpecs.tableOfContents = TableOfContents({});
|
|
1669
|
-
if (f.images)
|
|
1670
|
-
blockSpecs.image = BlogImageBlock({});
|
|
1671
|
-
if (f.buttons)
|
|
1672
|
-
blockSpecs.buttonBlock = ButtonBlock({});
|
|
1673
|
-
if (f.pdf)
|
|
1674
|
-
blockSpecs.pdfEmbed = PDFEmbedBlock({});
|
|
1728
|
+
if (codeBlock) blockSpecs.codeBlock = codeBlock;
|
|
1729
|
+
if (f.equations) blockSpecs.blockEquation = BlockEquation({});
|
|
1730
|
+
if (f.mermaid) blockSpecs.mermaidBlock = MermaidBlock({});
|
|
1731
|
+
if (f.tableOfContents) blockSpecs.tableOfContents = TableOfContents({});
|
|
1732
|
+
if (f.images) blockSpecs.image = BlogImageBlock({});
|
|
1733
|
+
if (f.buttons) blockSpecs.buttonBlock = ButtonBlock({});
|
|
1734
|
+
if (f.pdf) blockSpecs.pdfEmbed = PDFEmbedBlock({});
|
|
1675
1735
|
for (const spec of extraBlockSpecs) {
|
|
1676
|
-
if (spec.type && spec.spec)
|
|
1677
|
-
blockSpecs[spec.type] = spec.spec;
|
|
1736
|
+
if (spec.type && spec.spec) blockSpecs[spec.type] = spec.spec;
|
|
1678
1737
|
}
|
|
1679
1738
|
const inlineContentSpecs = { ...import_core.defaultInlineContentSpecs };
|
|
1680
|
-
if (f.equations)
|
|
1681
|
-
|
|
1682
|
-
if (f.dates)
|
|
1683
|
-
inlineContentSpecs.dateInline = DateInline;
|
|
1739
|
+
if (f.equations) inlineContentSpecs.inlineEquation = InlineEquation;
|
|
1740
|
+
if (f.dates) inlineContentSpecs.dateInline = DateInline;
|
|
1684
1741
|
for (const spec of extraInlineSpecs) {
|
|
1685
|
-
if (spec.type && spec.spec)
|
|
1686
|
-
inlineContentSpecs[spec.type] = spec.spec;
|
|
1742
|
+
if (spec.type && spec.spec) inlineContentSpecs[spec.type] = spec.spec;
|
|
1687
1743
|
}
|
|
1688
1744
|
return import_core.BlockNoteSchema.create({ blockSpecs, inlineContentSpecs });
|
|
1689
1745
|
}, []);
|
|
1690
1746
|
const sanitized = (0, import_react19.useMemo)(() => {
|
|
1691
|
-
if (!initialContent)
|
|
1692
|
-
return void 0;
|
|
1747
|
+
if (!initialContent) return void 0;
|
|
1693
1748
|
let blocks = initialContent;
|
|
1694
1749
|
if (typeof blocks === "string") {
|
|
1695
1750
|
try {
|
|
@@ -1698,8 +1753,7 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1698
1753
|
return void 0;
|
|
1699
1754
|
}
|
|
1700
1755
|
}
|
|
1701
|
-
if (!Array.isArray(blocks) || blocks.length === 0)
|
|
1702
|
-
return void 0;
|
|
1756
|
+
if (!Array.isArray(blocks) || blocks.length === 0) return void 0;
|
|
1703
1757
|
return blocks;
|
|
1704
1758
|
}, [initialContent]);
|
|
1705
1759
|
const editor = (0, import_react18.useCreateBlockNote)({
|
|
@@ -1716,15 +1770,12 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1716
1770
|
getMarkdown: async () => await editor.blocksToMarkdownLossy(editor.document)
|
|
1717
1771
|
}), [editor]);
|
|
1718
1772
|
(0, import_react19.useEffect)(() => {
|
|
1719
|
-
if (onReady)
|
|
1720
|
-
onReady();
|
|
1773
|
+
if (onReady) onReady();
|
|
1721
1774
|
}, []);
|
|
1722
1775
|
(0, import_react19.useEffect)(() => {
|
|
1723
|
-
if (!f.markdownLinks || !editor)
|
|
1724
|
-
return;
|
|
1776
|
+
if (!f.markdownLinks || !editor) return;
|
|
1725
1777
|
const tiptap = editor._tiptapEditor;
|
|
1726
|
-
if (!tiptap)
|
|
1727
|
-
return;
|
|
1778
|
+
if (!tiptap) return;
|
|
1728
1779
|
const handleInput = () => {
|
|
1729
1780
|
const { state, view } = tiptap;
|
|
1730
1781
|
const { $from } = state.selection;
|
|
@@ -1752,8 +1803,7 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1752
1803
|
return;
|
|
1753
1804
|
}
|
|
1754
1805
|
const match = textBefore.match(/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)$/);
|
|
1755
|
-
if (!match)
|
|
1756
|
-
return;
|
|
1806
|
+
if (!match) return;
|
|
1757
1807
|
const [fullMatch, linkText, url] = match;
|
|
1758
1808
|
const from = $from.pos - fullMatch.length;
|
|
1759
1809
|
const linkMark = state.schema.marks.link.create({ href: url });
|
|
@@ -1764,31 +1814,24 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1764
1814
|
return () => tiptap.off("update", handleInput);
|
|
1765
1815
|
}, [editor, f.markdownLinks]);
|
|
1766
1816
|
(0, import_react19.useEffect)(() => {
|
|
1767
|
-
if (!f.linkPreview)
|
|
1768
|
-
return;
|
|
1817
|
+
if (!f.linkPreview) return;
|
|
1769
1818
|
const wrapper = wrapperRef.current;
|
|
1770
|
-
if (!wrapper)
|
|
1771
|
-
return;
|
|
1819
|
+
if (!wrapper) return;
|
|
1772
1820
|
const handleMouseOver = (e) => {
|
|
1773
1821
|
const link = e.target.closest("a[href]");
|
|
1774
|
-
if (!link || link.closest(".bn-link-toolbar") || link.closest(".bn-toolbar"))
|
|
1775
|
-
return;
|
|
1822
|
+
if (!link || link.closest(".bn-link-toolbar") || link.closest(".bn-toolbar")) return;
|
|
1776
1823
|
const href = link.getAttribute("href");
|
|
1777
|
-
if (href && href.startsWith("http"))
|
|
1778
|
-
editorLinkPreview.show(link, href);
|
|
1824
|
+
if (href && href.startsWith("http")) editorLinkPreview.show(link, href);
|
|
1779
1825
|
};
|
|
1780
1826
|
const handleMouseOut = (e) => {
|
|
1781
1827
|
const link = e.target.closest("a[href]");
|
|
1782
|
-
if (!link)
|
|
1783
|
-
return;
|
|
1828
|
+
if (!link) return;
|
|
1784
1829
|
editorLinkPreview.cancel();
|
|
1785
1830
|
};
|
|
1786
1831
|
const handleClick = (e) => {
|
|
1787
|
-
if (!(e.ctrlKey || e.metaKey))
|
|
1788
|
-
return;
|
|
1832
|
+
if (!(e.ctrlKey || e.metaKey)) return;
|
|
1789
1833
|
const link = e.target.closest("a[href]");
|
|
1790
|
-
if (!link || link.closest(".bn-link-toolbar"))
|
|
1791
|
-
return;
|
|
1834
|
+
if (!link || link.closest(".bn-link-toolbar")) return;
|
|
1792
1835
|
const href = link.getAttribute("href");
|
|
1793
1836
|
if (href && href.startsWith("http")) {
|
|
1794
1837
|
e.preventDefault();
|
|
@@ -1797,8 +1840,7 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1797
1840
|
}
|
|
1798
1841
|
};
|
|
1799
1842
|
const handleKeyDown = (e) => {
|
|
1800
|
-
if (e.ctrlKey || e.metaKey)
|
|
1801
|
-
wrapper.classList.add("ctrl-held");
|
|
1843
|
+
if (e.ctrlKey || e.metaKey) wrapper.classList.add("ctrl-held");
|
|
1802
1844
|
};
|
|
1803
1845
|
const handleKeyUp = () => wrapper.classList.remove("ctrl-held");
|
|
1804
1846
|
wrapper.addEventListener("mouseover", handleMouseOver);
|
|
@@ -1822,7 +1864,7 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1822
1864
|
title: "Block Equation",
|
|
1823
1865
|
subtext: "LaTeX block equation",
|
|
1824
1866
|
group: "Advanced",
|
|
1825
|
-
icon:
|
|
1867
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 16 }, children: "\u2211" }),
|
|
1826
1868
|
onItemClick: () => editor.insertBlocks([{ type: "blockEquation" }], editor.getTextCursorPosition().block, "after")
|
|
1827
1869
|
});
|
|
1828
1870
|
}
|
|
@@ -1831,7 +1873,7 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1831
1873
|
title: "Diagram",
|
|
1832
1874
|
subtext: "Mermaid diagram (flowchart, sequence, etc.)",
|
|
1833
1875
|
group: "Advanced",
|
|
1834
|
-
icon:
|
|
1876
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 14 }, children: "\u25C7" }),
|
|
1835
1877
|
onItemClick: () => editor.insertBlocks([{ type: "mermaidBlock" }], editor.getTextCursorPosition().block, "after")
|
|
1836
1878
|
});
|
|
1837
1879
|
}
|
|
@@ -1840,33 +1882,39 @@ var LixEditor = (0, import_react19.forwardRef)(function LixEditor2({
|
|
|
1840
1882
|
title: "Table of Contents",
|
|
1841
1883
|
subtext: "Auto-generated document outline",
|
|
1842
1884
|
group: "Advanced",
|
|
1843
|
-
icon:
|
|
1885
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 14 }, children: "\u2630" }),
|
|
1844
1886
|
onItemClick: () => editor.insertBlocks([{ type: "tableOfContents" }], editor.getTextCursorPosition().block, "after")
|
|
1845
1887
|
});
|
|
1846
1888
|
}
|
|
1847
1889
|
return [...defaults, ...custom, ...extraSlashItems].filter((item) => item.title.toLowerCase().includes(query.toLowerCase()));
|
|
1848
1890
|
}, [editor, f, extraSlashItems]);
|
|
1849
1891
|
const handleChange = (0, import_react19.useCallback)(() => {
|
|
1850
|
-
if (onChange)
|
|
1851
|
-
onChange(editor);
|
|
1892
|
+
if (onChange) onChange(editor);
|
|
1852
1893
|
}, [editor, onChange]);
|
|
1853
|
-
return
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1894
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `lix-editor-wrapper${""}`, ref: wrapperRef, style: { position: "relative" }, children: [
|
|
1895
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1896
|
+
import_mantine.BlockNoteView,
|
|
1897
|
+
{
|
|
1898
|
+
editor,
|
|
1899
|
+
onChange: handleChange,
|
|
1900
|
+
theme: isDark ? "dark" : "light",
|
|
1901
|
+
slashMenu: false,
|
|
1902
|
+
children: [
|
|
1903
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react18.SuggestionMenuController, { triggerCharacter: "/", getItems }),
|
|
1904
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react18.TableHandlesController, {}),
|
|
1905
|
+
children
|
|
1906
|
+
]
|
|
1907
|
+
}
|
|
1908
|
+
),
|
|
1909
|
+
f.linkPreview && editorLinkPreview.preview && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1910
|
+
LinkPreviewTooltip,
|
|
1911
|
+
{
|
|
1912
|
+
anchorEl: editorLinkPreview.preview.anchorEl,
|
|
1913
|
+
url: editorLinkPreview.preview.url,
|
|
1914
|
+
onClose: editorLinkPreview.hide
|
|
1915
|
+
}
|
|
1916
|
+
)
|
|
1917
|
+
] });
|
|
1870
1918
|
});
|
|
1871
1919
|
var LixEditor_default = LixEditor;
|
|
1872
1920
|
|
|
@@ -1875,11 +1923,9 @@ var import_react20 = require("react");
|
|
|
1875
1923
|
|
|
1876
1924
|
// src/preview/renderBlocks.js
|
|
1877
1925
|
function renderBlocksToHTML(blocks) {
|
|
1878
|
-
if (!blocks || !blocks.length)
|
|
1879
|
-
return "";
|
|
1926
|
+
if (!blocks || !blocks.length) return "";
|
|
1880
1927
|
function inlineToHTML(content) {
|
|
1881
|
-
if (!content || !Array.isArray(content))
|
|
1882
|
-
return "";
|
|
1928
|
+
if (!content || !Array.isArray(content)) return "";
|
|
1883
1929
|
return content.map((c) => {
|
|
1884
1930
|
if (c.type === "inlineEquation" && c.props?.latex) {
|
|
1885
1931
|
return `<span class="lix-inline-equation" data-latex="${encodeURIComponent(c.props.latex)}"></span>`;
|
|
@@ -1898,23 +1944,15 @@ function renderBlocksToHTML(blocks) {
|
|
|
1898
1944
|
return `<a href="${c.href}">${linkText || c.href}</a>`;
|
|
1899
1945
|
}
|
|
1900
1946
|
let text = (c.text || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1901
|
-
if (!text)
|
|
1902
|
-
return "";
|
|
1947
|
+
if (!text) return "";
|
|
1903
1948
|
const s = c.styles || {};
|
|
1904
|
-
if (s.bold)
|
|
1905
|
-
|
|
1906
|
-
if (s.
|
|
1907
|
-
|
|
1908
|
-
if (s.
|
|
1909
|
-
|
|
1910
|
-
if (s.
|
|
1911
|
-
text = `<code>${text}</code>`;
|
|
1912
|
-
if (s.underline)
|
|
1913
|
-
text = `<u>${text}</u>`;
|
|
1914
|
-
if (s.textColor)
|
|
1915
|
-
text = `<span style="color:${s.textColor}">${text}</span>`;
|
|
1916
|
-
if (s.backgroundColor)
|
|
1917
|
-
text = `<span style="background:${s.backgroundColor};border-radius:3px;padding:0 2px">${text}</span>`;
|
|
1949
|
+
if (s.bold) text = `<strong>${text}</strong>`;
|
|
1950
|
+
if (s.italic) text = `<em>${text}</em>`;
|
|
1951
|
+
if (s.strike) text = `<del>${text}</del>`;
|
|
1952
|
+
if (s.code) text = `<code>${text}</code>`;
|
|
1953
|
+
if (s.underline) text = `<u>${text}</u>`;
|
|
1954
|
+
if (s.textColor) text = `<span style="color:${s.textColor}">${text}</span>`;
|
|
1955
|
+
if (s.backgroundColor) text = `<span style="background:${s.backgroundColor};border-radius:3px;padding:0 2px">${text}</span>`;
|
|
1918
1956
|
return text;
|
|
1919
1957
|
}).join("");
|
|
1920
1958
|
}
|
|
@@ -1928,8 +1966,7 @@ function renderBlocksToHTML(blocks) {
|
|
|
1928
1966
|
headings.push({ id, text: text.trim(), level: block.props?.level || 1 });
|
|
1929
1967
|
}
|
|
1930
1968
|
}
|
|
1931
|
-
if (block.children?.length)
|
|
1932
|
-
collectHeadings(block.children);
|
|
1969
|
+
if (block.children?.length) collectHeadings(block.children);
|
|
1933
1970
|
}
|
|
1934
1971
|
}
|
|
1935
1972
|
collectHeadings(blocks);
|
|
@@ -1955,12 +1992,10 @@ function renderBlocksToHTML(blocks) {
|
|
|
1955
1992
|
return `<li class="lix-check${checked ? " lix-check--checked" : ""}">${cb}<span class="lix-check-text">${content}</span>${childrenHTML}</li>`;
|
|
1956
1993
|
}
|
|
1957
1994
|
case "blockEquation":
|
|
1958
|
-
if (block.props?.latex)
|
|
1959
|
-
return `<div class="lix-block-equation" data-latex="${encodeURIComponent(block.props.latex)}"></div>${childrenHTML}`;
|
|
1995
|
+
if (block.props?.latex) return `<div class="lix-block-equation" data-latex="${encodeURIComponent(block.props.latex)}"></div>${childrenHTML}`;
|
|
1960
1996
|
return childrenHTML;
|
|
1961
1997
|
case "mermaidBlock":
|
|
1962
|
-
if (block.props?.diagram)
|
|
1963
|
-
return `<div class="lix-mermaid-block" data-diagram="${encodeURIComponent(block.props.diagram)}"></div>${childrenHTML}`;
|
|
1998
|
+
if (block.props?.diagram) return `<div class="lix-mermaid-block" data-diagram="${encodeURIComponent(block.props.diagram)}"></div>${childrenHTML}`;
|
|
1964
1999
|
return childrenHTML;
|
|
1965
2000
|
case "divider":
|
|
1966
2001
|
return `<hr class="lix-divider" />${childrenHTML}`;
|
|
@@ -1976,8 +2011,7 @@ function renderBlocksToHTML(blocks) {
|
|
|
1976
2011
|
return childrenHTML;
|
|
1977
2012
|
case "table": {
|
|
1978
2013
|
const rows = block.content?.rows || [];
|
|
1979
|
-
if (!rows.length)
|
|
1980
|
-
return childrenHTML;
|
|
2014
|
+
if (!rows.length) return childrenHTML;
|
|
1981
2015
|
const headerRows = block.content?.headerRows || 0;
|
|
1982
2016
|
let table = "<table>";
|
|
1983
2017
|
rows.forEach((row, ri) => {
|
|
@@ -1985,12 +2019,9 @@ function renderBlocksToHTML(blocks) {
|
|
|
1985
2019
|
(row.cells || []).forEach((cell) => {
|
|
1986
2020
|
const tag = ri < headerRows ? "th" : "td";
|
|
1987
2021
|
let cellContent;
|
|
1988
|
-
if (Array.isArray(cell))
|
|
1989
|
-
|
|
1990
|
-
else
|
|
1991
|
-
cellContent = Array.isArray(cell.content) ? cell.content : [];
|
|
1992
|
-
else
|
|
1993
|
-
cellContent = [];
|
|
2022
|
+
if (Array.isArray(cell)) cellContent = cell;
|
|
2023
|
+
else if (cell?.content) cellContent = Array.isArray(cell.content) ? cell.content : [];
|
|
2024
|
+
else cellContent = [];
|
|
1994
2025
|
table += `<${tag}>${inlineToHTML(cellContent)}</${tag}>`;
|
|
1995
2026
|
});
|
|
1996
2027
|
table += "</tr>";
|
|
@@ -2000,14 +2031,12 @@ function renderBlocksToHTML(blocks) {
|
|
|
2000
2031
|
}
|
|
2001
2032
|
case "paragraph":
|
|
2002
2033
|
default:
|
|
2003
|
-
if (content)
|
|
2004
|
-
return `<p>${content}</p>${childrenHTML}`;
|
|
2034
|
+
if (content) return `<p>${content}</p>${childrenHTML}`;
|
|
2005
2035
|
return childrenHTML || "";
|
|
2006
2036
|
}
|
|
2007
2037
|
}
|
|
2008
2038
|
function renderListGroup(blockList) {
|
|
2009
|
-
if (!blockList?.length)
|
|
2010
|
-
return "";
|
|
2039
|
+
if (!blockList?.length) return "";
|
|
2011
2040
|
const out = [];
|
|
2012
2041
|
let i = 0;
|
|
2013
2042
|
while (i < blockList.length) {
|
|
@@ -2055,7 +2084,7 @@ function renderBlocksToHTML(blocks) {
|
|
|
2055
2084
|
}
|
|
2056
2085
|
|
|
2057
2086
|
// src/preview/LixPreview.jsx
|
|
2058
|
-
|
|
2087
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2059
2088
|
function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
2060
2089
|
const { isDark } = useLixTheme();
|
|
2061
2090
|
const contentRef = (0, import_react20.useRef)(null);
|
|
@@ -2073,8 +2102,7 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2073
2102
|
const effectGenRef = (0, import_react20.useRef)(0);
|
|
2074
2103
|
(0, import_react20.useEffect)(() => {
|
|
2075
2104
|
const root = contentRef.current;
|
|
2076
|
-
if (!root)
|
|
2077
|
-
return;
|
|
2105
|
+
if (!root) return;
|
|
2078
2106
|
const gen = ++effectGenRef.current;
|
|
2079
2107
|
root.innerHTML = renderedHTML || "";
|
|
2080
2108
|
function isStale() {
|
|
@@ -2085,24 +2113,18 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2085
2113
|
const inlineEls = root.querySelectorAll(".lix-inline-equation[data-latex]");
|
|
2086
2114
|
if (eqEls.length || inlineEls.length) {
|
|
2087
2115
|
import("katex").then((mod) => {
|
|
2088
|
-
if (isStale())
|
|
2089
|
-
return;
|
|
2116
|
+
if (isStale()) return;
|
|
2090
2117
|
const katex3 = mod.default || mod;
|
|
2091
2118
|
const strip = (raw) => {
|
|
2092
2119
|
let s = raw.trim();
|
|
2093
|
-
if (s.startsWith("\\[") && s.endsWith("\\]"))
|
|
2094
|
-
|
|
2095
|
-
if (s.startsWith("
|
|
2096
|
-
|
|
2097
|
-
if (s.startsWith("\\(") && s.endsWith("\\)"))
|
|
2098
|
-
return s.slice(2, -2).trim();
|
|
2099
|
-
if (s.startsWith("$") && s.endsWith("$") && s.length > 2)
|
|
2100
|
-
return s.slice(1, -1).trim();
|
|
2120
|
+
if (s.startsWith("\\[") && s.endsWith("\\]")) return s.slice(2, -2).trim();
|
|
2121
|
+
if (s.startsWith("$$") && s.endsWith("$$")) return s.slice(2, -2).trim();
|
|
2122
|
+
if (s.startsWith("\\(") && s.endsWith("\\)")) return s.slice(2, -2).trim();
|
|
2123
|
+
if (s.startsWith("$") && s.endsWith("$") && s.length > 2) return s.slice(1, -1).trim();
|
|
2101
2124
|
return s;
|
|
2102
2125
|
};
|
|
2103
2126
|
eqEls.forEach((el) => {
|
|
2104
|
-
if (!el.isConnected)
|
|
2105
|
-
return;
|
|
2127
|
+
if (!el.isConnected) return;
|
|
2106
2128
|
try {
|
|
2107
2129
|
el.innerHTML = katex3.renderToString(strip(decodeURIComponent(el.dataset.latex)), { displayMode: true, throwOnError: false });
|
|
2108
2130
|
} catch (err) {
|
|
@@ -2110,8 +2132,7 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2110
2132
|
}
|
|
2111
2133
|
});
|
|
2112
2134
|
inlineEls.forEach((el) => {
|
|
2113
|
-
if (!el.isConnected)
|
|
2114
|
-
return;
|
|
2135
|
+
if (!el.isConnected) return;
|
|
2115
2136
|
try {
|
|
2116
2137
|
el.innerHTML = katex3.renderToString(strip(decodeURIComponent(el.dataset.latex)), { displayMode: false, throwOnError: false });
|
|
2117
2138
|
} catch (err) {
|
|
@@ -2126,8 +2147,7 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2126
2147
|
const mermaidEls = root.querySelectorAll(".lix-mermaid-block[data-diagram]");
|
|
2127
2148
|
if (mermaidEls.length) {
|
|
2128
2149
|
import("mermaid").then((mod) => {
|
|
2129
|
-
if (isStale())
|
|
2130
|
-
return;
|
|
2150
|
+
if (isStale()) return;
|
|
2131
2151
|
const mermaid = mod.default || mod;
|
|
2132
2152
|
mermaid.initialize({
|
|
2133
2153
|
startOnLoad: false,
|
|
@@ -2156,8 +2176,7 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2156
2176
|
}
|
|
2157
2177
|
}
|
|
2158
2178
|
} catch (err) {
|
|
2159
|
-
if (el.isConnected)
|
|
2160
|
-
el.innerHTML = `<pre style="color:#f87171;font-size:12px">${err.message || "Diagram error"}</pre>`;
|
|
2179
|
+
if (el.isConnected) el.innerHTML = `<pre style="color:#f87171;font-size:12px">${err.message || "Diagram error"}</pre>`;
|
|
2161
2180
|
try {
|
|
2162
2181
|
document.getElementById(id)?.remove();
|
|
2163
2182
|
document.getElementById("c-" + id)?.remove();
|
|
@@ -2174,22 +2193,18 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2174
2193
|
const codeEls = root.querySelectorAll('pre > code[class*="language-"]');
|
|
2175
2194
|
if (codeEls.length) {
|
|
2176
2195
|
import("shiki").then(({ createHighlighter }) => {
|
|
2177
|
-
if (isStale())
|
|
2178
|
-
return;
|
|
2196
|
+
if (isStale()) return;
|
|
2179
2197
|
const langs = /* @__PURE__ */ new Set();
|
|
2180
2198
|
codeEls.forEach((el) => {
|
|
2181
2199
|
const m = el.className.match(/language-(\w+)/);
|
|
2182
|
-
if (m?.[1] && m[1] !== "text")
|
|
2183
|
-
langs.add(m[1]);
|
|
2200
|
+
if (m?.[1] && m[1] !== "text") langs.add(m[1]);
|
|
2184
2201
|
});
|
|
2185
2202
|
return createHighlighter({ themes: ["vitesse-dark", "vitesse-light"], langs: [...langs] }).then((hl) => {
|
|
2186
|
-
if (isStale())
|
|
2187
|
-
return;
|
|
2203
|
+
if (isStale()) return;
|
|
2188
2204
|
const theme = isDark ? "vitesse-dark" : "vitesse-light";
|
|
2189
2205
|
codeEls.forEach((codeEl) => {
|
|
2190
2206
|
const pre = codeEl.parentElement;
|
|
2191
|
-
if (!pre || pre.dataset.highlighted)
|
|
2192
|
-
return;
|
|
2207
|
+
if (!pre || pre.dataset.highlighted) return;
|
|
2193
2208
|
pre.dataset.highlighted = "true";
|
|
2194
2209
|
const m = codeEl.className.match(/language-(\w+)/);
|
|
2195
2210
|
const lang = m?.[1] || "text";
|
|
@@ -2200,8 +2215,7 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2200
2215
|
const tmp = document.createElement("div");
|
|
2201
2216
|
tmp.innerHTML = html2;
|
|
2202
2217
|
const shikiPre = tmp.querySelector("pre");
|
|
2203
|
-
if (shikiPre)
|
|
2204
|
-
codeEl.innerHTML = shikiPre.querySelector("code")?.innerHTML || codeEl.innerHTML;
|
|
2218
|
+
if (shikiPre) codeEl.innerHTML = shikiPre.querySelector("code")?.innerHTML || codeEl.innerHTML;
|
|
2205
2219
|
} catch {
|
|
2206
2220
|
}
|
|
2207
2221
|
}
|
|
@@ -2235,8 +2249,7 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2235
2249
|
const handlers = [];
|
|
2236
2250
|
externalLinks.forEach((link) => {
|
|
2237
2251
|
const href = link.getAttribute("href");
|
|
2238
|
-
if (!href)
|
|
2239
|
-
return;
|
|
2252
|
+
if (!href) return;
|
|
2240
2253
|
const onEnter = () => linkPreviewRef.current.show(link, href);
|
|
2241
2254
|
const onLeave = () => linkPreviewRef.current.cancel();
|
|
2242
2255
|
link.addEventListener("mouseenter", onEnter);
|
|
@@ -2249,19 +2262,22 @@ function LixPreview({ blocks, html, features = {}, className = "" }) {
|
|
|
2249
2262
|
});
|
|
2250
2263
|
}
|
|
2251
2264
|
}, [renderedHTML, isDark]);
|
|
2252
|
-
return
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `lix-preview ${className}`, children: [
|
|
2266
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref: contentRef, className: "lix-preview-content" }),
|
|
2267
|
+
f.linkPreview && linkPreview.preview && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2268
|
+
LinkPreviewTooltip,
|
|
2269
|
+
{
|
|
2270
|
+
anchorEl: linkPreview.preview.anchorEl,
|
|
2271
|
+
url: linkPreview.preview.url,
|
|
2272
|
+
onClose: linkPreview.hide
|
|
2273
|
+
}
|
|
2274
|
+
)
|
|
2275
|
+
] });
|
|
2260
2276
|
}
|
|
2261
2277
|
|
|
2262
2278
|
// src/editor/KeyboardShortcutsModal.jsx
|
|
2263
2279
|
var import_react21 = require("react");
|
|
2264
|
-
|
|
2280
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2265
2281
|
var SHORTCUT_GROUPS = [
|
|
2266
2282
|
{
|
|
2267
2283
|
title: "General",
|
|
@@ -2313,12 +2329,10 @@ function KeyboardShortcutsModal({ onClose }) {
|
|
|
2313
2329
|
const ref = (0, import_react21.useRef)(null);
|
|
2314
2330
|
(0, import_react21.useEffect)(() => {
|
|
2315
2331
|
function handleKey(e) {
|
|
2316
|
-
if (e.key === "Escape")
|
|
2317
|
-
onClose();
|
|
2332
|
+
if (e.key === "Escape") onClose();
|
|
2318
2333
|
}
|
|
2319
2334
|
function handleClick(e) {
|
|
2320
|
-
if (ref.current && !ref.current.contains(e.target))
|
|
2321
|
-
onClose();
|
|
2335
|
+
if (ref.current && !ref.current.contains(e.target)) onClose();
|
|
2322
2336
|
}
|
|
2323
2337
|
document.addEventListener("keydown", handleKey);
|
|
2324
2338
|
document.addEventListener("mousedown", handleClick);
|
|
@@ -2327,38 +2341,50 @@ function KeyboardShortcutsModal({ onClose }) {
|
|
|
2327
2341
|
document.removeEventListener("mousedown", handleClick);
|
|
2328
2342
|
};
|
|
2329
2343
|
}, [onClose]);
|
|
2330
|
-
return
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center bg-black/30 backdrop-blur-sm", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
2345
|
+
"div",
|
|
2346
|
+
{
|
|
2347
|
+
ref,
|
|
2348
|
+
className: "w-full max-w-[520px] max-h-[80vh] rounded-2xl shadow-2xl overflow-hidden",
|
|
2349
|
+
style: { backgroundColor: "var(--card-bg)", border: "1px solid var(--border-default)", boxShadow: "var(--shadow-lg)" },
|
|
2350
|
+
children: [
|
|
2351
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between px-6 py-4", style: { borderBottom: "1px solid var(--divider)" }, children: [
|
|
2352
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2.5", children: [
|
|
2353
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("ion-icon", { name: "keypad-outline", style: { fontSize: "18px", color: "#9b7bf7" } }),
|
|
2354
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: "text-[15px] font-bold", style: { color: "var(--text-primary)" }, children: "Keyboard Shortcuts" })
|
|
2355
|
+
] }),
|
|
2356
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2357
|
+
"button",
|
|
2358
|
+
{
|
|
2359
|
+
onClick: onClose,
|
|
2360
|
+
className: "transition-colors p-1",
|
|
2361
|
+
style: { color: "var(--text-faint)" },
|
|
2362
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2363
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
2365
|
+
] })
|
|
2366
|
+
}
|
|
2367
|
+
)
|
|
2368
|
+
] }),
|
|
2369
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "overflow-y-auto max-h-[calc(80vh-60px)] p-6 space-y-6 scrollbar-thin", children: SHORTCUT_GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
2370
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-[11px] font-semibold uppercase tracking-wider mb-3", style: { color: "#9b7bf7" }, children: group.title }),
|
|
2371
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "space-y-1", children: group.shortcuts.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between py-1.5", children: [
|
|
2372
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-[13px]", style: { color: "var(--text-body)" }, children: s.desc }),
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex items-center gap-1", children: s.keys.map((key, j) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
|
|
2374
|
+
j > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-[10px] mx-0.5", style: { color: "var(--text-faint)" }, children: "+" }),
|
|
2375
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2376
|
+
"kbd",
|
|
2377
|
+
{
|
|
2378
|
+
className: "inline-block min-w-[24px] text-center px-1.5 py-0.5 text-[11px] font-medium rounded-md",
|
|
2379
|
+
style: { color: "var(--text-secondary)", backgroundColor: "var(--bg-surface)", border: "1px solid var(--border-default)" },
|
|
2380
|
+
children: key
|
|
2381
|
+
}
|
|
2382
|
+
)
|
|
2383
|
+
] }, j)) })
|
|
2384
|
+
] }, i)) })
|
|
2385
|
+
] }, group.title)) })
|
|
2386
|
+
]
|
|
2387
|
+
}
|
|
2388
|
+
) });
|
|
2363
2389
|
}
|
|
2364
2390
|
//# sourceMappingURL=index.cjs.map
|