@xom11/whiteboard 0.24.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +84 -11
  2. package/dist/{ExcalidrawWithMenus-WENZRYYE.mjs → ExcalidrawWithMenus-2QPPTXJM.mjs} +3 -2
  3. package/dist/ExcalidrawWithMenus-2QPPTXJM.mjs.map +1 -0
  4. package/dist/ai.d.mts +3217 -434
  5. package/dist/ai.d.ts +3217 -434
  6. package/dist/ai.js +7679 -598
  7. package/dist/ai.js.map +1 -1
  8. package/dist/ai.mjs +5707 -679
  9. package/dist/ai.mjs.map +1 -1
  10. package/dist/catalog.json +5 -5
  11. package/dist/{chunk-7WQXXEVR.mjs → chunk-4ETJ4CDY.mjs} +5 -5
  12. package/dist/{chunk-7WQXXEVR.mjs.map → chunk-4ETJ4CDY.mjs.map} +1 -1
  13. package/dist/chunk-AJAHD35N.mjs +1708 -0
  14. package/dist/chunk-AJAHD35N.mjs.map +1 -0
  15. package/dist/chunk-AYJPOHCI.mjs +265 -0
  16. package/dist/chunk-AYJPOHCI.mjs.map +1 -0
  17. package/dist/chunk-B4NJJZFR.mjs +18 -0
  18. package/dist/chunk-B4NJJZFR.mjs.map +1 -0
  19. package/dist/{chunk-AZIARTGX.mjs → chunk-BNBOIDO5.mjs} +3 -3
  20. package/dist/{chunk-AZIARTGX.mjs.map → chunk-BNBOIDO5.mjs.map} +1 -1
  21. package/dist/{chunk-LVNCYP4J.mjs → chunk-CXHNVYMD.mjs} +5 -5
  22. package/dist/{chunk-LVNCYP4J.mjs.map → chunk-CXHNVYMD.mjs.map} +1 -1
  23. package/dist/{chunk-45CGKJ7S.mjs → chunk-D5JLJ3PT.mjs} +4 -4
  24. package/dist/{chunk-45CGKJ7S.mjs.map → chunk-D5JLJ3PT.mjs.map} +1 -1
  25. package/dist/{chunk-WM2VDYQA.mjs → chunk-D5LWSN2Y.mjs} +944 -196
  26. package/dist/chunk-D5LWSN2Y.mjs.map +1 -0
  27. package/dist/{chunk-KRC2XOIG.mjs → chunk-HLAOGXEK.mjs} +3 -3
  28. package/dist/{chunk-KRC2XOIG.mjs.map → chunk-HLAOGXEK.mjs.map} +1 -1
  29. package/dist/{chunk-2WF6KIGF.mjs → chunk-I3L56GVH.mjs} +212 -71
  30. package/dist/chunk-I3L56GVH.mjs.map +1 -0
  31. package/dist/{chunk-ZBJBQKJ2.mjs → chunk-IHUFOV7L.mjs} +4 -19
  32. package/dist/chunk-IHUFOV7L.mjs.map +1 -0
  33. package/dist/chunk-J5LGTIGS.mjs +10 -0
  34. package/dist/chunk-J5LGTIGS.mjs.map +1 -0
  35. package/dist/{chunk-BEZSQKPY.mjs → chunk-KYMBUTPO.mjs} +5 -4
  36. package/dist/chunk-KYMBUTPO.mjs.map +1 -0
  37. package/dist/{chunk-4DS3MKID.mjs → chunk-KZGPSTZI.mjs} +4 -4
  38. package/dist/{chunk-4DS3MKID.mjs.map → chunk-KZGPSTZI.mjs.map} +1 -1
  39. package/dist/{chunk-SGFJLHHG.mjs → chunk-PPKHCRRE.mjs} +3 -3
  40. package/dist/{chunk-SGFJLHHG.mjs.map → chunk-PPKHCRRE.mjs.map} +1 -1
  41. package/dist/{chunk-BKSXPNPQ.mjs → chunk-SZDAS7LK.mjs} +81 -3
  42. package/dist/chunk-SZDAS7LK.mjs.map +1 -0
  43. package/dist/chunk-T3SOHYB2.mjs +851 -0
  44. package/dist/chunk-T3SOHYB2.mjs.map +1 -0
  45. package/dist/geometry-2d.d.mts +2 -2
  46. package/dist/geometry-2d.d.ts +2 -2
  47. package/dist/geometry-2d.js +6288 -901
  48. package/dist/geometry-2d.js.map +1 -1
  49. package/dist/geometry-2d.mjs +7 -5
  50. package/dist/geometry-3d.d.mts +2 -2
  51. package/dist/geometry-3d.d.ts +2 -2
  52. package/dist/geometry-3d.js +1335 -253
  53. package/dist/geometry-3d.js.map +1 -1
  54. package/dist/geometry-3d.mjs +6 -4
  55. package/dist/graph-2d.d.mts +2 -2
  56. package/dist/graph-2d.d.ts +2 -2
  57. package/dist/graph-2d.js +1501 -342
  58. package/dist/graph-2d.js.map +1 -1
  59. package/dist/graph-2d.mjs +9 -7
  60. package/dist/handleExtractProblem-C-U5KluK.d.mts +158 -0
  61. package/dist/handleExtractProblem-C-U5KluK.d.ts +158 -0
  62. package/dist/{host-EPZCNFLH.mjs → host-HAYCJJ2T.mjs} +1390 -376
  63. package/dist/host-HAYCJJ2T.mjs.map +1 -0
  64. package/dist/{host-LKCMYEAV.mjs → host-LTJHAY5A.mjs} +12 -10
  65. package/dist/host-LTJHAY5A.mjs.map +1 -0
  66. package/dist/{host-ZIQ77W33.mjs → host-M26FS244.mjs} +8 -6
  67. package/dist/host-M26FS244.mjs.map +1 -0
  68. package/dist/{host-QS2EOTRJ.mjs → host-ZQCDAT6O.mjs} +3 -2
  69. package/dist/host-ZQCDAT6O.mjs.map +1 -0
  70. package/dist/index.d.mts +4 -3
  71. package/dist/index.d.ts +4 -3
  72. package/dist/index.js +6493 -1102
  73. package/dist/index.js.map +1 -1
  74. package/dist/index.mjs +24 -21
  75. package/dist/index.mjs.map +1 -1
  76. package/dist/latex.d.mts +2 -2
  77. package/dist/latex.d.ts +2 -2
  78. package/dist/latex.mjs +2 -1
  79. package/dist/render-ZX2O2IK7.mjs +10 -0
  80. package/dist/{render-SA4JTOW3.mjs.map → render-ZX2O2IK7.mjs.map} +1 -1
  81. package/dist/serialize-C3LSUMSA.mjs +9 -0
  82. package/dist/{serialize-JAVOU22E.mjs.map → serialize-C3LSUMSA.mjs.map} +1 -1
  83. package/dist/types-zc_Pa0mp.d.mts +418 -0
  84. package/dist/types-zc_Pa0mp.d.ts +418 -0
  85. package/package.json +10 -1
  86. package/dist/ExcalidrawWithMenus-WENZRYYE.mjs.map +0 -1
  87. package/dist/chunk-2WF6KIGF.mjs.map +0 -1
  88. package/dist/chunk-BEZSQKPY.mjs.map +0 -1
  89. package/dist/chunk-BKSXPNPQ.mjs.map +0 -1
  90. package/dist/chunk-CGZZO4BX.mjs +0 -96
  91. package/dist/chunk-CGZZO4BX.mjs.map +0 -1
  92. package/dist/chunk-WM2VDYQA.mjs.map +0 -1
  93. package/dist/chunk-ZBJBQKJ2.mjs.map +0 -1
  94. package/dist/host-EPZCNFLH.mjs.map +0 -1
  95. package/dist/host-LKCMYEAV.mjs.map +0 -1
  96. package/dist/host-QS2EOTRJ.mjs.map +0 -1
  97. package/dist/host-ZIQ77W33.mjs.map +0 -1
  98. package/dist/render-SA4JTOW3.mjs +0 -8
  99. package/dist/serialize-JAVOU22E.mjs +0 -7
  100. package/dist/types-Crbefnfe.d.ts +0 -128
  101. package/dist/types-DxlMPh-6.d.mts +0 -49
  102. package/dist/types-DxlMPh-6.d.ts +0 -49
  103. package/dist/types-vtvyKGAA.d.mts +0 -128
@@ -0,0 +1,418 @@
1
+ import { z } from 'zod';
2
+ import { ReactNode, ComponentType, RefAttributes } from 'react';
3
+ import { ExcalidrawElement } from '@excalidraw/excalidraw/element/types';
4
+
5
+ declare const NameZ: z.ZodString;
6
+
7
+ type Name = z.infer<typeof NameZ>;
8
+ type DslDistanceSpec = {
9
+ kind: 'circleRadius';
10
+ circle: Name;
11
+ scale?: number;
12
+ offset?: number;
13
+ } | {
14
+ kind: 'segmentLength';
15
+ p1: Name;
16
+ p2: Name;
17
+ scale?: number;
18
+ offset?: number;
19
+ } | {
20
+ kind: 'literal';
21
+ value: number;
22
+ scale?: number;
23
+ offset?: number;
24
+ };
25
+ type DslPointT = {
26
+ name: Name;
27
+ kind: 'free';
28
+ x: number;
29
+ y: number;
30
+ } | {
31
+ name: Name;
32
+ kind: 'midpoint';
33
+ p1: Name;
34
+ p2: Name;
35
+ visible?: boolean;
36
+ } | {
37
+ name: Name;
38
+ kind: 'onSegment';
39
+ segmentId: Name;
40
+ t: number;
41
+ } | {
42
+ name: Name;
43
+ kind: 'onLine';
44
+ lineId: Name;
45
+ t: number;
46
+ } | {
47
+ name: Name;
48
+ kind: 'onCircle';
49
+ circleId: Name;
50
+ theta: number;
51
+ } | {
52
+ name: Name;
53
+ kind: 'perpFoot';
54
+ from: Name;
55
+ onLine: Name;
56
+ } | {
57
+ name: Name;
58
+ kind: 'circumcenter';
59
+ vertices: [Name, Name, Name];
60
+ } | {
61
+ name: Name;
62
+ kind: 'incenter';
63
+ vertices: [Name, Name, Name];
64
+ } | {
65
+ name: Name;
66
+ kind: 'centroid';
67
+ vertices: [Name, Name, Name];
68
+ } | {
69
+ name: Name;
70
+ kind: 'orthocenter';
71
+ vertices: [Name, Name, Name];
72
+ } | {
73
+ name: Name;
74
+ kind: 'intersection';
75
+ ref1: Name;
76
+ ref2: Name;
77
+ branch?: 0 | 1;
78
+ } | {
79
+ name: Name;
80
+ kind: 'secondIntersection';
81
+ line: Name;
82
+ circle: Name;
83
+ other: Name;
84
+ } | {
85
+ name: Name;
86
+ kind: 'circleIntersection';
87
+ c1: Name;
88
+ c2: Name;
89
+ which: 0 | 1;
90
+ } | {
91
+ name: Name;
92
+ kind: 'circleSecondIntersection';
93
+ c1: Name;
94
+ c2: Name;
95
+ exclude: Name;
96
+ } | {
97
+ name: Name;
98
+ kind: 'tangencyPoint';
99
+ circle: Name;
100
+ onLine: Name;
101
+ } | {
102
+ name: Name;
103
+ kind: 'tangentPointExt';
104
+ from: Name;
105
+ circle: Name;
106
+ which: 0 | 1;
107
+ } | {
108
+ name: Name;
109
+ kind: 'arcMidpoint';
110
+ circle: Name;
111
+ a: Name;
112
+ b: Name;
113
+ notContaining: Name;
114
+ } | {
115
+ name: Name;
116
+ kind: 'excenter';
117
+ vertices: [Name, Name, Name];
118
+ opposite: Name;
119
+ } | {
120
+ name: Name;
121
+ kind: 'reflectPoint';
122
+ of: Name;
123
+ through: Name;
124
+ } | {
125
+ name: Name;
126
+ kind: 'reflectLine';
127
+ of: Name;
128
+ through: Name;
129
+ } | {
130
+ name: Name;
131
+ kind: 'pointAtDistance';
132
+ from: Name;
133
+ through: Name;
134
+ distance: DslDistanceSpec;
135
+ };
136
+ type DslShapeT = {
137
+ name: Name;
138
+ kind: 'segment';
139
+ p1: Name;
140
+ p2: Name;
141
+ } | {
142
+ name: Name;
143
+ kind: 'line';
144
+ p1: Name;
145
+ p2: Name;
146
+ } | {
147
+ name: Name;
148
+ kind: 'ray';
149
+ origin: Name;
150
+ through: Name;
151
+ } | {
152
+ name: Name;
153
+ kind: 'polygon';
154
+ vertices: Name[];
155
+ } | {
156
+ name: Name;
157
+ kind: 'perpendicular';
158
+ throughPoint: Name;
159
+ toLine: Name;
160
+ } | {
161
+ name: Name;
162
+ kind: 'parallel';
163
+ throughPoint: Name;
164
+ toLine: Name;
165
+ } | {
166
+ name: Name;
167
+ kind: 'perpBisector';
168
+ p1: Name;
169
+ p2: Name;
170
+ } | {
171
+ name: Name;
172
+ kind: 'angleBisector';
173
+ p1: Name;
174
+ vertex: Name;
175
+ p2: Name;
176
+ } | {
177
+ name: Name;
178
+ kind: 'lineThrough';
179
+ points: Name[];
180
+ } | {
181
+ name: Name;
182
+ kind: 'radicalAxis';
183
+ circle1: Name;
184
+ circle2: Name;
185
+ } | {
186
+ name: Name;
187
+ kind: 'tangent';
188
+ throughPoint: Name;
189
+ toCircle: Name;
190
+ branch?: 0 | 1 | 'on';
191
+ } | {
192
+ name: Name;
193
+ kind: 'circleCP';
194
+ center: Name;
195
+ surfacePoint: Name;
196
+ visible?: boolean;
197
+ } | {
198
+ name: Name;
199
+ kind: 'circle3';
200
+ p1: Name;
201
+ p2: Name;
202
+ p3: Name;
203
+ } | {
204
+ name: Name;
205
+ kind: 'circleDiameter';
206
+ p1: Name;
207
+ p2: Name;
208
+ visible?: boolean;
209
+ } | {
210
+ name: Name;
211
+ kind: 'circleCR';
212
+ center: Name;
213
+ radius: number;
214
+ } | {
215
+ name: Name;
216
+ kind: 'incircle';
217
+ vertices: [Name, Name, Name];
218
+ } | {
219
+ name: Name;
220
+ kind: 'excircle';
221
+ vertices: [Name, Name, Name];
222
+ opposite: Name;
223
+ };
224
+ type DslInputT = {
225
+ version: 1;
226
+ points: DslPointT[];
227
+ shapes: DslShapeT[];
228
+ };
229
+
230
+ type SceneObject<A = Record<string, unknown>> = {
231
+ id: string;
232
+ kind: string;
233
+ label: string;
234
+ visible: boolean;
235
+ locked: boolean;
236
+ layer: string;
237
+ schemaVersion: number;
238
+ attrs: A;
239
+ };
240
+ type View2D = {
241
+ readonly bbox: readonly [number, number, number, number];
242
+ readonly showAxis: boolean;
243
+ readonly showGrid: boolean;
244
+ };
245
+ type View3D = {
246
+ readonly bbox3D: readonly [number, number, number, number, number, number];
247
+ readonly azimuth: number;
248
+ readonly elevation: number;
249
+ };
250
+ type ViewGraph2D = {
251
+ readonly xMin: number;
252
+ readonly xMax: number;
253
+ readonly yMin: number;
254
+ readonly yMax: number;
255
+ readonly showAxis: boolean;
256
+ readonly showGrid: boolean;
257
+ };
258
+ type StateMeta = {
259
+ readonly domain: '2d';
260
+ readonly version: number;
261
+ readonly view: View2D;
262
+ } | {
263
+ readonly domain: '3d';
264
+ readonly version: number;
265
+ readonly view: View3D;
266
+ } | {
267
+ readonly domain: 'graph2d';
268
+ readonly version: number;
269
+ readonly view: ViewGraph2D;
270
+ };
271
+ type State = {
272
+ readonly objects: Readonly<Record<string, SceneObject>>;
273
+ readonly order: readonly string[];
274
+ readonly counter: number;
275
+ readonly meta: StateMeta;
276
+ };
277
+
278
+ /** Minimal client-safe response required by the geometry AI editor. */
279
+ type AiFigureUiResult = {
280
+ ok: true;
281
+ state: State;
282
+ } | {
283
+ ok: false;
284
+ message: string;
285
+ };
286
+ /**
287
+ * Progress event emitted bởi streaming generator. Số token output đã sinh.
288
+ * Editor dùng để hiển thị "Đang nhận N token..." realtime.
289
+ */
290
+ interface AiFigureProgress {
291
+ /** Số token output đã sinh tính đến lúc emit. */
292
+ tokens: number;
293
+ }
294
+ /**
295
+ * Consumer-provided bridge to a server-side `generateFigure()` call.
296
+ * Implementations must keep API credentials outside the browser bundle.
297
+ *
298
+ * `onProgress` là optional: nếu consumer dùng streaming endpoint (SSE),
299
+ * forward chunk events vào đây. Non-streaming impl bỏ qua.
300
+ *
301
+ * `currentDsl` (MỚI cho multi-step refine): khi caller có hình hiện tại
302
+ * (state.order.length > 0) và muốn AI sửa/thêm → pass currentDsl. Consumer
303
+ * branch sang refine endpoint. Không pass → build endpoint cũ.
304
+ */
305
+ type GenerateGeometryFigure = (problem: string, options: {
306
+ signal: AbortSignal;
307
+ onProgress?: (info: AiFigureProgress) => void;
308
+ currentDsl?: DslInputT;
309
+ }) => Promise<AiFigureUiResult>;
310
+ /**
311
+ * Kết quả trả về từ `restoreFileFromCustomData`. Chứa đủ thông tin để
312
+ * consumer gọi `api.addFiles(...)`.
313
+ */
314
+ interface RestoredStampFile {
315
+ fileId: string;
316
+ dataURL: string;
317
+ mimeType: 'image/svg+xml' | 'image/png';
318
+ }
319
+ /**
320
+ * Tối thiểu mọi custom data của stamp cần có. Các stamp cụ thể (geometry,
321
+ * latex, ...) extend interface này với fields riêng.
322
+ */
323
+ interface BaseStampCustomData {
324
+ kind: string;
325
+ version: number;
326
+ }
327
+ /**
328
+ * Props mà mỗi StampHost nhận từ Whiteboard. Host component tự
329
+ * quản lý state nội bộ (panel ref, undo stack, displayMode...) — main view
330
+ * chỉ điều phối show/hide.
331
+ */
332
+ interface StampHostProps {
333
+ api: any;
334
+ /**
335
+ * Element đang re-edit (double-click) hoặc null nếu đang tạo mới.
336
+ * Host tự parse customData để load state ban đầu.
337
+ */
338
+ editingElement: {
339
+ id: string;
340
+ customData: unknown;
341
+ } | null;
342
+ /** Đóng stamp panel (gọi sau khi insert hoặc khi user huỷ). */
343
+ onClose: () => void;
344
+ /** Dark theme flag. */
345
+ isDark: boolean;
346
+ /** Optional client-safe bridge for the geometry-2d AI prompt editor. */
347
+ generateGeometryFigure?: GenerateGeometryFigure;
348
+ }
349
+ /**
350
+ * Imperative API mà main view truy cập qua ref:
351
+ * - tryInsert(): khi user click ra ngoài → auto-commit nếu valid.
352
+ * Trả về true nếu chèn thành công, false nếu chưa có nội dung.
353
+ * - hasContent(): có nội dung để chèn không.
354
+ */
355
+ interface StampHostHandle {
356
+ tryInsert(): boolean;
357
+ hasContent(): boolean;
358
+ }
359
+ /**
360
+ * Component contract của Host. Chấp nhận cả `forwardRef` thông thường lẫn
361
+ * `React.lazy(() => import('./host'))` (LazyExoticComponent forwards ref).
362
+ */
363
+ type StampHostComponent = ComponentType<StampHostProps & RefAttributes<StampHostHandle>>;
364
+ /**
365
+ * Định nghĩa 1 loại stamp. Mỗi stamp khai báo:
366
+ * - kind: unique string (khớp với customData.kind)
367
+ * - phím tắt + UI toolbar
368
+ * - cách nhận biết customData thuộc về stamp này (matchesCustomData)
369
+ * - cách re-render SVG từ customData (cho restore sau reload)
370
+ * - Host component: bọc trọn editor + left panel + insert logic
371
+ *
372
+ * Main view dispatch generic: `<stamp.Host ... />` — không cần biết kind.
373
+ */
374
+ interface StampType<TCustomData extends BaseStampCustomData = BaseStampCustomData> {
375
+ /** Unique kind. VD: 'geometry', 'latex'. Phải khớp với customData.kind. */
376
+ kind: string;
377
+ /** Phím tắt mở/đóng stamp (lowercase, 1 ký tự). VD: 'g', 'l'. */
378
+ shortcutKey: string;
379
+ /** Chữ hiển thị overlay góc dưới nút toolbar (e.g. "G"). */
380
+ toolbarLabel: string;
381
+ /** Tooltip + aria-label của nút toolbar. */
382
+ toolbarTitle: string;
383
+ /** Icon SVG (ReactNode) trong nút toolbar. */
384
+ toolbarIcon: ReactNode;
385
+ /** Test data-testid cho nút toolbar (optional). */
386
+ toolbarTestId?: string;
387
+ /** Type guard: customData có thuộc về stamp này không. */
388
+ matchesCustomData(data: unknown): data is TCustomData;
389
+ /**
390
+ * Re-render SVG từ customData. Dùng khi restore math-stamp file sau reload
391
+ * page (Excalidraw không persist binary file payload, chỉ giữ fileId trong
392
+ * element). SVG render với light palette (nét đậm) — Excalidraw tự đảo
393
+ * màu trong dark mode qua CSS filter.
394
+ */
395
+ renderSvgFromCustomData(data: TCustomData): Promise<string>;
396
+ /**
397
+ * Regenerate file SVG/PNG cho element thuộc stamp này khi reload từ persisted
398
+ * snapshot. Trả về `RestoredStampFile` để consumer gọi `api.addFiles`, hoặc
399
+ * `null` nếu element không cần file (vd stamp chỉ là text overlay).
400
+ *
401
+ * Khi method này có mặt, `restoreMissingStampFiles` sẽ ưu tiên gọi method
402
+ * này thay vì dùng `renderSvgFromCustomData`. Stamp tự chịu trách nhiệm lấy
403
+ * `fileId` từ element và render file.
404
+ */
405
+ restoreFileFromCustomData?: (element: ExcalidrawElement) => Promise<RestoredStampFile | null>;
406
+ /**
407
+ * Host component bọc toàn bộ UI editing (panel + left panel + insert
408
+ * handler). Whiteboard mount Host khi activeStamp khớp kind.
409
+ */
410
+ Host: StampHostComponent;
411
+ /**
412
+ * Đánh dấu stamp chưa production-ready. Consumer mặc định bỏ qua
413
+ * (xem `DEFAULT_STAMPS` chỉ gồm stamp không `experimental`).
414
+ */
415
+ experimental?: boolean;
416
+ }
417
+
418
+ export type { AiFigureProgress as A, BaseStampCustomData as B, DslInputT as D, GenerateGeometryFigure as G, StampType as S, AiFigureUiResult as a, State as b };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xom11/whiteboard",
3
- "version": "0.24.2",
3
+ "version": "0.27.0",
4
4
  "private": false,
5
5
  "description": "Excalidraw + JSXGraph + KaTeX whiteboard component (drawing, geometry stamps, LaTeX stamps).",
6
6
  "repository": {
@@ -73,6 +73,7 @@
73
73
  "demo": "vite --config scripts/demo/vite.config.ts",
74
74
  "ai:eval": "tsx scripts/eval-ai.ts",
75
75
  "ai:smoke": "tsx scripts/smoke-ai.ts",
76
+ "check:matrix": "tsx scripts/check-construct-matrix.ts",
76
77
  "prepublishOnly": "npm run clean && npm run build"
77
78
  },
78
79
  "peerDependencies": {
@@ -97,6 +98,7 @@
97
98
  "@typescript-eslint/eslint-plugin": "^8.59.4",
98
99
  "@typescript-eslint/parser": "^8.59.4",
99
100
  "@vitejs/plugin-react": "^6.0.2",
101
+ "dotenv": "^17.4.2",
100
102
  "eslint": "^9.39.4",
101
103
  "eslint-plugin-react": "^7.37.5",
102
104
  "eslint-plugin-react-hooks": "^5.2.0",
@@ -116,10 +118,17 @@
116
118
  "vite": "^8.0.13"
117
119
  },
118
120
  "dependencies": {
121
+ "@anthropic-ai/claude-agent-sdk": "^0.3.161",
119
122
  "@anthropic-ai/sdk": "^0.98.0",
120
123
  "immer": "^10.2.0",
121
124
  "pdfjs-dist": "^5.7.284",
125
+ "tesseract.js": "^7.0.0",
122
126
  "zod": "^3.23.8",
123
127
  "zod-to-json-schema": "^3.25.2"
128
+ },
129
+ "overrides": {
130
+ "@anthropic-ai/claude-agent-sdk": {
131
+ "zod": "$zod"
132
+ }
124
133
  }
125
134
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ExcalidrawWithMenus.tsx"],"names":[],"mappings":";;;AAiBO,SAAS,oBAAoB,KAAA,EAAwB;AAC1D,EAAA,MAAM,EAAE,QAAA,EAAU,GAAG,IAAA,EAAK,GAAI,KAAA;AAC9B,EAAA,uBACE,IAAA,CAAC,UAAA,EAAA,EAAY,GAAG,IAAA,EAEd,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,QAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAA,CAAS,YAAA,CAAa,SAAA,EAAtB,EAAgC,CAAA;AAAA,sBACjC,GAAA,CAAC,QAAA,CAAS,YAAA,CAAa,WAAA,EAAtB,EAAkC,CAAA;AAAA,sBACnC,GAAA,CAAC,QAAA,CAAS,YAAA,CAAa,WAAA,EAAtB,EAAkC,CAAA;AAAA,sBACnC,GAAA,CAAC,QAAA,CAAS,YAAA,CAAa,WAAA,EAAtB,EAAkC;AAAA,KAAA,EACrC,CAAA;AAAA,oBAEA,GAAA,CAAC,MAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EACR,CAAA;AAAA,oBAGA,GAAA,CAAC,aAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EACR,CAAA;AAAA,IACC;AAAA,GAAA,EACH,CAAA;AAEJ","file":"ExcalidrawWithMenus-WENZRYYE.mjs","sourcesContent":["'use client';\n\n// Client-only wrapper around Excalidraw that lets us reach for static helpers\n// like `MainMenu.DefaultItems.*`. Whiteboard dynamic-imports this\n// file so SSR never evaluates @excalidraw/excalidraw, while inside this file we\n// can use plain static imports (the entire module loads on the client).\n\nimport React from 'react';\nimport {\n Excalidraw,\n MainMenu,\n Footer,\n WelcomeScreen,\n} from '@excalidraw/excalidraw';\n \ntype ExcalidrawProps = any;\n\nexport function ExcalidrawWithMenus(props: ExcalidrawProps) {\n const { children, ...rest } = props;\n return (\n <Excalidraw {...rest}>\n {/* Replace default menu with curated items — no socials/help/branding */}\n <MainMenu>\n <MainMenu.DefaultItems.LoadScene />\n <MainMenu.DefaultItems.SaveAsImage />\n <MainMenu.DefaultItems.ClearCanvas />\n <MainMenu.DefaultItems.ToggleTheme />\n </MainMenu>\n {/* Footer slot with no content suppresses default \"Made with Excalidraw\" link */}\n <Footer>\n <span />\n </Footer>\n {/* WelcomeScreen slot (empty) prevents the default Excalidraw welcome panel\n * (which includes the Excalidraw logo and social links) from appearing. */}\n <WelcomeScreen>\n <span />\n </WelcomeScreen>\n {children}\n </Excalidraw>\n );\n}\n"]}