@elixpo/lixeditor 2.5.1 → 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 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 src_exports = {};
28
- __export(src_exports, {
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(src_exports);
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
- "use client";
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 <LixThemeContext.Provider value={{ theme, setTheme, toggleTheme, isDark, mounted }}>{children}</LixThemeContext.Provider>;
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
- "use client";
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
- return s.slice(2, -2).trim();
100
- if (s.startsWith("$$") && s.endsWith("$$"))
101
- return s.slice(2, -2).trim();
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 <div className="mermaid-block mermaid-block--editing">
149
- <div className="mermaid-block-header">
150
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#c4b5fd" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z" /></svg>
151
- <span>LaTeX Equation</span>
152
- <span style={{ marginLeft: "auto", fontSize: "10px", color: "var(--text-faint)" }}>Shift+Enter to save</span>
153
- </div>
154
- <textarea
155
- ref={inputRef}
156
- value={value}
157
- onChange={handleCodeChange}
158
- onKeyDown={(e) => {
159
- if (e.key === "Enter" && e.shiftKey) {
160
- e.preventDefault();
161
- save();
162
- }
163
- if (e.key === "Escape") {
164
- setEditing(false);
165
- setValue(block.props.latex || "");
166
- setLivePreview(block.props.latex || "");
167
- }
168
- }}
169
- placeholder="E = mc^2"
170
- rows={4}
171
- className="mermaid-block-textarea"
172
- />
173
- {livePreview.trim() && <div className="latex-live-preview">
174
- <div className="latex-live-preview-label">Preview</div>
175
- <div dangerouslySetInnerHTML={{ __html: renderKaTeX(livePreview) }} />
176
- </div>}
177
- <div className="mermaid-block-actions">
178
- <button onClick={() => {
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
- }} className="mermaid-btn-cancel">Cancel</button>
183
- <button onClick={save} className="mermaid-btn-save" disabled={!value.trim()}>Done</button>
184
- </div>
185
- </div>;
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 <div
190
- onClick={() => setEditing(true)}
191
- className="mermaid-block mermaid-block--empty"
192
- >
193
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z" /></svg>
194
- <span>Click to add a block equation</span>
195
- </div>;
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 <div
198
- onClick={() => setEditing(true)}
199
- className="editor-block-equation"
200
- dangerouslySetInnerHTML={{ __html: renderKaTeX(latex) }}
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
- "use client";
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 <div className="mermaid-viewport mermaid-viewport--compact"><pre style={{ color: "#f87171", fontSize: "12px", whiteSpace: "pre-wrap", padding: "16px", margin: 0 }}>{error}</pre></div>;
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 <div className="mermaid-viewport mermaid-viewport--compact" style={{ display: "flex", alignItems: "center", justifyContent: "center" }}><span style={{ color: "var(--text-faint)", fontSize: "12px" }}>Preview will appear here...</span></div>;
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 <div className="mermaid-viewport mermaid-viewport--compact" style={{ display: "flex", alignItems: "center", justifyContent: "center" }}><span style={{ color: "var(--text-faint)", fontSize: "13px" }}>Rendering...</span></div>;
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 <div
434
- ref={containerRef}
435
- className={interactive ? "mermaid-viewport" : "mermaid-viewport mermaid-viewport--compact"}
436
- onMouseDown={handleMouseDown}
437
- >
438
- <div
439
- className="mermaid-block-svg"
440
- style={{
441
- transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
442
- transformOrigin: "center center"
443
- }}
444
- dangerouslySetInnerHTML={{ __html: svgHTML }}
445
- />
446
- {interactive && <div className="mermaid-zoom-controls">
447
- <button
448
- onClick={(e) => {
449
- e.stopPropagation();
450
- setZoom((z) => Math.min(3, z + 0.2));
451
- }}
452
- className="mermaid-zoom-btn"
453
- title="Zoom in"
454
- ><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
455
- <line x1="12" y1="5" x2="12" y2="19" />
456
- <line x1="5" y1="12" x2="19" y2="12" />
457
- </svg></button>
458
- <span className="mermaid-zoom-label">
459
- {Math.round(zoom * 100)}
460
- {"%"}
461
- </span>
462
- <button
463
- onClick={(e) => {
464
- e.stopPropagation();
465
- setZoom((z) => Math.max(0.3, z - 0.2));
466
- }}
467
- className="mermaid-zoom-btn"
468
- title="Zoom out"
469
- ><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12" /></svg></button>
470
- <button
471
- onClick={(e) => {
472
- e.stopPropagation();
473
- resetView();
474
- }}
475
- className="mermaid-zoom-btn"
476
- title="Reset view"
477
- ><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
478
- <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10" />
479
- <polyline points="1 4 1 10 7 10" />
480
- </svg></button>
481
- </div>}
482
- </div>;
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 <div className="mermaid-block mermaid-block--editing">
525
- <div className="mermaid-block-header">
526
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#c4b5fd" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><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" /></svg>
527
- <span>Mermaid Diagram</span>
528
- <span style={{ marginLeft: "auto", fontSize: "10px", color: "var(--text-faint)" }}>Shift+Enter to save</span>
529
- </div>
530
- <textarea
531
- ref={inputRef}
532
- value={value}
533
- onChange={handleCodeChange}
534
- onKeyDown={(e) => {
535
- if (e.key === "Enter" && e.shiftKey) {
536
- e.preventDefault();
537
- save();
538
- }
539
- if (e.key === "Escape") {
540
- setEditing(false);
541
- setValue(block.props.diagram || "");
542
- setLivePreview(block.props.diagram || "");
543
- }
544
- if (e.key === "Tab") {
545
- e.preventDefault();
546
- const start = e.target.selectionStart;
547
- const end = e.target.selectionEnd;
548
- const newVal = value.substring(0, start) + " " + value.substring(end);
549
- setValue(newVal);
550
- setLivePreview(newVal);
551
- requestAnimationFrame(() => {
552
- e.target.selectionStart = e.target.selectionEnd = start + 4;
553
- });
554
- }
555
- }}
556
- placeholder={`graph TD
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
- rows={8}
561
- className="mermaid-block-textarea"
562
- />
563
- <div className="mermaid-live-preview">
564
- <div className="mermaid-live-preview-label">Preview</div>
565
- <MermaidPreview diagram={livePreview} isDark={isDark} interactive={false} />
566
- </div>
567
- <div className="mermaid-block-actions">
568
- <button onClick={() => {
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
- }} className="mermaid-btn-cancel">Cancel</button>
573
- <button onClick={save} className="mermaid-btn-save" disabled={!value.trim()}>Done</button>
574
- </div>
575
- </div>;
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 <div onClick={() => setEditing(true)} className="mermaid-block mermaid-block--empty">
579
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
580
- <rect x="3" y="3" width="7" height="7" rx="1.5" />
581
- <rect x="14" y="3" width="7" height="7" rx="1.5" />
582
- <rect x="8.5" y="14" width="7" height="7" rx="1.5" />
583
- <line x1="6.5" y1="10" x2="6.5" y2="14" />
584
- <line x1="17.5" y1="10" x2="17.5" y2="14" />
585
- <line x1="6.5" y1="14" x2="8.5" y2="14" />
586
- <line x1="17.5" y1="14" x2="15.5" y2="14" />
587
- </svg>
588
- <span>Click to add a Mermaid diagram</span>
589
- </div>;
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 <div className="mermaid-block mermaid-block--rendered group" onDoubleClick={() => setEditing(true)}>
592
- <MermaidPreview diagram={block.props.diagram} isDark={isDark} interactive={true} />
593
- <div className="mermaid-block-hover">
594
- <button onClick={() => setEditing(true)} className="mermaid-hover-btn" title="Edit diagram"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
595
- <path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" />
596
- <path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" />
597
- </svg></button>
598
- <button onClick={handleDelete} className="mermaid-hover-btn mermaid-hover-delete" title="Delete"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
599
- <polyline points="3 6 5 6 21 6" />
600
- <path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" />
601
- </svg></button>
602
- </div>
603
- </div>;
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
- "use client";
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 <div className="toc-block border border-[var(--border-default)] rounded-xl bg-[var(--bg-surface)] px-5 py-4 my-2 select-none">
623
- <p className="text-[11px] uppercase tracking-wider text-[var(--text-muted)] font-bold mb-3">Table of Contents</p>
624
- {headings.length === 0 ? <p className="text-[13px] text-[var(--text-faint)] italic">Add headings to see the outline here.</p> : <ul className="space-y-1.5">{headings.map((h) => {
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 <li
628
- key={h.id}
629
- className="text-[13px] text-[#9b7bf7] hover:text-[#b69aff] cursor-pointer transition-colors"
630
- style={{ paddingLeft: `${(level - 1) * 16}px` }}
631
- onClick={() => editor.setTextCursorPosition(h.id)}
632
- >{text}</li>;
633
- })}</ul>}
634
- </div>;
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
- "use client";
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
- return s.slice(2, -2).trim();
648
- if (s.startsWith("\\[") && s.endsWith("\\]"))
649
- return s.slice(2, -2).trim();
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 <span className="relative inline-flex items-center">
692
- <span
693
- onClick={(e) => {
694
- e.preventDefault();
695
- e.stopPropagation();
696
- setValue(inlineContent.props.latex || "");
697
- setEditing(!editing);
698
- }}
699
- className="inline-equation-chip"
700
- dangerouslySetInnerHTML={{ __html: html }}
701
- title={inlineContent.props.latex}
702
- />
703
- {editing && <div
704
- ref={popupRef}
705
- className="inline-equation-editor"
706
- onMouseDown={(e) => e.stopPropagation()}
707
- >
708
- <input
709
- ref={inputRef}
710
- type="text"
711
- className="inline-equation-editor-input"
712
- value={value}
713
- onChange={(e) => setValue(e.target.value)}
714
- onKeyDown={(e) => {
715
- if (e.key === "Enter") {
716
- e.preventDefault();
717
- save();
718
- }
719
- if (e.key === "Escape") {
720
- setEditing(false);
721
- }
722
- }}
723
- placeholder="E = mc^2"
724
- />
725
- {previewHtml && <div className="inline-equation-editor-preview" dangerouslySetInnerHTML={{ __html: previewHtml }} />}
726
- <div className="inline-equation-editor-actions">
727
- <button className="mermaid-btn-cancel" onClick={() => setEditing(false)}>Cancel</button>
728
- <button className="mermaid-btn-save" disabled={!value.trim()} onClick={save}>Save</button>
729
- </div>
730
- </div>}
731
- </span>;
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) => <InlineEquationChip {...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
- "use client";
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
- days.push(null);
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
- return null;
790
- return <div
791
- ref={ref}
792
- className="fixed z-[100] rounded-xl shadow-2xl overflow-hidden"
793
- style={{ backgroundColor: "var(--bg-app)", border: "1px solid var(--border-default)", width: "240px", top: pos.top, left: pos.left }}
794
- onMouseDown={(e) => e.stopPropagation()}
795
- >
796
- <div className="flex items-center justify-between px-3 py-2" style={{ borderBottom: "1px solid var(--divider)" }}>
797
- <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)" }}><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><polyline points="15 18 9 12 15 6" /></svg></button>
798
- <span className="text-[12px] font-semibold" style={{ color: "var(--text-primary)" }}>{monthName}</span>
799
- <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)" }}><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><polyline points="9 18 15 12 9 6" /></svg></button>
800
- </div>
801
- <div className="grid grid-cols-7 px-2 pt-2">{["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((d) => <div key={d} className="text-center text-[10px] font-medium py-1" style={{ color: "var(--text-faint)" }}>{d}</div>)}</div>
802
- <div className="grid grid-cols-7 px-2 pb-2 gap-0.5">{days.map((d, i) => {
803
- if (!d)
804
- return <div key={`e${i}`} />;
805
- const dateStr = toDateStr(d);
806
- const isSelected = dateStr === selectedDate;
807
- const isToday = dateStr === todayStr;
808
- return <button
809
- key={d}
810
- onClick={() => {
811
- onSelect(dateStr);
812
- onClose();
813
- }}
814
- className="w-7 h-7 rounded-lg text-[11px] font-medium flex items-center justify-center transition-all"
815
- style={{
816
- backgroundColor: isSelected ? "#9b7bf7" : "transparent",
817
- color: isSelected ? "white" : isToday ? "#9b7bf7" : "var(--text-body)",
818
- border: isToday && !isSelected ? "1px solid #9b7bf7" : "1px solid transparent"
819
- }}
820
- onMouseEnter={(e) => {
821
- if (!isSelected)
822
- e.currentTarget.style.backgroundColor = "var(--bg-hover)";
823
- }}
824
- onMouseLeave={(e) => {
825
- if (!isSelected)
826
- e.currentTarget.style.backgroundColor = "transparent";
827
- }}
828
- >{d}</button>;
829
- })}</div>
830
- <div className="flex items-center justify-between px-3 py-1.5" style={{ borderTop: "1px solid var(--divider)" }}>
831
- <button
832
- onClick={() => {
833
- onSelect("");
834
- onClose();
835
- }}
836
- className="text-[10px] font-medium transition-colors"
837
- style={{ color: "var(--text-faint)" }}
838
- >Clear</button>
839
- <button
840
- onClick={() => {
841
- onSelect(todayStr);
842
- onClose();
843
- }}
844
- className="text-[10px] font-medium transition-colors"
845
- style={{ color: "#9b7bf7" }}
846
- >Today</button>
847
- </div>
848
- </div>;
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 <span className="relative inline-flex items-center">
867
- <span
868
- ref={chipRef}
869
- onClick={(e) => {
870
- e.preventDefault();
871
- e.stopPropagation();
872
- setShowPicker(!showPicker);
873
- }}
874
- 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"
875
- style={{ color: "#9b7bf7", backgroundColor: "rgba(155,123,247,0.06)", border: "1px solid rgba(155,123,247,0.15)" }}
876
- title="Click to change date (Ctrl+D to insert)"
877
- >
878
- <svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
879
- <rect x="3" y="4" width="18" height="18" rx="2" ry="2" strokeWidth={2} />
880
- <line x1="16" y1="2" x2="16" y2="6" strokeWidth={2} />
881
- <line x1="8" y1="2" x2="8" y2="6" strokeWidth={2} />
882
- <line x1="3" y1="10" x2="21" y2="10" strokeWidth={2} />
883
- </svg>
884
- {formatted}
885
- </span>
886
- {showPicker && <MiniCalendar
887
- selectedDate={d}
888
- onSelect={handleSelect}
889
- onClose={() => setShowPicker(false)}
890
- anchorEl={chipRef.current}
891
- />}
892
- </span>;
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) => <DateChip {...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
- "use client";
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) => <ImageRenderer {...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 <div
1039
- ref={blockRef}
1040
- className="blog-img-empty"
1041
- tabIndex={0}
1042
- onPaste={handlePaste}
1043
- onDrop={handleDrop}
1044
- onDragOver={(e) => {
1045
- e.preventDefault();
1046
- setIsDragOver(true);
1047
- }}
1048
- onDragLeave={() => setIsDragOver(false)}
1049
- data-drag-over={isDragOver}
1050
- >
1051
- <input
1052
- ref={fileInputRef}
1053
- type="file"
1054
- accept="image/*"
1055
- onChange={(e) => {
1056
- if (e.target.files?.[0])
1057
- uploadFile(e.target.files[0]);
1058
- e.target.value = "";
1059
- }}
1060
- style={{ display: "none" }}
1061
- />
1062
- {mode === "uploading" && <div className="blog-img-status">
1063
- <div className="blog-img-spinner" />
1064
- <span>{uploadStatus}</span>
1065
- </div>}
1066
- {mode === "idle" && <>
1067
- <div className="blog-img-actions-row">
1068
- <button className="blog-img-action" onClick={() => fileInputRef.current?.click()}>
1069
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
1070
- <path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" />
1071
- <polyline points="17 8 12 3 7 8" />
1072
- <line x1="12" y1="3" x2="12" y2="15" />
1073
- </svg>
1074
- {"Upload"}
1075
- </button>
1076
- <button className="blog-img-action" onClick={() => setMode("embed")}>
1077
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
1078
- <path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" />
1079
- <path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" />
1080
- </svg>
1081
- {"Embed URL"}
1082
- </button>
1083
- </div>
1084
- <p className="blog-img-hint">{"or drag & drop / paste an image"}</p>
1085
- </>}
1086
- {mode === "embed" && <div className="blog-img-input-row">
1087
- <input
1088
- ref={embedInputRef}
1089
- type="url"
1090
- value={embedUrl}
1091
- onChange={(e) => {
1092
- setEmbedUrl(e.target.value);
1093
- setEmbedError("");
1094
- }}
1095
- onKeyDown={(e) => {
1096
- if (e.key === "Enter")
1097
- handleEmbed();
1098
- if (e.key === "Escape") {
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
- placeholder="https://example.com/image.jpg"
1105
- className="blog-img-url-input"
1106
- />
1107
- <button className="blog-img-submit-btn" onClick={handleEmbed} disabled={!embedUrl.trim()}><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg></button>
1108
- <button className="blog-img-cancel-btn" onClick={() => {
1109
- setMode("idle");
1110
- setEmbedUrl("");
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 <div ref={blockRef} className="blog-img-loaded" tabIndex={0} onPaste={handlePaste}>
1121
- <div className="blog-img-wrapper">
1122
- <img src={url} alt={caption || "Image"} className="blog-img-main" draggable={false} />
1123
- <div className="blog-img-hover-overlay"><div className="blog-img-hover-actions">
1124
- <button className="blog-img-hover-btn" onClick={handleReplace}><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
1125
- <path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" />
1126
- <polyline points="17 8 12 3 7 8" />
1127
- <line x1="12" y1="3" x2="12" y2="15" />
1128
- </svg></button>
1129
- <button className="blog-img-hover-btn" onClick={() => setEditingCaption(true)}><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
1130
- <path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" />
1131
- <path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" />
1132
- </svg></button>
1133
- <button className="blog-img-hover-btn blog-img-hover-delete" onClick={handleDelete}><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
1134
- <polyline points="3 6 5 6 21 6" />
1135
- <path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" />
1136
- </svg></button>
1137
- </div></div>
1138
- </div>
1139
- {editingCaption ? <input
1140
- type="text"
1141
- value={captionText}
1142
- onChange={(e) => setCaptionText(e.target.value)}
1143
- onKeyDown={(e) => {
1144
- if (e.key === "Enter")
1145
- handleCaptionSave();
1146
- if (e.key === "Escape") {
1147
- setEditingCaption(false);
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
- onBlur={handleCaptionSave}
1152
- placeholder="Add a caption..."
1153
- className="blog-img-caption-input"
1154
- autoFocus
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
- "use client";
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 <div className="border border-[var(--border-default)] rounded-xl bg-[var(--bg-surface)] p-4 my-2 space-y-3">
1204
- <p className="text-[11px] text-[var(--text-muted)] font-medium">Button Block</p>
1205
- <input
1206
- type="text"
1207
- value={label}
1208
- onChange={(e) => setLabel(e.target.value)}
1209
- placeholder="Button label"
1210
- 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]"
1211
- />
1212
- <div className="flex gap-2">
1213
- <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">{BUTTON_ACTIONS.map((a) => <option key={a.value} value={a.value}>{a.label}</option>)}</select>
1214
- <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">{BUTTON_VARIANTS.map((v) => <option key={v.value} value={v.value}>{v.label}</option>)}</select>
1215
- </div>
1216
- {(action === "link" || action === "copy") && <input
1217
- type="text"
1218
- value={actionValue}
1219
- onChange={(e) => setActionValue(e.target.value)}
1220
- placeholder={action === "link" ? "https://..." : "Text to copy"}
1221
- 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]"
1222
- />}
1223
- <div className="flex justify-end gap-2">
1224
- <button onClick={() => setEditing(false)} className="px-3 py-1 text-[12px] text-[#888] hover:text-[var(--text-primary)] transition-colors">Cancel</button>
1225
- <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">Done</button>
1226
- </div>
1227
- </div>;
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 <div className="my-2" onDoubleClick={() => setEditing(true)}><button className={`px-5 py-2 rounded-lg text-[13px] font-medium transition-colors ${variantCls}`}>{label}</button></div>;
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
- "use client";
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 <div style={{
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
- <div style={{ display: "flex", alignItems: "center", gap: "8px", marginBottom: "12px" }}>
1287
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#9b7bf7" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
1288
- <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" />
1289
- <polyline points="14 2 14 8 20 8" />
1290
- <line x1="16" y1="13" x2="8" y2="13" />
1291
- <line x1="16" y1="17" x2="8" y2="17" />
1292
- <polyline points="10 9 9 9 8 9" />
1293
- </svg>
1294
- <span style={{ fontSize: "14px", fontWeight: 600, color: "var(--text-primary)" }}>Embed PDF</span>
1295
- </div>
1296
- <div style={{ display: "flex", gap: "8px" }}>
1297
- <input
1298
- type="text"
1299
- value={inputUrl}
1300
- onChange={(e) => setInputUrl(e.target.value)}
1301
- onKeyDown={(e) => e.key === "Enter" && handleSubmit()}
1302
- placeholder="Paste PDF link..."
1303
- style={{
1304
- flex: 1,
1305
- background: "var(--bg-app)",
1306
- color: "var(--text-primary)",
1307
- border: "1px solid #232d3f",
1308
- borderRadius: "8px",
1309
- padding: "8px 12px",
1310
- fontSize: "13px",
1311
- outline: "none"
1312
- }}
1313
- />
1314
- <button
1315
- onClick={handleSubmit}
1316
- disabled={!inputUrl.trim() || loading}
1317
- style={{
1318
- padding: "8px 16px",
1319
- background: "#9b7bf7",
1320
- color: "white",
1321
- border: "none",
1322
- borderRadius: "8px",
1323
- fontSize: "13px",
1324
- fontWeight: 600,
1325
- cursor: "pointer",
1326
- opacity: !inputUrl.trim() || loading ? 0.4 : 1
1327
- }}
1328
- >{loading ? "..." : "Embed"}</button>
1329
- </div>
1330
- </div>;
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 <div style={{
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
- <div style={{
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
- <iframe
1348
- src={`${url}#toolbar=0&navpanes=0&scrollbar=0&view=FitH`}
1349
- title={title || "PDF"}
1350
- style={{
1351
- width: "100%",
1352
- height: "100%",
1353
- border: "none",
1354
- pointerEvents: "none"
1355
- }}
1356
- />
1357
- <div style={{
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
- <div style={{
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
- }}>PDF</div>
1377
- </div>
1378
- <div style={{ flex: 1, padding: "16px", display: "flex", flexDirection: "column", justifyContent: "space-between" }}>
1379
- <div>
1380
- <div style={{ display: "flex", alignItems: "center", gap: "8px", marginBottom: "8px" }}>
1381
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#9b7bf7" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
1382
- <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" />
1383
- <polyline points="14 2 14 8 20 8" />
1384
- </svg>
1385
- <span style={{ fontSize: "14px", fontWeight: 600, color: "var(--text-primary)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{title || "Document"}</span>
1386
- </div>
1387
- <div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
1388
- {fileSize && <span style={{ fontSize: "12px", color: "var(--text-muted)", display: "flex", alignItems: "center", gap: "4px" }}>
1389
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3" /></svg>
1390
- {fileSize}
1391
- </span>}
1392
- {pageCount && <span style={{ fontSize: "12px", color: "var(--text-muted)", display: "flex", alignItems: "center", gap: "4px" }}>
1393
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
1394
- <path d="M4 19.5A2.5 2.5 0 016.5 17H20" />
1395
- <path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z" />
1396
- </svg>
1397
- {pageCount}
1398
- {" pages"}
1399
- </span>}
1400
- </div>
1401
- </div>
1402
- <div style={{ display: "flex", gap: "8px", marginTop: "12px" }}>
1403
- <a
1404
- href={url}
1405
- target="_blank"
1406
- rel="noopener noreferrer"
1407
- style={{
1408
- padding: "6px 12px",
1409
- background: "rgba(155,123,247,0.1)",
1410
- border: "1px solid rgba(155,123,247,0.25)",
1411
- borderRadius: "6px",
1412
- fontSize: "12px",
1413
- color: "#a78bfa",
1414
- fontWeight: 500,
1415
- textDecoration: "none",
1416
- cursor: "pointer"
1417
- }}
1418
- >Open PDF</a>
1419
- <button onClick={handleReplace} style={{
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
- }}>Replace</button>
1428
- <button onClick={handleDelete} style={{
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
- }}>Delete</button>
1437
- </div>
1438
- </div>
1439
- </div>;
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
- "use client";
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 <div
1537
- ref={tooltipRef}
1538
- className="link-preview-tooltip"
1539
- style={style}
1540
- onMouseEnter={onTooltipEnter}
1541
- onMouseLeave={onTooltipLeave}
1542
- >{loading ? <div className="link-preview-loading">
1543
- <div className="link-preview-skeleton" style={{ width: "60%", height: 12 }} />
1544
- <div className="link-preview-skeleton" style={{ width: "90%", height: 10, marginTop: 8 }} />
1545
- <div className="link-preview-skeleton" style={{ width: "40%", height: 10, marginTop: 4 }} />
1546
- </div> : data ? <a href={url} target="_blank" rel="noopener noreferrer" className="link-preview-card">
1547
- {data.image && <div className="link-preview-image"><img src={data.image} alt="" onError={(e) => {
1548
- e.target.style.display = "none";
1549
- }} /></div>}
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
- <span>{data.domain}</span>
1558
- </div>
1559
- </div>
1560
- </a> : null}</div>;
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
- "use client";
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
- blockSpecs.codeBlock = codeBlock;
1663
- if (f.equations)
1664
- blockSpecs.blockEquation = BlockEquation({});
1665
- if (f.mermaid)
1666
- blockSpecs.mermaidBlock = MermaidBlock({});
1667
- if (f.tableOfContents)
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
- inlineContentSpecs.inlineEquation = InlineEquation;
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: <span style={{ fontSize: 16 }}>{"\u2211"}</span>,
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: <span style={{ fontSize: 14 }}>{"\u25C7"}</span>,
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: <span style={{ fontSize: 14 }}>{"\u2630"}</span>,
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 <div className={`lix-editor-wrapper${""}`} ref={wrapperRef} style={{ position: "relative" }}>
1854
- <import_mantine.BlockNoteView
1855
- editor={editor}
1856
- onChange={handleChange}
1857
- theme={isDark ? "dark" : "light"}
1858
- slashMenu={false}
1859
- >
1860
- <import_react18.SuggestionMenuController triggerCharacter="/" getItems={getItems} />
1861
- <import_react18.TableHandlesController />
1862
- {children}
1863
- </import_mantine.BlockNoteView>
1864
- {f.linkPreview && editorLinkPreview.preview && <LinkPreviewTooltip
1865
- anchorEl={editorLinkPreview.preview.anchorEl}
1866
- url={editorLinkPreview.preview.url}
1867
- onClose={editorLinkPreview.hide}
1868
- />}
1869
- </div>;
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1901
- if (!text)
1902
- return "";
1947
+ if (!text) return "";
1903
1948
  const s = c.styles || {};
1904
- if (s.bold)
1905
- text = `<strong>${text}</strong>`;
1906
- if (s.italic)
1907
- text = `<em>${text}</em>`;
1908
- if (s.strike)
1909
- text = `<del>${text}</del>`;
1910
- if (s.code)
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
- cellContent = cell;
1990
- else if (cell?.content)
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
- "use client";
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
- return s.slice(2, -2).trim();
2095
- if (s.startsWith("$$") && s.endsWith("$$"))
2096
- return s.slice(2, -2).trim();
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 <div className={`lix-preview ${className}`}>
2253
- <div ref={contentRef} className="lix-preview-content" />
2254
- {f.linkPreview && linkPreview.preview && <LinkPreviewTooltip
2255
- anchorEl={linkPreview.preview.anchorEl}
2256
- url={linkPreview.preview.url}
2257
- onClose={linkPreview.hide}
2258
- />}
2259
- </div>;
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
- "use client";
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 <div className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/30 backdrop-blur-sm"><div
2331
- ref={ref}
2332
- className="w-full max-w-[520px] max-h-[80vh] rounded-2xl shadow-2xl overflow-hidden"
2333
- style={{ backgroundColor: "var(--card-bg)", border: "1px solid var(--border-default)", boxShadow: "var(--shadow-lg)" }}
2334
- >
2335
- <div className="flex items-center justify-between px-6 py-4" style={{ borderBottom: "1px solid var(--divider)" }}>
2336
- <div className="flex items-center gap-2.5">
2337
- <ion-icon name="keypad-outline" style={{ fontSize: "18px", color: "#9b7bf7" }} />
2338
- <h2 className="text-[15px] font-bold" style={{ color: "var(--text-primary)" }}>Keyboard Shortcuts</h2>
2339
- </div>
2340
- <button
2341
- onClick={onClose}
2342
- className="transition-colors p-1"
2343
- style={{ color: "var(--text-faint)" }}
2344
- ><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
2345
- <line x1="18" y1="6" x2="6" y2="18" />
2346
- <line x1="6" y1="6" x2="18" y2="18" />
2347
- </svg></button>
2348
- </div>
2349
- <div className="overflow-y-auto max-h-[calc(80vh-60px)] p-6 space-y-6 scrollbar-thin">{SHORTCUT_GROUPS.map((group) => <div key={group.title}>
2350
- <h3 className="text-[11px] font-semibold uppercase tracking-wider mb-3" style={{ color: "#9b7bf7" }}>{group.title}</h3>
2351
- <div className="space-y-1">{group.shortcuts.map((s, i) => <div key={i} className="flex items-center justify-between py-1.5">
2352
- <span className="text-[13px]" style={{ color: "var(--text-body)" }}>{s.desc}</span>
2353
- <div className="flex items-center gap-1">{s.keys.map((key, j) => <span key={j}>
2354
- {j > 0 && <span className="text-[10px] mx-0.5" style={{ color: "var(--text-faint)" }}>+</span>}
2355
- <kbd
2356
- className="inline-block min-w-[24px] text-center px-1.5 py-0.5 text-[11px] font-medium rounded-md"
2357
- style={{ color: "var(--text-secondary)", backgroundColor: "var(--bg-surface)", border: "1px solid var(--border-default)" }}
2358
- >{key}</kbd>
2359
- </span>)}</div>
2360
- </div>)}</div>
2361
- </div>)}</div>
2362
- </div></div>;
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