sketchboard-app 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,46 +1,167 @@
1
- # SketchBoard
1
+ <div align="center">
2
2
 
3
- A local-first whiteboard app. Run instantly with no setup required.
3
+ ```
4
+ ╔═══════════════════════════════════════════════════════╗
5
+ ║ ║
6
+ ║ ✏ S K E T C H B O A R D ║
7
+ ║ ║
8
+ ║ Draw · Save · Share · Collaborate ║
9
+ ║ ║
10
+ ╚═══════════════════════════════════════════════════════╝
11
+ ```
12
+
13
+ **A local-first whiteboard that lives on your machine.**
14
+ No account. No cloud. No setup. Just draw.
15
+
16
+ [![npm version](https://img.shields.io/npm/v/sketchboard-app?style=flat-square&color=0ea5e9&label=npm)](https://www.npmjs.com/package/sketchboard-app)
17
+ [![npm downloads](https://img.shields.io/npm/dt/sketchboard-app?style=flat-square&color=6366f1&label=installs)](https://www.npmjs.com/package/sketchboard-app)
18
+ [![License: MIT](https://img.shields.io/badge/License-MIT-22c55e?style=flat-square)](LICENSE)
19
+ [![Node.js](https://img.shields.io/badge/Node.js-18%2B-f97316?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org)
20
+
21
+ </div>
22
+
23
+ ---
24
+
25
+ ## Install & Run
4
26
 
5
- ## Quick Start
27
+ ### Run instantly (no install needed)
6
28
 
7
29
  ```bash
8
30
  npx sketchboard-app
9
31
  ```
10
32
 
11
- That's it. Your browser will open automatically at `http://localhost:4321`.
33
+ Your browser opens automatically at **http://localhost:4321**.
34
+
35
+ ---
36
+
37
+ ### Install globally (launch from anywhere, zero wait)
38
+
39
+ ```bash
40
+ npm install -g sketchboard-app
41
+ ```
42
+
43
+ Then just type:
44
+
45
+ ```bash
46
+ sketchboard
47
+ ```
48
+
49
+ ---
50
+
51
+ ### Uninstall
52
+
53
+ ```bash
54
+ npm uninstall -g sketchboard-app
55
+ ```
56
+
57
+ ---
12
58
 
13
59
  ## Features
14
60
 
15
- - **Zero setup** — no database, no config, no accounts needed
16
- - **Local-first** — all data stored on your machine in `~/.sketchboard`
17
- - **Offline capable** — works without internet once loaded
18
- - **Collaboration** — share drawings with others on the same network
19
- - **Export** — save your work as PNG, SVG, or JSON
61
+ - **Zero config** — one command, instant whiteboard
62
+ - **Saves to your machine** — drawings stored as JSON files in `~/.sketchboard/`
63
+ - **My Drawings sidebar** — browse, rename, load, and delete all your drawings
64
+ - **Ctrl+S** — save with unsaved-changes indicator in the toolbar
65
+ - **Share links** — generate a public read-only link for any drawing
66
+ - **Live collaboration** — real-time multi-user sessions over socket.io
67
+ - **Full export** — PNG, SVG, clipboard, or `.excalidraw` file
68
+ - **Light & dark theme** — auto-synced across the entire UI
69
+ - **Offline-capable** — works without internet once loaded
70
+ - **Cross-platform** — Windows, macOS, Linux
20
71
 
21
- ## Data Storage
72
+ ---
22
73
 
23
- All drawings are saved locally at:
74
+ ## Usage
24
75
 
25
- | OS | Path |
26
- |---|---|
27
- | Windows | `C:\Users\<you>\.sketchboard` |
28
- | macOS | `/Users/<you>/.sketchboard` |
29
- | Linux | `/home/<you>/.sketchboard` |
76
+ ```
77
+ ╔═══════════════════════════════════════╗
78
+ ║ SketchBoard ║
79
+ ╠═══════════════════════════════════════╣
80
+ ║ URL : http://localhost:4321 ║
81
+ ║ Data : ~/.sketchboard ║
82
+ ╚═══════════════════════════════════════╝
83
+ ```
30
84
 
31
- ## Configuration
85
+ ### Custom port
32
86
 
33
- | Env Variable | Default | Description |
34
- |---|---|---|
35
- | `PORT` | `4321` | Server port |
36
- | `SKETCHBOARD_DATA` | `~/.sketchboard` | Data directory |
87
+ ```bash
88
+ PORT=8888 npx sketchboard-app
89
+ # or with global install:
90
+ PORT=8888 sketchboard
91
+ ```
37
92
 
38
- Example:
93
+ ### Custom data directory
39
94
 
40
95
  ```bash
41
- PORT=5678 npx sketchboard-app
96
+ SKETCHBOARD_DATA=/path/to/my/drawings npx sketchboard-app
42
97
  ```
43
98
 
99
+ ### Environment variables
100
+
101
+ | Variable | Default | Description |
102
+ |---|---|---|
103
+ | `PORT` | `4321` | Port the server listens on |
104
+ | `SKETCHBOARD_DATA` | `~/.sketchboard` | Where drawings are stored |
105
+
106
+ ---
107
+
108
+ ## Where your data lives
109
+
110
+ ```
111
+ ~/.sketchboard/
112
+ drawings/
113
+ <uuid>.json ← one file per drawing (permanent)
114
+ library.json ← your saved shape library
115
+ collab/ ← live collaboration room scenes
116
+ collab-files/ ← collaboration image files
117
+ ```
118
+
119
+ | OS | Path |
120
+ |---|---|
121
+ | Windows | `C:\Users\<you>\.sketchboard\` |
122
+ | macOS | `/Users/<you>/.sketchboard/` |
123
+ | Linux | `/home/<you>/.sketchboard/` |
124
+
125
+ Plain JSON files — easy to back up, move, or sync with any tool.
126
+
127
+ ---
128
+
129
+ ## Keyboard shortcuts
130
+
131
+ | Shortcut | Action |
132
+ |---|---|
133
+ | `Ctrl+S` / `Cmd+S` | Save current drawing |
134
+ | `Ctrl+Z` | Undo |
135
+ | `Ctrl+Shift+Z` | Redo |
136
+ | `V` | Selection tool |
137
+ | `R` | Rectangle |
138
+ | `E` | Ellipse |
139
+ | `A` | Arrow |
140
+ | `T` | Text |
141
+ | `P` | Pencil / freehand |
142
+ | `Delete` | Delete selected |
143
+
144
+ ---
145
+
146
+ ## Troubleshooting
147
+
148
+ | Problem | Fix |
149
+ |---|---|
150
+ | Port 4321 already in use | `PORT=5678 npx sketchboard-app` |
151
+ | Browser does not open | Manually visit `http://localhost:4321` |
152
+ | Old version cached by npx | `npx --yes sketchboard-app@latest` |
153
+ | `EACCES` error on Linux/Mac | `sudo npm install -g sketchboard-app` |
154
+ | Drawings not saving | Check `~/.sketchboard/drawings/` is writable |
155
+
156
+ ---
157
+
158
+ ## Credits
159
+
160
+ Built on top of **[Excalidraw](https://github.com/excalidraw/excalidraw)** — the excellent open-source hand-drawn whiteboard (MIT licensed).
161
+ SketchBoard adds local persistence, drawing management, and the npm package layer.
162
+
163
+ ---
164
+
44
165
  ## License
45
166
 
46
167
  MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sketchboard-app",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "SketchBoard — local-first whiteboard app. Run with: npx sketchboard-app",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -1,2 +1,2 @@
1
- import{r as o,j as L}from"./index-DPcDil7M.js";import{S as R,C,E as n,a as x,k as y,h as D,l as S,d as T,p as H,r as N,b as j,c as z,s as w,D as g,H as E,t as r}from"./codemirror.chunk-CLhMQAUm.js";import"./mermaid-to-excalidraw-D-aVQaad.js";const G=R.define({token(e){return e.match(/^%%.*$/)?"comment":e.match(/^"(?:[^"\\]|\\.)*"/)?"string":e.match(/^(flowchart|graph|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt|pie|mindmap|journey|gitGraph|timeline|quadrantChart|sankey|xychart)\b/i)||e.match(/^(TB|TD|BT|RL|LR)\b/)||e.match(/^(subgraph|end|participant|actor|loop|alt|else|opt|par|critical|break|rect|note|over|activate|deactivate|title|section|class|style|linkStyle|classDef|click)\b/i)?"keyword":e.match(/^[-.=<>|ox]+>/)||e.match(/^<[-.=<>|ox]+/)||e.match(/^--+|\.\.+|==+/)?"operator":e.match(/^[[\](){}|<>]/)?"bracket":e.match(/^[A-Za-z_][A-Za-z0-9_]*/)?"variableName":e.match(/^\d+(\.\d+)?/)?"number":e.match(/^[,:;]/)?"punctuation":(e.eatSpace()||e.next(),null)}});function M(){return G}const q=n.theme({"&":{backgroundColor:"#1e1e1e",color:"#d4d4d4"},".cm-content":{caretColor:"#fff"},".cm-cursor":{borderLeftColor:"#fff"},".cm-gutters":{backgroundColor:"#1e1e1e",color:"#858585",border:"none"},".cm-activeLineGutter":{backgroundColor:"#2a2a2a"},".cm-activeLine":{backgroundColor:"#2a2a2a"},".cm-errorLine":{backgroundColor:"rgba(255, 0, 0, 0.15)"}},{dark:!0}),A=E.define([{tag:r.keyword,color:"#569cd6"},{tag:r.string,color:"#ce9178"},{tag:r.comment,color:"#6a9955"},{tag:r.number,color:"#b5cea8"},{tag:r.operator,color:"#d4d4d4"},{tag:r.punctuation,color:"#d4d4d4"},{tag:r.variableName,color:"#9cdcfe"},{tag:r.bracket,color:"#ffd700"}]),B=n.theme({"&":{backgroundColor:"#ffffff",color:"#1e1e1e"},".cm-content":{caretColor:"#000"},".cm-cursor":{borderLeftColor:"#000"},".cm-gutters":{backgroundColor:"#fff",color:"#999",border:"none"},".cm-activeLineGutter":{backgroundColor:"#e8e8e8"},".cm-activeLine":{backgroundColor:"#e8e8e8"},".cm-errorLine":{backgroundColor:"rgba(255, 0, 0, 0.1)"}}),Z=E.define([{tag:r.keyword,color:"#0000ff"},{tag:r.string,color:"#a31515"},{tag:r.comment,color:"#008000"},{tag:r.number,color:"#098658"},{tag:r.operator,color:"#1e1e1e"},{tag:r.punctuation,color:"#1e1e1e"},{tag:r.variableName,color:"#001080"},{tag:r.bracket,color:"#af00db"}]),_=g.line({class:"cm-errorLine"}),P=(e,c)=>{if(!e||e<1||e>c.lines)return n.decorations.of(g.none);const s=c.line(e);return n.decorations.of(g.set([_.range(s.from)]))},v=e=>e==="dark"?[q,w(A)]:[B,w(Z)],I=({value:e,onChange:c,onKeyboardSubmit:s,placeholder:m,theme:l,errorLine:h})=>{const d=o.useRef(null),i=o.useRef(null),p=o.useRef(c),f=o.useRef(s),k=o.useRef(new C),b=o.useRef(new C);return p.current=c,f.current=s,o.useEffect(()=>{if(!d.current)return;const t=k.current,a=new n({state:x.create({doc:e,extensions:[y.of([{key:"Mod-Enter",run:()=>{var u;return(u=f.current)==null||u.call(f),!0}},{key:"Mod-Shift-z",run:N,preventDefault:!0}]),n.updateListener.of(u=>{u.docChanged&&p.current(u.state.doc.toString())}),D(),y.of([...j,...z]),S(),n.lineWrapping,t.of(v(l)),b.current.of([]),M(),T({drawRangeCursor:!0}),...m?[H(m)]:[]]}),parent:d.current});return i.current=a,a.focus(),()=>{a.destroy(),i.current=null}},[]),o.useEffect(()=>{const t=i.current;t&&t.dispatch({effects:k.current.reconfigure(v(l))})},[l]),o.useEffect(()=>{const t=i.current;t&&t.dispatch({effects:b.current.reconfigure(P(h,t.state.doc))})},[h]),o.useEffect(()=>{const t=i.current;if(!t)return;const a=t.state.doc.toString();e!==a&&t.dispatch({changes:{from:0,to:a.length,insert:e}})},[e]),L("div",{ref:d,className:"ttd-dialog-input ttd-dialog-input--codemirror"})};export{I as default};
2
- //# sourceMappingURL=CodeMirrorEditor-DLdTFwmz.js.map
1
+ import{r as o,j as L}from"./index-6ESeQJx8.js";import{S as R,C,E as n,a as x,k as y,h as D,l as S,d as T,p as H,r as N,b as j,c as z,s as w,D as g,H as E,t as r}from"./codemirror.chunk-CLhMQAUm.js";import"./mermaid-to-excalidraw-D-aVQaad.js";const G=R.define({token(e){return e.match(/^%%.*$/)?"comment":e.match(/^"(?:[^"\\]|\\.)*"/)?"string":e.match(/^(flowchart|graph|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt|pie|mindmap|journey|gitGraph|timeline|quadrantChart|sankey|xychart)\b/i)||e.match(/^(TB|TD|BT|RL|LR)\b/)||e.match(/^(subgraph|end|participant|actor|loop|alt|else|opt|par|critical|break|rect|note|over|activate|deactivate|title|section|class|style|linkStyle|classDef|click)\b/i)?"keyword":e.match(/^[-.=<>|ox]+>/)||e.match(/^<[-.=<>|ox]+/)||e.match(/^--+|\.\.+|==+/)?"operator":e.match(/^[[\](){}|<>]/)?"bracket":e.match(/^[A-Za-z_][A-Za-z0-9_]*/)?"variableName":e.match(/^\d+(\.\d+)?/)?"number":e.match(/^[,:;]/)?"punctuation":(e.eatSpace()||e.next(),null)}});function M(){return G}const q=n.theme({"&":{backgroundColor:"#1e1e1e",color:"#d4d4d4"},".cm-content":{caretColor:"#fff"},".cm-cursor":{borderLeftColor:"#fff"},".cm-gutters":{backgroundColor:"#1e1e1e",color:"#858585",border:"none"},".cm-activeLineGutter":{backgroundColor:"#2a2a2a"},".cm-activeLine":{backgroundColor:"#2a2a2a"},".cm-errorLine":{backgroundColor:"rgba(255, 0, 0, 0.15)"}},{dark:!0}),A=E.define([{tag:r.keyword,color:"#569cd6"},{tag:r.string,color:"#ce9178"},{tag:r.comment,color:"#6a9955"},{tag:r.number,color:"#b5cea8"},{tag:r.operator,color:"#d4d4d4"},{tag:r.punctuation,color:"#d4d4d4"},{tag:r.variableName,color:"#9cdcfe"},{tag:r.bracket,color:"#ffd700"}]),B=n.theme({"&":{backgroundColor:"#ffffff",color:"#1e1e1e"},".cm-content":{caretColor:"#000"},".cm-cursor":{borderLeftColor:"#000"},".cm-gutters":{backgroundColor:"#fff",color:"#999",border:"none"},".cm-activeLineGutter":{backgroundColor:"#e8e8e8"},".cm-activeLine":{backgroundColor:"#e8e8e8"},".cm-errorLine":{backgroundColor:"rgba(255, 0, 0, 0.1)"}}),Z=E.define([{tag:r.keyword,color:"#0000ff"},{tag:r.string,color:"#a31515"},{tag:r.comment,color:"#008000"},{tag:r.number,color:"#098658"},{tag:r.operator,color:"#1e1e1e"},{tag:r.punctuation,color:"#1e1e1e"},{tag:r.variableName,color:"#001080"},{tag:r.bracket,color:"#af00db"}]),_=g.line({class:"cm-errorLine"}),P=(e,c)=>{if(!e||e<1||e>c.lines)return n.decorations.of(g.none);const s=c.line(e);return n.decorations.of(g.set([_.range(s.from)]))},v=e=>e==="dark"?[q,w(A)]:[B,w(Z)],I=({value:e,onChange:c,onKeyboardSubmit:s,placeholder:m,theme:l,errorLine:h})=>{const d=o.useRef(null),i=o.useRef(null),p=o.useRef(c),f=o.useRef(s),k=o.useRef(new C),b=o.useRef(new C);return p.current=c,f.current=s,o.useEffect(()=>{if(!d.current)return;const t=k.current,a=new n({state:x.create({doc:e,extensions:[y.of([{key:"Mod-Enter",run:()=>{var u;return(u=f.current)==null||u.call(f),!0}},{key:"Mod-Shift-z",run:N,preventDefault:!0}]),n.updateListener.of(u=>{u.docChanged&&p.current(u.state.doc.toString())}),D(),y.of([...j,...z]),S(),n.lineWrapping,t.of(v(l)),b.current.of([]),M(),T({drawRangeCursor:!0}),...m?[H(m)]:[]]}),parent:d.current});return i.current=a,a.focus(),()=>{a.destroy(),i.current=null}},[]),o.useEffect(()=>{const t=i.current;t&&t.dispatch({effects:k.current.reconfigure(v(l))})},[l]),o.useEffect(()=>{const t=i.current;t&&t.dispatch({effects:b.current.reconfigure(P(h,t.state.doc))})},[h]),o.useEffect(()=>{const t=i.current;if(!t)return;const a=t.state.doc.toString();e!==a&&t.dispatch({changes:{from:0,to:a.length,insert:e}})},[e]),L("div",{ref:d,className:"ttd-dialog-input ttd-dialog-input--codemirror"})};export{I as default};
2
+ //# sourceMappingURL=CodeMirrorEditor-CuIBSOZ0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CodeMirrorEditor-DLdTFwmz.js","sources":["../../../packages/excalidraw/components/TTDDialog/mermaid-lang-lite.ts","../../../packages/excalidraw/components/TTDDialog/CodeMirrorEditor.tsx"],"sourcesContent":["import { StreamLanguage } from \"@codemirror/language\";\n\nconst mermaidStreamParser = StreamLanguage.define({\n token(stream) {\n // Comments: %%...\n if (stream.match(/^%%.*$/)) {\n return \"comment\";\n }\n\n // Strings\n if (stream.match(/^\"(?:[^\"\\\\]|\\\\.)*\"/)) {\n return \"string\";\n }\n\n // Diagram type keywords (at start of line or after whitespace)\n if (\n stream.match(\n /^(flowchart|graph|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt|pie|mindmap|journey|gitGraph|timeline|quadrantChart|sankey|xychart)\\b/i,\n )\n ) {\n return \"keyword\";\n }\n\n // Direction keywords\n if (stream.match(/^(TB|TD|BT|RL|LR)\\b/)) {\n return \"keyword\";\n }\n\n // Keywords\n if (\n stream.match(\n /^(subgraph|end|participant|actor|loop|alt|else|opt|par|critical|break|rect|note|over|activate|deactivate|title|section|class|style|linkStyle|classDef|click)\\b/i,\n )\n ) {\n return \"keyword\";\n }\n\n // Arrows: -->, ---, -.->, ===>, etc.\n if (stream.match(/^[-.=<>|ox]+>/)) {\n return \"operator\";\n }\n if (stream.match(/^<[-.=<>|ox]+/)) {\n return \"operator\";\n }\n if (stream.match(/^--+|\\.\\.+|==+/)) {\n return \"operator\";\n }\n\n // Labels in brackets/parens: [text], (text), {text}, ((text)), etc.\n if (stream.match(/^[[\\](){}|<>]/)) {\n return \"bracket\";\n }\n\n // Node IDs (alphanumeric)\n if (stream.match(/^[A-Za-z_][A-Za-z0-9_]*/)) {\n return \"variableName\";\n }\n\n // Numbers\n if (stream.match(/^\\d+(\\.\\d+)?/)) {\n return \"number\";\n }\n\n // Punctuation\n if (stream.match(/^[,:;]/)) {\n return \"punctuation\";\n }\n\n // Skip whitespace\n if (stream.eatSpace()) {\n return null;\n }\n\n // Skip any other character\n stream.next();\n return null;\n },\n});\n\nexport function mermaidLite() {\n return mermaidStreamParser;\n}\n","import { useEffect, useRef } from \"react\";\nimport {\n Decoration,\n EditorView,\n keymap,\n lineNumbers,\n placeholder as cmPlaceholder,\n drawSelection,\n} from \"@codemirror/view\";\nimport { Compartment, EditorState, type Extension } from \"@codemirror/state\";\nimport {\n defaultKeymap,\n history,\n historyKeymap,\n redo,\n} from \"@codemirror/commands\";\nimport { syntaxHighlighting, HighlightStyle } from \"@codemirror/language\";\nimport { tags } from \"@lezer/highlight\";\n\nimport type { Theme } from \"@excalidraw/element/types\";\n\nimport { mermaidLite } from \"./mermaid-lang-lite\";\n\nexport interface CodeMirrorEditorProps {\n value: string;\n onChange: (value: string) => void;\n onKeyboardSubmit?: () => void;\n placeholder?: string;\n theme: Theme;\n errorLine?: number | null;\n}\n\n// ---- Dark theme ----\n\nconst darkTheme = EditorView.theme(\n {\n \"&\": {\n backgroundColor: \"#1e1e1e\",\n color: \"#d4d4d4\",\n },\n \".cm-content\": { caretColor: \"#fff\" },\n \".cm-cursor\": { borderLeftColor: \"#fff\" },\n \".cm-gutters\": {\n backgroundColor: \"#1e1e1e\",\n color: \"#858585\",\n border: \"none\",\n },\n \".cm-activeLineGutter\": { backgroundColor: \"#2a2a2a\" },\n \".cm-activeLine\": { backgroundColor: \"#2a2a2a\" },\n \".cm-errorLine\": { backgroundColor: \"rgba(255, 0, 0, 0.15)\" },\n },\n { dark: true },\n);\n\nconst darkHighlight = HighlightStyle.define([\n { tag: tags.keyword, color: \"#569cd6\" },\n { tag: tags.string, color: \"#ce9178\" },\n { tag: tags.comment, color: \"#6a9955\" },\n { tag: tags.number, color: \"#b5cea8\" },\n { tag: tags.operator, color: \"#d4d4d4\" },\n { tag: tags.punctuation, color: \"#d4d4d4\" },\n { tag: tags.variableName, color: \"#9cdcfe\" },\n { tag: tags.bracket, color: \"#ffd700\" },\n]);\n\n// ---- Light theme ----\n\nconst lightTheme = EditorView.theme({\n \"&\": {\n backgroundColor: \"#ffffff\",\n color: \"#1e1e1e\",\n },\n \".cm-content\": { caretColor: \"#000\" },\n \".cm-cursor\": { borderLeftColor: \"#000\" },\n \".cm-gutters\": {\n backgroundColor: \"#fff\",\n color: \"#999\",\n border: \"none\",\n },\n \".cm-activeLineGutter\": { backgroundColor: \"#e8e8e8\" },\n \".cm-activeLine\": { backgroundColor: \"#e8e8e8\" },\n \".cm-errorLine\": { backgroundColor: \"rgba(255, 0, 0, 0.1)\" },\n});\n\nconst lightHighlight = HighlightStyle.define([\n { tag: tags.keyword, color: \"#0000ff\" },\n { tag: tags.string, color: \"#a31515\" },\n { tag: tags.comment, color: \"#008000\" },\n { tag: tags.number, color: \"#098658\" },\n { tag: tags.operator, color: \"#1e1e1e\" },\n { tag: tags.punctuation, color: \"#1e1e1e\" },\n { tag: tags.variableName, color: \"#001080\" },\n { tag: tags.bracket, color: \"#af00db\" },\n]);\n\n// ---- Error line decoration ----\n\nconst errorLineDeco = Decoration.line({ class: \"cm-errorLine\" });\n\nconst getErrorLineExtension = (\n errorLine: number | null | undefined,\n doc: { line(n: number): { from: number }; lines: number },\n): Extension => {\n if (!errorLine || errorLine < 1 || errorLine > doc.lines) {\n return EditorView.decorations.of(Decoration.none);\n }\n const line = doc.line(errorLine);\n return EditorView.decorations.of(\n Decoration.set([errorLineDeco.range(line.from)]),\n );\n};\n\n// ---- Helpers ----\n\nconst getThemeExtensions = (theme: Theme) => {\n if (theme === \"dark\") {\n return [darkTheme, syntaxHighlighting(darkHighlight)];\n }\n return [lightTheme, syntaxHighlighting(lightHighlight)];\n};\n\nconst CodeMirrorEditor = ({\n value,\n onChange,\n onKeyboardSubmit,\n placeholder,\n theme,\n errorLine,\n}: CodeMirrorEditorProps) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<EditorView | null>(null);\n const onChangeRef = useRef(onChange);\n const onKeyboardSubmitRef = useRef(onKeyboardSubmit);\n const themeCompartmentRef = useRef(new Compartment());\n const errorLineCompartmentRef = useRef(new Compartment());\n\n onChangeRef.current = onChange;\n onKeyboardSubmitRef.current = onKeyboardSubmit;\n\n useEffect(() => {\n if (!containerRef.current) {\n return;\n }\n\n const themeCompartment = themeCompartmentRef.current;\n\n const view = new EditorView({\n state: EditorState.create({\n doc: value,\n extensions: [\n keymap.of([\n {\n key: \"Mod-Enter\",\n run: () => {\n onKeyboardSubmitRef.current?.();\n return true;\n },\n },\n // historyKeymap binds Mod-Shift-z only on Mac; add it for all platforms\n { key: \"Mod-Shift-z\", run: redo, preventDefault: true },\n ]),\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n onChangeRef.current(update.state.doc.toString());\n }\n }),\n history(),\n keymap.of([...defaultKeymap, ...historyKeymap]),\n lineNumbers(),\n EditorView.lineWrapping,\n themeCompartment.of(getThemeExtensions(theme)),\n errorLineCompartmentRef.current.of([]),\n mermaidLite(),\n drawSelection({ drawRangeCursor: true }),\n ...(placeholder ? [cmPlaceholder(placeholder)] : []),\n ],\n }),\n parent: containerRef.current,\n });\n\n viewRef.current = view;\n view.focus();\n\n return () => {\n view.destroy();\n viewRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Swap theme dynamically via compartment\n useEffect(() => {\n const view = viewRef.current;\n if (!view) {\n return;\n }\n view.dispatch({\n effects: themeCompartmentRef.current.reconfigure(\n getThemeExtensions(theme),\n ),\n });\n }, [theme]);\n\n // Update error line highlight\n useEffect(() => {\n const view = viewRef.current;\n if (!view) {\n return;\n }\n view.dispatch({\n effects: errorLineCompartmentRef.current.reconfigure(\n getErrorLineExtension(errorLine, view.state.doc),\n ),\n });\n }, [errorLine]);\n\n // Sync external value changes into EditorView\n useEffect(() => {\n const view = viewRef.current;\n if (!view) {\n return;\n }\n const currentDoc = view.state.doc.toString();\n if (value !== currentDoc) {\n view.dispatch({\n changes: { from: 0, to: currentDoc.length, insert: value },\n });\n }\n }, [value]);\n\n return (\n <div\n ref={containerRef}\n className=\"ttd-dialog-input ttd-dialog-input--codemirror\"\n />\n );\n};\n\nexport default CodeMirrorEditor;\n"],"names":["mermaidStreamParser","StreamLanguage","stream","mermaidLite","darkTheme","EditorView","darkHighlight","HighlightStyle","tags","lightTheme","lightHighlight","errorLineDeco","Decoration","getErrorLineExtension","errorLine","doc","line","getThemeExtensions","theme","syntaxHighlighting","CodeMirrorEditor","value","onChange","onKeyboardSubmit","placeholder","containerRef","useRef","viewRef","onChangeRef","onKeyboardSubmitRef","themeCompartmentRef","Compartment","errorLineCompartmentRef","useEffect","themeCompartment","view","EditorState","keymap","_a","redo","update","history","defaultKeymap","historyKeymap","lineNumbers","drawSelection","cmPlaceholder","currentDoc","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"CodeMirrorEditor-CuIBSOZ0.js","sources":["../../../packages/excalidraw/components/TTDDialog/mermaid-lang-lite.ts","../../../packages/excalidraw/components/TTDDialog/CodeMirrorEditor.tsx"],"sourcesContent":["import { StreamLanguage } from \"@codemirror/language\";\n\nconst mermaidStreamParser = StreamLanguage.define({\n token(stream) {\n // Comments: %%...\n if (stream.match(/^%%.*$/)) {\n return \"comment\";\n }\n\n // Strings\n if (stream.match(/^\"(?:[^\"\\\\]|\\\\.)*\"/)) {\n return \"string\";\n }\n\n // Diagram type keywords (at start of line or after whitespace)\n if (\n stream.match(\n /^(flowchart|graph|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt|pie|mindmap|journey|gitGraph|timeline|quadrantChart|sankey|xychart)\\b/i,\n )\n ) {\n return \"keyword\";\n }\n\n // Direction keywords\n if (stream.match(/^(TB|TD|BT|RL|LR)\\b/)) {\n return \"keyword\";\n }\n\n // Keywords\n if (\n stream.match(\n /^(subgraph|end|participant|actor|loop|alt|else|opt|par|critical|break|rect|note|over|activate|deactivate|title|section|class|style|linkStyle|classDef|click)\\b/i,\n )\n ) {\n return \"keyword\";\n }\n\n // Arrows: -->, ---, -.->, ===>, etc.\n if (stream.match(/^[-.=<>|ox]+>/)) {\n return \"operator\";\n }\n if (stream.match(/^<[-.=<>|ox]+/)) {\n return \"operator\";\n }\n if (stream.match(/^--+|\\.\\.+|==+/)) {\n return \"operator\";\n }\n\n // Labels in brackets/parens: [text], (text), {text}, ((text)), etc.\n if (stream.match(/^[[\\](){}|<>]/)) {\n return \"bracket\";\n }\n\n // Node IDs (alphanumeric)\n if (stream.match(/^[A-Za-z_][A-Za-z0-9_]*/)) {\n return \"variableName\";\n }\n\n // Numbers\n if (stream.match(/^\\d+(\\.\\d+)?/)) {\n return \"number\";\n }\n\n // Punctuation\n if (stream.match(/^[,:;]/)) {\n return \"punctuation\";\n }\n\n // Skip whitespace\n if (stream.eatSpace()) {\n return null;\n }\n\n // Skip any other character\n stream.next();\n return null;\n },\n});\n\nexport function mermaidLite() {\n return mermaidStreamParser;\n}\n","import { useEffect, useRef } from \"react\";\nimport {\n Decoration,\n EditorView,\n keymap,\n lineNumbers,\n placeholder as cmPlaceholder,\n drawSelection,\n} from \"@codemirror/view\";\nimport { Compartment, EditorState, type Extension } from \"@codemirror/state\";\nimport {\n defaultKeymap,\n history,\n historyKeymap,\n redo,\n} from \"@codemirror/commands\";\nimport { syntaxHighlighting, HighlightStyle } from \"@codemirror/language\";\nimport { tags } from \"@lezer/highlight\";\n\nimport type { Theme } from \"@excalidraw/element/types\";\n\nimport { mermaidLite } from \"./mermaid-lang-lite\";\n\nexport interface CodeMirrorEditorProps {\n value: string;\n onChange: (value: string) => void;\n onKeyboardSubmit?: () => void;\n placeholder?: string;\n theme: Theme;\n errorLine?: number | null;\n}\n\n// ---- Dark theme ----\n\nconst darkTheme = EditorView.theme(\n {\n \"&\": {\n backgroundColor: \"#1e1e1e\",\n color: \"#d4d4d4\",\n },\n \".cm-content\": { caretColor: \"#fff\" },\n \".cm-cursor\": { borderLeftColor: \"#fff\" },\n \".cm-gutters\": {\n backgroundColor: \"#1e1e1e\",\n color: \"#858585\",\n border: \"none\",\n },\n \".cm-activeLineGutter\": { backgroundColor: \"#2a2a2a\" },\n \".cm-activeLine\": { backgroundColor: \"#2a2a2a\" },\n \".cm-errorLine\": { backgroundColor: \"rgba(255, 0, 0, 0.15)\" },\n },\n { dark: true },\n);\n\nconst darkHighlight = HighlightStyle.define([\n { tag: tags.keyword, color: \"#569cd6\" },\n { tag: tags.string, color: \"#ce9178\" },\n { tag: tags.comment, color: \"#6a9955\" },\n { tag: tags.number, color: \"#b5cea8\" },\n { tag: tags.operator, color: \"#d4d4d4\" },\n { tag: tags.punctuation, color: \"#d4d4d4\" },\n { tag: tags.variableName, color: \"#9cdcfe\" },\n { tag: tags.bracket, color: \"#ffd700\" },\n]);\n\n// ---- Light theme ----\n\nconst lightTheme = EditorView.theme({\n \"&\": {\n backgroundColor: \"#ffffff\",\n color: \"#1e1e1e\",\n },\n \".cm-content\": { caretColor: \"#000\" },\n \".cm-cursor\": { borderLeftColor: \"#000\" },\n \".cm-gutters\": {\n backgroundColor: \"#fff\",\n color: \"#999\",\n border: \"none\",\n },\n \".cm-activeLineGutter\": { backgroundColor: \"#e8e8e8\" },\n \".cm-activeLine\": { backgroundColor: \"#e8e8e8\" },\n \".cm-errorLine\": { backgroundColor: \"rgba(255, 0, 0, 0.1)\" },\n});\n\nconst lightHighlight = HighlightStyle.define([\n { tag: tags.keyword, color: \"#0000ff\" },\n { tag: tags.string, color: \"#a31515\" },\n { tag: tags.comment, color: \"#008000\" },\n { tag: tags.number, color: \"#098658\" },\n { tag: tags.operator, color: \"#1e1e1e\" },\n { tag: tags.punctuation, color: \"#1e1e1e\" },\n { tag: tags.variableName, color: \"#001080\" },\n { tag: tags.bracket, color: \"#af00db\" },\n]);\n\n// ---- Error line decoration ----\n\nconst errorLineDeco = Decoration.line({ class: \"cm-errorLine\" });\n\nconst getErrorLineExtension = (\n errorLine: number | null | undefined,\n doc: { line(n: number): { from: number }; lines: number },\n): Extension => {\n if (!errorLine || errorLine < 1 || errorLine > doc.lines) {\n return EditorView.decorations.of(Decoration.none);\n }\n const line = doc.line(errorLine);\n return EditorView.decorations.of(\n Decoration.set([errorLineDeco.range(line.from)]),\n );\n};\n\n// ---- Helpers ----\n\nconst getThemeExtensions = (theme: Theme) => {\n if (theme === \"dark\") {\n return [darkTheme, syntaxHighlighting(darkHighlight)];\n }\n return [lightTheme, syntaxHighlighting(lightHighlight)];\n};\n\nconst CodeMirrorEditor = ({\n value,\n onChange,\n onKeyboardSubmit,\n placeholder,\n theme,\n errorLine,\n}: CodeMirrorEditorProps) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<EditorView | null>(null);\n const onChangeRef = useRef(onChange);\n const onKeyboardSubmitRef = useRef(onKeyboardSubmit);\n const themeCompartmentRef = useRef(new Compartment());\n const errorLineCompartmentRef = useRef(new Compartment());\n\n onChangeRef.current = onChange;\n onKeyboardSubmitRef.current = onKeyboardSubmit;\n\n useEffect(() => {\n if (!containerRef.current) {\n return;\n }\n\n const themeCompartment = themeCompartmentRef.current;\n\n const view = new EditorView({\n state: EditorState.create({\n doc: value,\n extensions: [\n keymap.of([\n {\n key: \"Mod-Enter\",\n run: () => {\n onKeyboardSubmitRef.current?.();\n return true;\n },\n },\n // historyKeymap binds Mod-Shift-z only on Mac; add it for all platforms\n { key: \"Mod-Shift-z\", run: redo, preventDefault: true },\n ]),\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n onChangeRef.current(update.state.doc.toString());\n }\n }),\n history(),\n keymap.of([...defaultKeymap, ...historyKeymap]),\n lineNumbers(),\n EditorView.lineWrapping,\n themeCompartment.of(getThemeExtensions(theme)),\n errorLineCompartmentRef.current.of([]),\n mermaidLite(),\n drawSelection({ drawRangeCursor: true }),\n ...(placeholder ? [cmPlaceholder(placeholder)] : []),\n ],\n }),\n parent: containerRef.current,\n });\n\n viewRef.current = view;\n view.focus();\n\n return () => {\n view.destroy();\n viewRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Swap theme dynamically via compartment\n useEffect(() => {\n const view = viewRef.current;\n if (!view) {\n return;\n }\n view.dispatch({\n effects: themeCompartmentRef.current.reconfigure(\n getThemeExtensions(theme),\n ),\n });\n }, [theme]);\n\n // Update error line highlight\n useEffect(() => {\n const view = viewRef.current;\n if (!view) {\n return;\n }\n view.dispatch({\n effects: errorLineCompartmentRef.current.reconfigure(\n getErrorLineExtension(errorLine, view.state.doc),\n ),\n });\n }, [errorLine]);\n\n // Sync external value changes into EditorView\n useEffect(() => {\n const view = viewRef.current;\n if (!view) {\n return;\n }\n const currentDoc = view.state.doc.toString();\n if (value !== currentDoc) {\n view.dispatch({\n changes: { from: 0, to: currentDoc.length, insert: value },\n });\n }\n }, [value]);\n\n return (\n <div\n ref={containerRef}\n className=\"ttd-dialog-input ttd-dialog-input--codemirror\"\n />\n );\n};\n\nexport default CodeMirrorEditor;\n"],"names":["mermaidStreamParser","StreamLanguage","stream","mermaidLite","darkTheme","EditorView","darkHighlight","HighlightStyle","tags","lightTheme","lightHighlight","errorLineDeco","Decoration","getErrorLineExtension","errorLine","doc","line","getThemeExtensions","theme","syntaxHighlighting","CodeMirrorEditor","value","onChange","onKeyboardSubmit","placeholder","containerRef","useRef","viewRef","onChangeRef","onKeyboardSubmitRef","themeCompartmentRef","Compartment","errorLineCompartmentRef","useEffect","themeCompartment","view","EditorState","keymap","_a","redo","update","history","defaultKeymap","historyKeymap","lineNumbers","drawSelection","cmPlaceholder","currentDoc","jsx"],"mappings":"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"}