@xom11/whiteboard 0.32.0 → 0.33.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 (68) hide show
  1. package/dist/ai.d.mts +1 -1
  2. package/dist/ai.d.ts +1 -1
  3. package/dist/ai.mjs +2 -2
  4. package/dist/catalog.json +4 -4
  5. package/dist/{chunk-FI2MGX5H.mjs → chunk-4NJUTCFF.mjs} +3 -3
  6. package/dist/{chunk-FI2MGX5H.mjs.map → chunk-4NJUTCFF.mjs.map} +1 -1
  7. package/dist/{chunk-XSTGTEGP.mjs → chunk-BZZ5BROM.mjs} +4 -5
  8. package/dist/chunk-BZZ5BROM.mjs.map +1 -0
  9. package/dist/{host-JNLJ5BVR.mjs → chunk-C3RDFBQ5.mjs} +17 -32
  10. package/dist/chunk-C3RDFBQ5.mjs.map +1 -0
  11. package/dist/chunk-C7C66BAV.mjs +11 -0
  12. package/dist/chunk-C7C66BAV.mjs.map +1 -0
  13. package/dist/{chunk-DBG6DZ2V.mjs → chunk-FOPZOVI3.mjs} +5 -4
  14. package/dist/chunk-FOPZOVI3.mjs.map +1 -0
  15. package/dist/{chunk-MOAXHVKI.mjs → chunk-GKDQ5IV7.mjs} +3 -3
  16. package/dist/{chunk-MOAXHVKI.mjs.map → chunk-GKDQ5IV7.mjs.map} +1 -1
  17. package/dist/{chunk-KLGPAMJS.mjs → chunk-NBMYET5H.mjs} +3 -10
  18. package/dist/{chunk-KLGPAMJS.mjs.map → chunk-NBMYET5H.mjs.map} +1 -1
  19. package/dist/{chunk-DJM5EWTT.mjs → chunk-NTFG7ZRN.mjs} +2 -2
  20. package/dist/{chunk-DJM5EWTT.mjs.map → chunk-NTFG7ZRN.mjs.map} +1 -1
  21. package/dist/{chunk-C76SOFXF.mjs → chunk-QCK3Z5WN.mjs} +3 -3
  22. package/dist/{chunk-C76SOFXF.mjs.map → chunk-QCK3Z5WN.mjs.map} +1 -1
  23. package/dist/geometry-2d.d.mts +1 -1
  24. package/dist/geometry-2d.d.ts +1 -1
  25. package/dist/geometry-2d.js +146 -115
  26. package/dist/geometry-2d.js.map +1 -1
  27. package/dist/geometry-2d.mjs +4 -3
  28. package/dist/geometry-3d.d.mts +1 -1
  29. package/dist/geometry-3d.d.ts +1 -1
  30. package/dist/geometry-3d.js +6 -4
  31. package/dist/geometry-3d.js.map +1 -1
  32. package/dist/geometry-3d.mjs +2 -2
  33. package/dist/graph-2d.d.mts +1 -1
  34. package/dist/graph-2d.d.ts +1 -1
  35. package/dist/graph-2d.js +6 -4
  36. package/dist/graph-2d.js.map +1 -1
  37. package/dist/graph-2d.mjs +2 -2
  38. package/dist/host-6WTLCXUE.mjs +62 -0
  39. package/dist/host-6WTLCXUE.mjs.map +1 -0
  40. package/dist/{host-H2IGOKJU.mjs → host-BWIXT5TR.mjs} +3 -3
  41. package/dist/{host-H2IGOKJU.mjs.map → host-BWIXT5TR.mjs.map} +1 -1
  42. package/dist/{host-VRWLQSMH.mjs → host-QDVRULJV.mjs} +10 -7
  43. package/dist/host-QDVRULJV.mjs.map +1 -0
  44. package/dist/{host-W4U6YCSX.mjs → host-USOIVTQB.mjs} +10 -7
  45. package/dist/host-USOIVTQB.mjs.map +1 -0
  46. package/dist/index.d.mts +13 -3
  47. package/dist/index.d.ts +13 -3
  48. package/dist/index.js +173 -119
  49. package/dist/index.js.map +1 -1
  50. package/dist/index.mjs +31 -16
  51. package/dist/index.mjs.map +1 -1
  52. package/dist/latex.d.mts +1 -1
  53. package/dist/latex.d.ts +1 -1
  54. package/dist/latex.mjs +1 -1
  55. package/dist/studio.d.mts +35 -0
  56. package/dist/studio.d.ts +35 -0
  57. package/dist/studio.js +10883 -0
  58. package/dist/studio.js.map +1 -0
  59. package/dist/studio.mjs +28 -0
  60. package/dist/studio.mjs.map +1 -0
  61. package/dist/{types-tePd94vW.d.mts → types-eEEEVsLF.d.mts} +1 -1
  62. package/dist/{types-tePd94vW.d.ts → types-eEEEVsLF.d.ts} +1 -1
  63. package/package.json +9 -2
  64. package/dist/chunk-DBG6DZ2V.mjs.map +0 -1
  65. package/dist/chunk-XSTGTEGP.mjs.map +0 -1
  66. package/dist/host-JNLJ5BVR.mjs.map +0 -1
  67. package/dist/host-VRWLQSMH.mjs.map +0 -1
  68. package/dist/host-W4U6YCSX.mjs.map +0 -1
package/dist/index.d.mts CHANGED
@@ -3,8 +3,8 @@ import { NonDeletedExcalidrawElement } from '@excalidraw/excalidraw/element/type
3
3
  export { ExcalidrawElement, NonDeletedExcalidrawElement } from '@excalidraw/excalidraw/element/types';
4
4
  import { AppState, BinaryFiles } from '@excalidraw/excalidraw/types';
5
5
  export { AppState, BinaryFiles } from '@excalidraw/excalidraw/types';
6
- import { S as StampType, G as GenerateGeometryFigure, a as GeometryDraftPreview } from './types-tePd94vW.mjs';
7
- export { A as AiFigureProgress, b as AiFigureUiResult, B as BaseStampCustomData } from './types-tePd94vW.mjs';
6
+ import { S as StampType, G as GenerateGeometryFigure, a as GeometryDraftPreview } from './types-eEEEVsLF.mjs';
7
+ export { A as AiFigureProgress, b as AiFigureUiResult, B as BaseStampCustomData } from './types-eEEEVsLF.mjs';
8
8
  import { GeometryCustomData } from './geometry-2d.mjs';
9
9
  export { geometryStamp } from './geometry-2d.mjs';
10
10
  import { LatexCustomData } from './latex.mjs';
@@ -282,4 +282,14 @@ declare function insertPdfPages(api: ExApi, source: File | Blob | ArrayBuffer, o
282
282
  */
283
283
  declare function parsePageRange(input: string, totalPages: number): number[];
284
284
 
285
- export { ALL_STAMPS, DEFAULT_STAMPS, EXPERIMENTAL_STAMPS, type ExcalidrawSceneSnapshot, GenerateGeometryFigure, Geometry3DCustomData, GeometryCustomData, GeometryDraftPreview, Graph2DCustomData, type InsertPdfPagesOptions, type InsertPdfPagesResult, type InsertRasterizedPagesOptions, type InsertRasterizedPagesResult, LatexCustomData, type RasterizeOptions, type RasterizedPage, STABLE_STAMPS, STAMP_CATALOG, type StampCatalogEntry, type StampCustomData, StampType, type SyncableAppState, Whiteboard, type WhiteboardProps, closePdfDocument, configurePdfWorker, findCatalogEntry, findStampForCustomData, insertPdfPages, insertRasterizedPagesIntoScene, isStampElement, loadPdfDocument, parsePageRange, pickSyncableAppState, rasterizePdf, restoreMissingStampFiles };
285
+ /**
286
+ * Chèn một hình học (dạng `jsonState`) vào Excalidraw scene như một stamp
287
+ * re-edit được. Dùng cho handoff "Mở trong bảng trắng": trang landing ghi
288
+ * `jsonState` vào sessionStorage, trang /whiteboard đọc ra rồi gọi hàm này.
289
+ *
290
+ * `api` là `ExcalidrawImperativeAPI` — để `unknown` ở public API cho consumer
291
+ * không phải khớp type Excalidraw.
292
+ */
293
+ declare function insertGeometryStampIntoScene(api: unknown, jsonState: string): Promise<void>;
294
+
295
+ export { ALL_STAMPS, DEFAULT_STAMPS, EXPERIMENTAL_STAMPS, type ExcalidrawSceneSnapshot, GenerateGeometryFigure, Geometry3DCustomData, GeometryCustomData, GeometryDraftPreview, Graph2DCustomData, type InsertPdfPagesOptions, type InsertPdfPagesResult, type InsertRasterizedPagesOptions, type InsertRasterizedPagesResult, LatexCustomData, type RasterizeOptions, type RasterizedPage, STABLE_STAMPS, STAMP_CATALOG, type StampCatalogEntry, type StampCustomData, StampType, type SyncableAppState, Whiteboard, type WhiteboardProps, closePdfDocument, configurePdfWorker, findCatalogEntry, findStampForCustomData, insertGeometryStampIntoScene, insertPdfPages, insertRasterizedPagesIntoScene, isStampElement, loadPdfDocument, parsePageRange, pickSyncableAppState, rasterizePdf, restoreMissingStampFiles };
package/dist/index.d.ts CHANGED
@@ -3,8 +3,8 @@ import { NonDeletedExcalidrawElement } from '@excalidraw/excalidraw/element/type
3
3
  export { ExcalidrawElement, NonDeletedExcalidrawElement } from '@excalidraw/excalidraw/element/types';
4
4
  import { AppState, BinaryFiles } from '@excalidraw/excalidraw/types';
5
5
  export { AppState, BinaryFiles } from '@excalidraw/excalidraw/types';
6
- import { S as StampType, G as GenerateGeometryFigure, a as GeometryDraftPreview } from './types-tePd94vW.js';
7
- export { A as AiFigureProgress, b as AiFigureUiResult, B as BaseStampCustomData } from './types-tePd94vW.js';
6
+ import { S as StampType, G as GenerateGeometryFigure, a as GeometryDraftPreview } from './types-eEEEVsLF.js';
7
+ export { A as AiFigureProgress, b as AiFigureUiResult, B as BaseStampCustomData } from './types-eEEEVsLF.js';
8
8
  import { GeometryCustomData } from './geometry-2d.js';
9
9
  export { geometryStamp } from './geometry-2d.js';
10
10
  import { LatexCustomData } from './latex.js';
@@ -282,4 +282,14 @@ declare function insertPdfPages(api: ExApi, source: File | Blob | ArrayBuffer, o
282
282
  */
283
283
  declare function parsePageRange(input: string, totalPages: number): number[];
284
284
 
285
- export { ALL_STAMPS, DEFAULT_STAMPS, EXPERIMENTAL_STAMPS, type ExcalidrawSceneSnapshot, GenerateGeometryFigure, Geometry3DCustomData, GeometryCustomData, GeometryDraftPreview, Graph2DCustomData, type InsertPdfPagesOptions, type InsertPdfPagesResult, type InsertRasterizedPagesOptions, type InsertRasterizedPagesResult, LatexCustomData, type RasterizeOptions, type RasterizedPage, STABLE_STAMPS, STAMP_CATALOG, type StampCatalogEntry, type StampCustomData, StampType, type SyncableAppState, Whiteboard, type WhiteboardProps, closePdfDocument, configurePdfWorker, findCatalogEntry, findStampForCustomData, insertPdfPages, insertRasterizedPagesIntoScene, isStampElement, loadPdfDocument, parsePageRange, pickSyncableAppState, rasterizePdf, restoreMissingStampFiles };
285
+ /**
286
+ * Chèn một hình học (dạng `jsonState`) vào Excalidraw scene như một stamp
287
+ * re-edit được. Dùng cho handoff "Mở trong bảng trắng": trang landing ghi
288
+ * `jsonState` vào sessionStorage, trang /whiteboard đọc ra rồi gọi hàm này.
289
+ *
290
+ * `api` là `ExcalidrawImperativeAPI` — để `unknown` ở public API cho consumer
291
+ * không phải khớp type Excalidraw.
292
+ */
293
+ declare function insertGeometryStampIntoScene(api: unknown, jsonState: string): Promise<void>;
294
+
295
+ export { ALL_STAMPS, DEFAULT_STAMPS, EXPERIMENTAL_STAMPS, type ExcalidrawSceneSnapshot, GenerateGeometryFigure, Geometry3DCustomData, GeometryCustomData, GeometryDraftPreview, Graph2DCustomData, type InsertPdfPagesOptions, type InsertPdfPagesResult, type InsertRasterizedPagesOptions, type InsertRasterizedPagesResult, LatexCustomData, type RasterizeOptions, type RasterizedPage, STABLE_STAMPS, STAMP_CATALOG, type StampCatalogEntry, type StampCustomData, StampType, type SyncableAppState, Whiteboard, type WhiteboardProps, closePdfDocument, configurePdfWorker, findCatalogEntry, findStampForCustomData, insertGeometryStampIntoScene, insertPdfPages, insertRasterizedPagesIntoScene, isStampElement, loadPdfDocument, parsePageRange, pickSyncableAppState, rasterizePdf, restoreMissingStampFiles };
package/dist/index.js CHANGED
@@ -11348,92 +11348,10 @@ var init_useChordShortcut = __esm({
11348
11348
  A_CODE2 = "a".charCodeAt(0);
11349
11349
  }
11350
11350
  });
11351
-
11352
- // src/stamps/shared/insertImage.ts
11353
- function buildStampImageElement(api, fileId, width, height, customData, x, y) {
11354
- const appState = api?.getAppState() ?? { scrollX: 0, scrollY: 0, width: 800, height: 600, zoom: { value: 1 } };
11355
- const cx = x ?? appState.scrollX + (appState.width ?? 800) / 2 / (appState.zoom?.value ?? 1) - width / 2;
11356
- const cy = y ?? appState.scrollY + (appState.height ?? 600) / 2 / (appState.zoom?.value ?? 1) - height / 2;
11357
- return {
11358
- type: "image",
11359
- id: "stamp_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8),
11360
- x: cx,
11361
- y: cy,
11362
- width,
11363
- height,
11364
- fileId,
11365
- customData,
11366
- angle: 0,
11367
- strokeColor: "transparent",
11368
- backgroundColor: "transparent",
11369
- fillStyle: "solid",
11370
- strokeWidth: 1,
11371
- strokeStyle: "solid",
11372
- roughness: 0,
11373
- opacity: 100,
11374
- groupIds: [],
11375
- roundness: null,
11376
- seed: Math.floor(Math.random() * 1e9),
11377
- versionNonce: 0,
11378
- version: 1,
11379
- isDeleted: false,
11380
- boundElements: null,
11381
- updated: Date.now(),
11382
- link: null,
11383
- locked: false,
11384
- status: "saved",
11385
- scale: [1, 1]
11386
- };
11387
- }
11388
- async function insertStampImage(api, opts) {
11389
- const { dataURL, fileId, width, height, mimeType } = await createStampFile(opts.svgString);
11390
- api.addFiles([{ id: fileId, dataURL, mimeType, created: Date.now() }]);
11391
- const customData = opts.makeCustomData();
11392
- const elements = api.getSceneElements();
11393
- const editingId = opts.editingElementId ?? null;
11394
- if (editingId) {
11395
- const old = opts.preserveExistingSize ? elements.find((e) => e.id === editingId) : void 0;
11396
- const oldLongest = old ? Math.max(old.width ?? 0, old.height ?? 0) : 0;
11397
- const newLongest = Math.max(width, height);
11398
- const scale3 = oldLongest > 0 && newLongest > 0 ? oldLongest / newLongest : 1;
11399
- const w = width * scale3;
11400
- const h = height * scale3;
11401
- const updated = elements.map(
11402
- (e) => e.id === editingId ? { ...e, fileId, customData, width: w, height: h } : e
11403
- );
11404
- api.updateScene({ elements: updated, appState: clearAppStateAfterInsert() });
11405
- return { fileId, width: w, height: h, elementId: editingId };
11406
- }
11407
- const newElement = buildStampImageElement(
11408
- api,
11409
- fileId,
11410
- width,
11411
- height,
11412
- customData,
11413
- opts.position?.x,
11414
- opts.position?.y
11415
- );
11416
- api.updateScene({
11417
- elements: [...elements, newElement],
11418
- appState: clearAppStateAfterInsert()
11419
- });
11420
- return { fileId, width, height, elementId: newElement.id };
11421
- }
11422
- var clearAppStateAfterInsert;
11423
- var init_insertImage = __esm({
11424
- "src/stamps/shared/insertImage.ts"() {
11425
- init_svgToStampFile();
11426
- clearAppStateAfterInsert = () => ({
11427
- selectedElementIds: {},
11428
- croppingElementId: null
11429
- });
11430
- }
11431
- });
11432
- function useStampStore(domain, editingElement, parseInitial) {
11351
+ function useStampStore(domain, makeInitialState) {
11433
11352
  const ref = React19.useRef(null);
11434
11353
  if (!ref.current) {
11435
- const initial = editingElement?.customData ? parseInitial(editingElement.customData) ?? createEmptyState(domain) : createEmptyState(domain);
11436
- ref.current = createStore(initial);
11354
+ ref.current = createStore(makeInitialState?.() ?? createEmptyState(domain));
11437
11355
  }
11438
11356
  return ref.current;
11439
11357
  }
@@ -12010,38 +11928,29 @@ var init_dslRenderRow = __esm({
12010
11928
  init_describeDsl();
12011
11929
  }
12012
11930
  });
12013
-
12014
- // src/stamps/geometry-2d/host.tsx
12015
- var host_exports = {};
12016
- __export(host_exports, {
12017
- GeometryStampHost: () => GeometryStampHost
12018
- });
12019
- function parseInitialState(data) {
12020
- if (!isGeometryCustomData(data)) return null;
12021
- return deserializeBoard(data.jsonState);
12022
- }
12023
- var GeometryStampHost;
12024
- var init_host = __esm({
12025
- "src/stamps/geometry-2d/host.tsx"() {
11931
+ var GeometryStudio;
11932
+ var init_GeometryStudio = __esm({
11933
+ "src/stamps/geometry-2d/studio/GeometryStudio.tsx"() {
12026
11934
  "use client";
12027
11935
  init_StampLeftPanel();
12028
11936
  init_icons();
12029
11937
  init_EditorPanel();
12030
11938
  init_tools();
12031
11939
  init_useChordShortcut();
12032
- init_insertImage();
12033
11940
  init_serialize();
12034
- init_types3();
12035
11941
  init_scene();
12036
11942
  init_useIsMobile();
12037
11943
  init_useStampStore();
12038
11944
  init_dslRenderRow();
12039
- GeometryStampHost = React19.forwardRef(
12040
- function GeometryStampHost2({ api, editingElement, onClose, isDark, generateGeometryFigure, onGeometryDraft }, ref) {
11945
+ GeometryStudio = React19.forwardRef(
11946
+ function GeometryStudio2({ initialJsonState, onCommit, onClose, isDark, api, generateGeometryFigure, onGeometryDraft }, ref) {
12041
11947
  const panelRef = React19.useRef(null);
12042
11948
  const { isMobile } = useIsMobile();
12043
11949
  const [drawerOpen, setDrawerOpen] = React19.useState(false);
12044
- const sceneStore = useStampStore("2d", editingElement, parseInitialState);
11950
+ const sceneStore = useStampStore(
11951
+ "2d",
11952
+ () => initialJsonState ? deserializeBoard(initialJsonState) : null
11953
+ );
12045
11954
  const initialMeta = sceneStore.getState().meta;
12046
11955
  const initialView = initialMeta.domain === "2d" ? initialMeta.view : DEFAULT_VIEW_2D;
12047
11956
  const [selectedTool, setSelectedTool] = React19.useState("move");
@@ -12065,24 +11974,15 @@ var init_host = __esm({
12065
11974
  const renderRow = React19.useMemo(() => makeDslRenderRow(sceneStore), [sceneStore]);
12066
11975
  const handleInsert = React19.useCallback(
12067
11976
  async (jsonState, svgString) => {
12068
- if (!api) return;
12069
11977
  try {
12070
- await insertStampImage(api, {
12071
- svgString,
12072
- makeCustomData: () => ({
12073
- kind: "geometry",
12074
- version: 1,
12075
- jsonState
12076
- }),
12077
- editingElementId: editingElement?.id ?? null,
12078
- preserveExistingSize: true
12079
- });
11978
+ const committed = await onCommit(jsonState, svgString);
11979
+ if (committed === false) return;
12080
11980
  } catch (err) {
12081
- console.error("Geometry insert failed:", err);
11981
+ console.error("Geometry commit failed:", err);
12082
11982
  }
12083
11983
  onClose();
12084
11984
  },
12085
- [api, editingElement?.id, onClose]
11985
+ [onCommit, onClose]
12086
11986
  );
12087
11987
  React19.useImperativeHandle(
12088
11988
  ref,
@@ -12164,6 +12064,137 @@ var init_host = __esm({
12164
12064
  }
12165
12065
  });
12166
12066
 
12067
+ // src/stamps/shared/insertImage.ts
12068
+ function buildStampImageElement(api, fileId, width, height, customData, x, y) {
12069
+ const appState = api?.getAppState() ?? { scrollX: 0, scrollY: 0, width: 800, height: 600, zoom: { value: 1 } };
12070
+ const cx = x ?? appState.scrollX + (appState.width ?? 800) / 2 / (appState.zoom?.value ?? 1) - width / 2;
12071
+ const cy = y ?? appState.scrollY + (appState.height ?? 600) / 2 / (appState.zoom?.value ?? 1) - height / 2;
12072
+ return {
12073
+ type: "image",
12074
+ id: "stamp_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8),
12075
+ x: cx,
12076
+ y: cy,
12077
+ width,
12078
+ height,
12079
+ fileId,
12080
+ customData,
12081
+ angle: 0,
12082
+ strokeColor: "transparent",
12083
+ backgroundColor: "transparent",
12084
+ fillStyle: "solid",
12085
+ strokeWidth: 1,
12086
+ strokeStyle: "solid",
12087
+ roughness: 0,
12088
+ opacity: 100,
12089
+ groupIds: [],
12090
+ roundness: null,
12091
+ seed: Math.floor(Math.random() * 1e9),
12092
+ versionNonce: 0,
12093
+ version: 1,
12094
+ isDeleted: false,
12095
+ boundElements: null,
12096
+ updated: Date.now(),
12097
+ link: null,
12098
+ locked: false,
12099
+ status: "saved",
12100
+ scale: [1, 1]
12101
+ };
12102
+ }
12103
+ async function insertStampImage(api, opts) {
12104
+ const { dataURL, fileId, width, height, mimeType } = await createStampFile(opts.svgString);
12105
+ api.addFiles([{ id: fileId, dataURL, mimeType, created: Date.now() }]);
12106
+ const customData = opts.makeCustomData();
12107
+ const elements = api.getSceneElements();
12108
+ const editingId = opts.editingElementId ?? null;
12109
+ if (editingId) {
12110
+ const old = opts.preserveExistingSize ? elements.find((e) => e.id === editingId) : void 0;
12111
+ const oldLongest = old ? Math.max(old.width ?? 0, old.height ?? 0) : 0;
12112
+ const newLongest = Math.max(width, height);
12113
+ const scale3 = oldLongest > 0 && newLongest > 0 ? oldLongest / newLongest : 1;
12114
+ const w = width * scale3;
12115
+ const h = height * scale3;
12116
+ const updated = elements.map(
12117
+ (e) => e.id === editingId ? { ...e, fileId, customData, width: w, height: h } : e
12118
+ );
12119
+ api.updateScene({ elements: updated, appState: clearAppStateAfterInsert() });
12120
+ return { fileId, width: w, height: h, elementId: editingId };
12121
+ }
12122
+ const newElement = buildStampImageElement(
12123
+ api,
12124
+ fileId,
12125
+ width,
12126
+ height,
12127
+ customData,
12128
+ opts.position?.x,
12129
+ opts.position?.y
12130
+ );
12131
+ api.updateScene({
12132
+ elements: [...elements, newElement],
12133
+ appState: clearAppStateAfterInsert()
12134
+ });
12135
+ return { fileId, width, height, elementId: newElement.id };
12136
+ }
12137
+ var clearAppStateAfterInsert;
12138
+ var init_insertImage = __esm({
12139
+ "src/stamps/shared/insertImage.ts"() {
12140
+ init_svgToStampFile();
12141
+ clearAppStateAfterInsert = () => ({
12142
+ selectedElementIds: {},
12143
+ croppingElementId: null
12144
+ });
12145
+ }
12146
+ });
12147
+
12148
+ // src/stamps/geometry-2d/host.tsx
12149
+ var host_exports = {};
12150
+ __export(host_exports, {
12151
+ GeometryStampHost: () => GeometryStampHost
12152
+ });
12153
+ var GeometryStampHost;
12154
+ var init_host = __esm({
12155
+ "src/stamps/geometry-2d/host.tsx"() {
12156
+ "use client";
12157
+ init_GeometryStudio();
12158
+ init_insertImage();
12159
+ init_types3();
12160
+ GeometryStampHost = React19.forwardRef(
12161
+ function GeometryStampHost2({ api, editingElement, onClose, isDark, generateGeometryFigure, onGeometryDraft }, ref) {
12162
+ const initialJsonState = isGeometryCustomData(editingElement?.customData) ? editingElement.customData.jsonState : void 0;
12163
+ const handleCommit = React19.useCallback(
12164
+ async (jsonState, svgString) => {
12165
+ if (!api) return false;
12166
+ await insertStampImage(api, {
12167
+ svgString,
12168
+ makeCustomData: () => ({
12169
+ kind: "geometry",
12170
+ version: 1,
12171
+ jsonState
12172
+ }),
12173
+ editingElementId: editingElement?.id ?? null,
12174
+ preserveExistingSize: true
12175
+ });
12176
+ return true;
12177
+ },
12178
+ [api, editingElement?.id]
12179
+ );
12180
+ return /* @__PURE__ */ jsxRuntime.jsx(
12181
+ GeometryStudio,
12182
+ {
12183
+ ref,
12184
+ initialJsonState,
12185
+ onCommit: handleCommit,
12186
+ onClose,
12187
+ isDark,
12188
+ api,
12189
+ generateGeometryFigure,
12190
+ onGeometryDraft
12191
+ }
12192
+ );
12193
+ }
12194
+ );
12195
+ }
12196
+ });
12197
+
12167
12198
  // src/stamps/latex/render.ts
12168
12199
  function absoluteOrigin() {
12169
12200
  if (typeof window !== "undefined" && window.location) return window.location.origin;
@@ -18479,7 +18510,7 @@ var host_exports3 = {};
18479
18510
  __export(host_exports3, {
18480
18511
  Geometry3DStampHost: () => Geometry3DStampHost
18481
18512
  });
18482
- function parseInitialState2(data) {
18513
+ function parseInitialState(data) {
18483
18514
  if (!isGeometry3DCustomData(data)) return null;
18484
18515
  return deserializeBoard3D(data.jsonState);
18485
18516
  }
@@ -18503,7 +18534,10 @@ var init_host3 = __esm({
18503
18534
  Geometry3DStampHost = React19.forwardRef(
18504
18535
  function Geometry3DStampHost2({ api, editingElement, onClose, isDark }, ref) {
18505
18536
  const editorRef = React19.useRef(null);
18506
- const sceneStore = useStampStore("3d", editingElement, parseInitialState2);
18537
+ const sceneStore = useStampStore(
18538
+ "3d",
18539
+ () => editingElement?.customData ? parseInitialState(editingElement.customData) : null
18540
+ );
18507
18541
  const { isMobile } = useIsMobile();
18508
18542
  const [drawerOpen, setDrawerOpen] = React19.useState(false);
18509
18543
  const [selectedTool, setSelectedTool] = React19.useState("move");
@@ -19736,7 +19770,7 @@ function makeRenderRow(store) {
19736
19770
  return null;
19737
19771
  };
19738
19772
  }
19739
- function parseInitialState3(data) {
19773
+ function parseInitialState2(data) {
19740
19774
  if (!isGraph2DCustomData(data)) return null;
19741
19775
  const state = parseSceneState(data.jsonState);
19742
19776
  if (!state) {
@@ -19768,7 +19802,10 @@ var init_host4 = __esm({
19768
19802
  const panelRef = React19.useRef(null);
19769
19803
  const { isMobile } = useIsMobile();
19770
19804
  const [drawerOpen, setDrawerOpen] = React19.useState(false);
19771
- const sceneStore = useStampStore("graph2d", editingElement, parseInitialState3);
19805
+ const sceneStore = useStampStore(
19806
+ "graph2d",
19807
+ () => editingElement?.customData ? parseInitialState2(editingElement.customData) : null
19808
+ );
19772
19809
  const [selectedObjectId, setSelectedObjectId] = React19.useState(void 0);
19773
19810
  const initialMeta = sceneStore.getState().meta;
19774
19811
  const initialView = initialMeta.domain === "graph2d" ? initialMeta.view : null;
@@ -22281,6 +22318,22 @@ function Whiteboard({
22281
22318
  ] });
22282
22319
  }
22283
22320
 
22321
+ // src/stamps/geometry-2d/insertGeometryStamp.ts
22322
+ init_render();
22323
+ init_insertImage();
22324
+ async function insertGeometryStampIntoScene(api, jsonState) {
22325
+ const svgString = await renderGeometrySvgFromState(jsonState);
22326
+ await insertStampImage(api, {
22327
+ svgString,
22328
+ makeCustomData: () => ({
22329
+ kind: "geometry",
22330
+ version: 1,
22331
+ jsonState
22332
+ }),
22333
+ editingElementId: null
22334
+ });
22335
+ }
22336
+
22284
22337
  // src/index.ts
22285
22338
  init_handleExtractProblem();
22286
22339
 
@@ -22298,6 +22351,7 @@ exports.geometry3dStamp = geometry3dStamp;
22298
22351
  exports.geometryStamp = geometryStamp;
22299
22352
  exports.graph2dStamp = graph2dStamp;
22300
22353
  exports.handleExtractProblem = handleExtractProblem;
22354
+ exports.insertGeometryStampIntoScene = insertGeometryStampIntoScene;
22301
22355
  exports.insertPdfPages = insertPdfPages;
22302
22356
  exports.insertRasterizedPagesIntoScene = insertRasterizedPagesIntoScene;
22303
22357
  exports.isStampElement = isStampElement;